1 /*********************************************************************************
\r
3 * --------------------------------------------------------------------------------
\r
5 * This file is part of MiMic
\r
6 * Copyright (C)2011 Ryo Iizuka
\r
8 * MiMic is free software: you can redistribute it and/or modify
\r
9 * it under the terms of the GNU Lesser General Public License as published
\r
10 * by the Free Software Foundation, either version 3 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU Lesser General Public License
\r
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
21 * For further information please contact.
\r
23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
25 *********************************************************************************/
\r
28 #include "NyLPC_cHttpHeaderWriter.h"
\r
29 #include "NyLPC_cHttpdConfig.h"
\r
33 * Httpリクエストヘッダに対応したHttpヘッダライタを構築します。
\r
35 NyLPC_TBool NyLPC_cHttpHeaderWriter_initialize(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TcHttpStream_t* i_ref_stream,const struct NyLPC_THttpBasicHeader* i_req_header)
\r
37 i_inst->_is_chunked=NyLPC_TUInt8_FALSE;
\r
38 i_inst->_content_length=0;
\r
39 i_inst->_ref_stream=i_ref_stream;
\r
40 i_inst->_is_error=NyLPC_TUInt8_FALSE;
\r
42 NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);
\r
43 //必要に応じてリクエストの内容をパース
\r
44 if(i_req_header!=NULL){
\r
45 if(i_req_header->type!=NyLPC_THttpHeaderType_REQUEST){
\r
46 return NyLPC_TBool_FALSE;
\r
49 if((i_req_header->connection==NyLPC_THttpMessgeHeader_Connection_CLOSE)||
\r
50 (i_req_header->startline.req.version!=NyLPC_THttpVersion_11))
\r
52 i_inst->_is_close=NyLPC_TUInt8_TRUE;
\r
54 i_inst->_is_close=NyLPC_TUInt8_FALSE;
\r
57 i_inst->_is_close=NyLPC_TUInt8_TRUE;
\r
59 return NyLPC_TBool_TRUE;
\r
62 #define NyLPC_cHttpHttpWriter_finalize(i)
\r
65 void NyLPC_cHttpHeaderWriter_setChunked(NyLPC_TcHttpHeaderWriter_t* i_inst)
\r
67 i_inst->_is_chunked=NyLPC_TUInt8_TRUE;
\r
70 void NyLPC_cHttpHeaderWriter_setContentLength(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt32 i_content_length)
\r
72 i_inst->_content_length=i_content_length;
\r
75 void NyLPC_cHttpHeaderWriter_setClose(NyLPC_TcHttpHeaderWriter_t* i_inst)
\r
77 i_inst->_is_close=NyLPC_TUInt8_TRUE;
\r
83 const static struct{
\r
85 const NyLPC_TChar* message;
\r
86 }status_line_tbl[]={
\r
88 {400,"Bad Request"},
\r
91 {405,"Method Not Allowed"},
\r
92 {500,"Internal Server Error"},
\r
95 const static char* getStatusMessage(NyLPC_TUInt16 i_status)
\r
98 while(status_line_tbl[i].code!=0){
\r
99 if(i_status==status_line_tbl[i].code){
\r
100 return status_line_tbl[i].message;
\r
107 static NyLPC_TBool writeln(NyLPC_TcHttpStream_t* i_inst,const void* i_data,NyLPC_TInt16 i_length)
\r
109 if(NyLPC_iHttpPtrStream_write(i_inst,i_data,i_length)){
\r
110 if(NyLPC_iHttpPtrStream_write(i_inst,"\r\n",2)){
\r
111 return NyLPC_TBool_TRUE;
\r
114 return NyLPC_TBool_FALSE;
\r
119 #define TIMEOUT 10*1000
\r
122 * ステータスラインと、標準メッセージヘッダを出力します。
\r
124 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status)
\r
127 const char* m=getStatusMessage(i_status);
\r
129 if(i_inst->_is_error){
\r
130 return NyLPC_TBool_FALSE;
\r
135 m=getStatusMessage(500);
\r
138 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"HTTP/1.1 ",9)){
\r
139 NyLPC_OnErrorGoto(Error);
\r
141 NyLPC_itoa(i_status,v,10);
\r
142 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){
\r
143 NyLPC_OnErrorGoto(Error);
\r
145 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){
\r
146 NyLPC_OnErrorGoto(Error);
\r
148 if(!writeln(i_inst->_ref_stream,m,-1)){
\r
149 NyLPC_OnErrorGoto(Error);
\r
151 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Server: " NyLPC_cHttpdConfig_SERVER "\r\n",-1)){
\r
152 NyLPC_OnErrorGoto(Error);
\r
154 if(i_inst->_is_close){
\r
155 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){
\r
156 NyLPC_OnErrorGoto(Error);
\r
160 if(i_inst->_is_chunked){
\r
161 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){
\r
162 NyLPC_OnErrorGoto(Error);
\r
165 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){
\r
166 NyLPC_OnErrorGoto(Error);
\r
168 NyLPC_itoa(i_inst->_content_length,v,10);
\r
169 if(!writeln(i_inst->_ref_stream,v,-1)){
\r
170 NyLPC_OnErrorGoto(Error);
\r
174 i_inst->_size_of_sent=0;
\r
175 return NyLPC_TBool_TRUE;
\r
177 i_inst->_is_error=NyLPC_TUInt8_FALSE;
\r
178 return NyLPC_TBool_FALSE;
\r
182 * 独自定義のメッセージヘッダを記述します。
\r
184 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_name,const NyLPC_TChar* i_field)
\r
187 if(i_inst->_is_error){
\r
188 return NyLPC_TBool_FALSE;
\r
190 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_name,-1)){
\r
191 NyLPC_OnErrorGoto(Error);
\r
193 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,": ",2)){
\r
194 NyLPC_OnErrorGoto(Error);
\r
196 if(!writeln(i_inst->_ref_stream,i_field,-1)){
\r
197 NyLPC_OnErrorGoto(Error);
\r
199 return NyLPC_TBool_TRUE;
\r
201 i_inst->_is_error=NyLPC_TUInt8_FALSE;
\r
202 return NyLPC_TBool_FALSE;
\r
206 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRawMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_additional_header)
\r
209 if(i_inst->_is_error){
\r
210 return NyLPC_TBool_FALSE;
\r
212 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_additional_header,strlen(i_additional_header))){
\r
213 NyLPC_OnErrorGoto(Error);
\r
215 return NyLPC_TBool_TRUE;
\r
217 i_inst->_is_error=NyLPC_TUInt8_FALSE;
\r
218 return NyLPC_TBool_FALSE;
\r
222 * Httpヘッダの書き込みを完了します。
\r
223 * 続けてbody転送が可能な場合は、必要に応じてエンコーディングモードを更新します。
\r
225 * 現在のストリームのステータスを返します。
\r
227 NyLPC_TBool NyLPC_cHttpHeaderWriter_close(NyLPC_TcHttpHeaderWriter_t* i_inst)
\r
230 if(i_inst->_is_error){
\r
231 return NyLPC_TBool_FALSE;
\r
233 if(NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"\r\n",2)){
\r
234 if( NyLPC_iHttpPtrStream_flush(i_inst->_ref_stream)){
\r
235 return NyLPC_TBool_TRUE;
\r
238 return NyLPC_TBool_FALSE;
\r