OSDN Git Service

iHttpPtrStream.pread関数にタイムアウト引数を追加
[mimic/MiMicSDK.git] / lib / src / http / NyLPC_cHttpBasicHeaderParser.c
1 /*********************************************************************************\r
2  * PROJECT: MiMic\r
3  * --------------------------------------------------------------------------------\r
4  *\r
5  * This file is part of MiMic\r
6  * Copyright (C)2011 Ryo Iizuka\r
7  *\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
12  *\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
17  *\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
20  *\r
21  * For further information please contact.\r
22  *      http://nyatla.jp/\r
23  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
24  *\r
25  *********************************************************************************/\r
26 #include "NyLPC_cHttpBasicHeaderParser_protected.h"\r
27 #include <stdlib.h>\r
28 \r
29 #define HTTP_TIMEOUT NyLPC_TiHttpPtrStream_DEFAULT_HTTP_TIMEOUT\r
30 \r
31 static const struct NyLPC_TTextIdTbl method_id_table[]=\r
32 {\r
33         //HTTP STANDARD\r
34         {"GET",NyLPC_THttpMethodType_GET},\r
35         {"POST",NyLPC_THttpMethodType_POST},\r
36         {"HEAD",NyLPC_THttpMethodType_HEAD},\r
37         //SSDP\r
38         {"M-SEARCH",NyLPC_THttpMethodType_M_SEARCH},\r
39         {"NOTIFY",NyLPC_THttpMethodType_NOTIFY},\r
40         {NULL,NyLPC_THttpMethodType_NULL}\r
41 };\r
42 /*--------------------------------------------------------------------------------\r
43  *\r
44  * NyLPC_THttpMethodType\r
45  *\r
46  --------------------------------------------------------------------------------*/\r
47 const char* NyLPC_THttpMethodType_toString(NyLPC_THttpMethodType i_method)\r
48 {\r
49         const char* ret=NyLPC_TTextIdTbl_getTextById(i_method,method_id_table);\r
50         if(ret==NULL){\r
51                 NyLPC_Abort();\r
52         }\r
53         return ret;\r
54 }\r
55 \r
56 static NyLPC_TBool parseRequestMethodStr(NyLPC_TcStr_t* i_str,NyLPC_THttpMethodType* o_out)\r
57 {\r
58         //解析処理\r
59         *o_out=NyLPC_TTextIdTbl_getMatchIdIgnoreCase(NyLPC_cStr_str(i_str),method_id_table);\r
60         if(*o_out==NyLPC_THttpMethodType_NULL){\r
61                 NyLPC_OnErrorGoto(ERROR);\r
62         }\r
63         return NyLPC_TBool_TRUE;\r
64 ERROR:\r
65         return NyLPC_TBool_FALSE;\r
66 }\r
67 /*--------------------------------------------------------------------------------\r
68  *\r
69  * NyLPC_THttpBasicHeader\r
70  *\r
71  --------------------------------------------------------------------------------*/\r
72 \r
73 NyLPC_TBool NyLPC_THttpBasicHeader_isPersistent(const struct NyLPC_THttpBasicHeader* i_struct)\r
74 {\r
75         switch(i_struct->type)\r
76         {\r
77         case NyLPC_THttpHeaderType_REQUEST:\r
78                 return (i_struct->connection!=NyLPC_THttpMessgeHeader_Connection_CLOSE)&&(i_struct->startline.req.version==NyLPC_THttpVersion_11);\r
79         case NyLPC_THttpHeaderType_RESPONSE:\r
80         default:\r
81                 break;\r
82         }\r
83         return NyLPC_TBool_FALSE;\r
84 }\r
85 \r
86 \r
87 \r
88 \r
89 \r
90 \r
91 \r
92 \r
93 /*\r
94         文字コードの定義\r
95 */\r
96 #define HTTP_SP 0x20\r
97 #define HTTP_LF 0x0A\r
98 #define HTTP_CR 0x0D\r
99 #define HTTP_DM ':' \r
100 \r
101 \r
102 \r
103 \r
104 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
105 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_ContentLength(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
106 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage1(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
107 static NyLPC_TcHttpBasicHeaderParser_ST parseVersion(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,NyLPC_TcHttpBasicHeaderParser_ST i_next,struct NyLPC_THttpBasicHeader* o_out);\r
108 static NyLPC_TcHttpBasicHeaderParser_ST parseRequestUrl(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
109 static NyLPC_TcHttpBasicHeaderParser_ST parseMessageParam(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
110 static NyLPC_TcHttpBasicHeaderParser_ST parseStartLine(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
111 static NyLPC_TcHttpBasicHeaderParser_ST parseStatusCode(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
112 static NyLPC_TcHttpBasicHeaderParser_ST parseReason(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c);\r
113 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_TransferEncoding(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);\r
114 \r
115 \r
116 static NyLPC_TBool parseHttpVersionStr(NyLPC_TcStr_t* i_str,NyLPC_THttpVersion* o_out);\r
117 static NyLPC_TBool parseRequestMethodStr(NyLPC_TcStr_t* i_str,NyLPC_THttpMethodType* o_out);\r
118 \r
119 static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error);\r
120 \r
121 \r
122 /**\r
123  * デフォルトハンドラ\r
124  */\r
125 static const struct NyLPC_TcHttpBasicHeaderParser_Handler _default_handler=\r
126 {\r
127         NULL,NULL\r
128 };\r
129 \r
130 \r
131 \r
132 /*----------------------------------------\r
133         Public/Protected関数\r
134 ----------------------------------------*/\r
135 \r
136 \r
137 void NyLPC_cHttpBasicHeaderParser_initialize(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const struct NyLPC_TcHttpBasicHeaderParser_Handler* i_handler)\r
138 {\r
139         NyLPC_cStr_initialize(&(i_inst->_wsb),i_inst->_wsb_buf,NyLPC_cHttpBasicHeaderParser_SIZE_OF_WBS);\r
140         i_inst->_handler=((i_handler==NULL)?&_default_handler:i_handler);\r
141 }\r
142 \r
143 /**\r
144  * parserの初期化\r
145  */\r
146 void NyLPC_cHttpBasicHeaderParser_parseInit(NyLPC_TcHttpBasicHeaderParser_t* i_inst,struct NyLPC_THttpBasicHeader* o_out)\r
147 {\r
148         //出力構造体を初期化\r
149         o_out->connection=NyLPC_THttpMessgeHeader_Connection_NONE;\r
150         o_out->content_length=NyLPC_THttpContentLength_INVALID_LENGTH;\r
151         o_out->transfer_encoding=NyLPC_THttpMessgeHeader_TransferEncoding_NONE;\r
152         i_inst->_st=NyLPC_TcHttpBasicHeaderParser_ST_START;\r
153 }\r
154 /**\r
155  * parseCharがNyLPC_TcHttpBasicHeaderParser_ST_EOHを返却したらコールすること。\r
156  */\r
157 NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parseFinish(NyLPC_TcHttpBasicHeaderParser_t* i_inst,struct NyLPC_THttpBasicHeader* o_out)\r
158 {\r
159         if(i_inst->_st!=NyLPC_TcHttpBasicHeaderParser_ST_EOH)\r
160         {\r
161                 return NyLPC_TBool_FALSE;\r
162         }\r
163         //整合性チェック\r
164         if(!testHeader(o_out,&i_inst->_rcode)){\r
165                 i_inst->_st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
166                 return NyLPC_TBool_FALSE;\r
167         }\r
168         return NyLPC_TBool_TRUE;\r
169 }\r
170 /**\r
171  * 文字列をパースします。\r
172  * コール前にNyLPC_cHttpBasicHeaderParser_parseInitでパーサを開始してください。\r
173  * @return\r
174  * パースした文字列の長さ。-1の場合はエラー。\r
175  * TRUEの場合、NyLPC_cHttpBasicHeaderParser_getParseStatus関数で状態をチェックして、後続の処理を選択してください。\r
176  */\r
177 NyLPC_TInt32 NyLPC_cHttpBasicHeaderParser_parseChar(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const NyLPC_TChar* i_c,NyLPC_TInt32 i_size,struct NyLPC_THttpBasicHeader* o_out)\r
178 {\r
179         int i;\r
180         NyLPC_TChar c;\r
181         //Errorチェック\r
182         if(NyLPC_TcHttpBasicHeaderParser_ST_ERROR==i_inst->_st)\r
183         {\r
184                 return 0;\r
185         }\r
186         for(i=0;i<i_size;i++){\r
187                 c=*(i_c+i);\r
188                 switch(i_inst->_st)\r
189                 {\r
190                 case NyLPC_TcHttpBasicHeaderParser_ST_START:\r
191                         i_inst->_st=parseStartLine(i_inst,c,o_out);\r
192                         break;\r
193                 case NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM:\r
194                         i_inst->_st=parseMessageParam(i_inst,c,o_out);\r
195                         break;\r
196                 case NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD:\r
197                         i_inst->_st=parseMessage1(i_inst,c,o_out);\r
198                         break;\r
199                 case NyLPC_TcHttpBasicHeaderParser_ST_RL_URL:\r
200                         i_inst->_st=parseRequestUrl(i_inst,c,o_out);\r
201                         break;\r
202                 case NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION:\r
203                         i_inst->_st=parseVersion(i_inst,c,NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD,o_out);\r
204                         break;\r
205                 case NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE:\r
206                         i_inst->_st=parseStatusCode(i_inst,c,o_out);\r
207                         break;\r
208                 case NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON:\r
209                         i_inst->_st=parseReason(i_inst,c);\r
210                         break;\r
211                 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH:\r
212                         i_inst->_st=parseMessage_ContentLength(i_inst,c,o_out);\r
213                         break;\r
214                 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION:\r
215                         i_inst->_st=parseMessage_Connection(i_inst,c,o_out);\r
216                         break;\r
217                 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING:\r
218                         i_inst->_st=parseMessage_TransferEncoding(i_inst,c,o_out);\r
219                         break;\r
220                 default:\r
221                         i_inst->_rcode=500;\r
222                         i_inst->_st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
223                 }\r
224                 if(NyLPC_TcHttpBasicHeaderParser_ST_isError(i_inst->_st)){\r
225                         //エラー起こしたら終了。\r
226                         return i;\r
227                 }else if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){\r
228                         //ヘッダ終端なら終了。\r
229                         return i+1;\r
230                 }\r
231         }\r
232         return i_size;\r
233 }\r
234 \r
235 \r
236 \r
237 /**\r
238  * ストリームから読み出して、パースします。\r
239  * コール前にNyLPC_cHttpBasicHeaderParser_parseInitでパーサを開始してください。\r
240  * @return\r
241  * FALSE-失敗/TRUE-成功\r
242  * 関数が成功した場合、NyLPC_cHttpBasicHeaderParser_parseFinishでパーサを閉じることが出来ます。\r
243  */\r
244 NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parseStream(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TiHttpPtrStream_t* i_stream,struct NyLPC_THttpBasicHeader* o_out)\r
245 {\r
246         const char* rp_base;\r
247         NyLPC_TInt32 rsize;\r
248         for(;;){\r
249                 //タイムアウト付でストリームから読み出し。\r
250                 rsize=NyLPC_iHttpPtrStream_pread(i_stream,(const void**)(&rp_base),HTTP_TIMEOUT);\r
251                 if(rsize<=0){\r
252                         return NyLPC_TBool_FALSE;\r
253                 }\r
254                 rsize=NyLPC_cHttpBasicHeaderParser_parseChar(i_inst,rp_base,rsize,o_out);\r
255                 if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_ERROR){\r
256                         //パース失敗\r
257                         NyLPC_iHttpPtrStream_rseek(i_stream,rsize);\r
258                         return NyLPC_TBool_FALSE;\r
259                 }\r
260                 if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){\r
261                         //パース成功\r
262                         NyLPC_iHttpPtrStream_rseek(i_stream,rsize);\r
263                         return NyLPC_TBool_TRUE;\r
264                 }\r
265                 NyLPC_iHttpPtrStream_rseek(i_stream,(NyLPC_TUInt16)rsize);\r
266         }\r
267         return NyLPC_TBool_FALSE;\r
268 }\r
269 \r
270 \r
271 ///**\r
272 // * ストリームから読み出して、パースします。\r
273 // */\r
274 //NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parse(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TcHttpStream_t* i_stream,struct NyLPC_THttpBasicHeader* o_out)\r
275 //{\r
276 //      NyLPC_TcHttpBasicHeaderParser_ST st;\r
277 //      const char* rp_base;\r
278 //      NyLPC_TInt32 rsize;\r
279 //      char c;\r
280 //      int i;\r
281 //\r
282 //      //出力構造体を初期化\r
283 //      st=NyLPC_TcHttpBasicHeaderParser_ST_START;\r
284 //      o_out->connection=NyLPC_THttpMessgeHeader_Connection_NONE;\r
285 //      o_out->content_length=NyLPC_THttpContentLength_INVALID_LENGTH;\r
286 //      o_out->transfer_encoding=NyLPC_THttpMessgeHeader_TransferEncoding_NONE;\r
287 //\r
288 //      for(;;){\r
289 //              //タイムアウト付でストリームから読み出し。\r
290 //              rsize=NyLPC_iHttpPtrStream_pread(i_stream,(const void**)(&rp_base));\r
291 //              if(rsize<=0){\r
292 //                      return NyLPC_TBool_FALSE;\r
293 //              }\r
294 //              for(i=0;i<rsize;i++){\r
295 //                      c=*(rp_base+i);\r
296 //                      switch(st)\r
297 //                      {\r
298 //                      case NyLPC_TcHttpBasicHeaderParser_ST_START:\r
299 //                              st=parseStartLine(i_inst,c,o_out);\r
300 //                              break;\r
301 //                      case NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM:\r
302 //                              st=parseMessageParam(i_inst,c,o_out);\r
303 //                              break;\r
304 //                      case NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD:\r
305 //                              st=parseMessage1(i_inst,c,o_out);\r
306 //                              break;\r
307 //                      case NyLPC_TcHttpBasicHeaderParser_ST_RL_URL:\r
308 //                              st=parseRequestUrl(i_inst,c,o_out);\r
309 //                              break;\r
310 //                      case NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION:\r
311 //                              st=parseVersion(i_inst,c,NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD,o_out);\r
312 //                              break;\r
313 //                      case NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE:\r
314 //                              st=parseStatusCode(i_inst,c,o_out);\r
315 //                              break;\r
316 //                      case NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON:\r
317 //                              st=parseReason(i_inst,c);\r
318 //                              break;\r
319 //                      case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH:\r
320 //                              st=parseMessage_ContentLength(i_inst,c,o_out);\r
321 //                              break;\r
322 //                      case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION:\r
323 //                              st=parseMessage_Connection(i_inst,c,o_out);\r
324 //                              break;\r
325 //                      case NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING:\r
326 //                              st=parseMessage_TransferEncoding(i_inst,c,o_out);\r
327 //                              break;\r
328 //                      default:\r
329 //                              i_inst->_rcode=500;\r
330 //                              st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
331 //                      }\r
332 //                      //エラー起こしたら終了。\r
333 //                      if(NyLPC_TcHttpBasicHeaderParser_ST_isError(st)){\r
334 //                              return NyLPC_TBool_FALSE;\r
335 //                      }\r
336 //                      //パース成功\r
337 //                      if(st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){\r
338 //                              //整合性チェック\r
339 //                              if(!testHeader(o_out,&i_inst->_rcode)){\r
340 //                                      st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
341 //                                      return NyLPC_TBool_FALSE;\r
342 //                              }\r
343 //                              //シーク\r
344 //                              NyLPC_iHttpPtrStream_rseek(i_stream,i+1);\r
345 //                              return NyLPC_TBool_TRUE;\r
346 //                      }\r
347 //              }\r
348 //              //シーク\r
349 //              NyLPC_iHttpPtrStream_rseek(i_stream,(NyLPC_TUInt16)rsize);\r
350 //      }\r
351 //      return NyLPC_TBool_FALSE;\r
352 //}\r
353 \r
354 \r
355 \r
356 /*----------------------------------------\r
357         private関数\r
358 ----------------------------------------*/\r
359 /**\r
360 ヘッダの整合性をとる。\r
361 */\r
362 static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error)\r
363 {\r
364         switch(i_header->startline.req.version){\r
365         case NyLPC_THttpVersion_09:\r
366                 if(i_header->type==NyLPC_THttpHeaderType_REQUEST){\r
367                         //Requestの時だけmethodチェック\r
368                         //GETだけ\r
369                         if(i_header->startline.req.method!=NyLPC_THttpMethodType_GET){\r
370                                 *o_error=400;\r
371                                 break;\r
372                         }\r
373                 }\r
374                 //TEは受け付けない。\r
375                 if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){\r
376                         *o_error=400;\r
377                         break;\r
378                 }\r
379                 //ContentLength=0,Connection=Closedに修正。\r
380                 i_header->content_length=0;\r
381                 i_header->connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;\r
382                 return NyLPC_TBool_TRUE;\r
383         case NyLPC_THttpVersion_10:\r
384                 //TEは受け付けない。\r
385                 if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){\r
386                         *o_error=406;\r
387                         break;\r
388                 }\r
389                 //ContentLengthが無いときは0\r
390                 if(i_header->content_length==NyLPC_THttpContentLength_INVALID_LENGTH){\r
391                         i_header->content_length=0;\r
392                 }\r
393                 //Connection=Closedに修正。(1.0のKeepaliveは難しいから無視)\r
394                 i_header->connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;\r
395                 return NyLPC_TBool_TRUE;\r
396         case NyLPC_THttpVersion_11:\r
397                 if(i_header->content_length==NyLPC_THttpContentLength_INVALID_LENGTH){\r
398                         //Contentlength無しのChunked指定はOK\r
399                         if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_CHUNKED){\r
400                                 //Chunkedが無い場合はContent-Lengthは0と仮定\r
401                                 i_header->content_length=0;\r
402                         }else{\r
403                                 //content-length無し && Chunked有\r
404                                 //OK\r
405                         }\r
406                 }else if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){\r
407                         //ContentLengthあるのにChunkedとは何事\r
408                         *o_error=400;\r
409                         break;\r
410                 }\r
411                 return NyLPC_TBool_TRUE;\r
412         case NyLPC_THttpVersion_UNKNOWN:\r
413                 //おい馬鹿やめろ\r
414                 *o_error=505;\r
415                 break;\r
416         default:\r
417                 *o_error=500;\r
418                 break;\r
419         }\r
420         return NyLPC_TBool_FALSE;\r
421 }\r
422 \r
423 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_TransferEncoding(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
424 {\r
425 \r
426         //先頭のスペース除外\r
427         if(NyLPC_cStr_len(&(i_inst->_wsb))==0){\r
428                 if(i_c==HTTP_SP){\r
429                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし\r
430                 }\r
431         }\r
432         if(i_c==HTTP_CR){\r
433                 //CRの無視\r
434                 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし\r
435         }else if(i_c==HTTP_LF){\r
436                 //大文字化\r
437                 NyLPC_cStr_toUpper(&(i_inst->_wsb));\r
438                 //close?\r
439                 o_out->transfer_encoding=NyLPC_cStr_isEqual(&(i_inst->_wsb),"CHUNKED")?NyLPC_THttpMessgeHeader_TransferEncoding_CHUNKED:NyLPC_THttpMessgeHeader_TransferEncoding_UNKNOWN;\r
440                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
441                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;\r
442         }\r
443         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
444                 i_inst->_rcode=500;\r
445                 NyLPC_OnErrorGoto(Error);\r
446         }\r
447         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし;\r
448 Error:\r
449         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
450 }\r
451 \r
452 \r
453 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
454 {\r
455         const static NyLPC_TUInt8 id[]={\r
456                 NyLPC_THttpMessgeHeader_Connection_CLOSE,\r
457                 NyLPC_THttpMessgeHeader_Connection_KEEPALIVE,\r
458                 NyLPC_THttpMessgeHeader_Connection_UPGRADE,\r
459                 NyLPC_THttpMessgeHeader_Connection_UNKNOWN\r
460         };\r
461         const static NyLPC_TChar* str[]={\r
462                 "CLOSE",\r
463                 "KEEP-ALIVE",\r
464                 "UPGRADE"\r
465         };\r
466         NyLPC_TUInt8 i;\r
467         //先頭のスペース除外\r
468         if(NyLPC_cStr_len(&(i_inst->_wsb))==0){\r
469                 if(i_c==HTTP_SP){\r
470                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし\r
471                 }\r
472         }\r
473         if(i_c==HTTP_CR){\r
474                 //CRの無視\r
475                 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし\r
476         }else if(i_c==HTTP_LF){\r
477                 //大文字化\r
478                 NyLPC_cStr_toUpper(&(i_inst->_wsb));\r
479                 //Convert to ID\r
480                 o_out->connection=NyLPC_THttpMessgeHeader_Connection_UNKNOWN;\r
481                 for(i=0;id[i]!=NyLPC_THttpMessgeHeader_Connection_UNKNOWN;i++){\r
482                         if(NyLPC_cStr_isEqual(&(i_inst->_wsb),str[i])){\r
483                                 o_out->connection=id[i];\r
484                                 break;\r
485                         }\r
486                 }\r
487                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
488                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;\r
489         }\r
490         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
491                 i_inst->_rcode=500;\r
492                 NyLPC_OnErrorGoto(Error);\r
493         }\r
494         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし;\r
495 Error:\r
496         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
497 }\r
498 \r
499 \r
500 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_ContentLength(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
501 {\r
502         char* e;\r
503         char* p;\r
504 \r
505         //先頭のスペース除外\r
506         if(NyLPC_cStr_len(&(i_inst->_wsb))==0)\r
507         {\r
508                 if(i_c==HTTP_SP){\r
509                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし\r
510                 }\r
511         }\r
512         if(i_c==HTTP_CR){\r
513                 //CRの無視\r
514                 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし\r
515         }else if(i_c==HTTP_LF){\r
516                 p=NyLPC_cStr_str(&(i_inst->_wsb));\r
517                 o_out->content_length=strtol(p,&e,10);\r
518                 if(e==p){\r
519                         i_inst->_rcode=400;\r
520                         NyLPC_OnErrorGoto(Error);//ギャー\r
521                 }\r
522                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
523                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;\r
524         }\r
525         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
526                 i_inst->_rcode=500;\r
527                 NyLPC_OnErrorGoto(Error);\r
528         }\r
529         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし;\r
530 Error:\r
531         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
532 }\r
533 \r
534 static NyLPC_TcHttpBasicHeaderParser_ST parseStatusCode(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
535 {\r
536         NyLPC_TcStr_t* ws=&(i_inst->_wsb);\r
537         char* e;\r
538         char* p;\r
539 \r
540         //先頭のスペース除外\r
541         if(NyLPC_cStr_len(ws)==0)\r
542         {\r
543                 if(i_c==HTTP_SP){\r
544                         return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし\r
545                 }\r
546         }\r
547         if(i_c==HTTP_SP){\r
548         //SPで終了\r
549                 p=NyLPC_cStr_str(ws);\r
550                 o_out->startline.res.status=(strtol(p,&e,10));\r
551                 if(e==p){\r
552                         i_inst->_rcode=400;\r
553                         NyLPC_OnErrorGoto(Error);//ギャー\r
554                 }\r
555                 NyLPC_cStr_clear(ws);\r
556                 return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;\r
557         }\r
558         if(!NyLPC_cStr_put(ws,i_c)){\r
559                 i_inst->_rcode=500;\r
560                 NyLPC_OnErrorGoto(Error);\r
561         }\r
562         return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし;\r
563 Error:\r
564         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
565 }\r
566 static NyLPC_TcHttpBasicHeaderParser_ST parseReason(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c)\r
567 {\r
568         NyLPC_TcStr_t* ws=&(i_inst->_wsb);\r
569         //LFくるまで飛ばす。\r
570         switch(i_c){\r
571         case HTTP_LF:\r
572                 NyLPC_cStr_clear(ws);\r
573                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;\r
574         default:\r
575                 break;\r
576         }\r
577         //URLパーサへ通知\r
578         return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;//変化なし\r
579 }\r
580 static NyLPC_TcHttpBasicHeaderParser_ST parseMessageParam(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
581 {\r
582         NyLPC_TcStr_t* ws=&(i_inst->_wsb);\r
583         //先頭のスペース除外\r
584         if(NyLPC_cStr_len(ws)==0){\r
585                 if(i_c==HTTP_SP){\r
586                         return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし\r
587                 }else{\r
588                         NyLPC_cStr_put(ws,'C');//開始フラグ\r
589                 }\r
590         }\r
591         switch(i_c){\r
592         case HTTP_CR:\r
593                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし\r
594         case HTTP_LF:\r
595                 //メッセージフィールドの終端を通知\r
596                 if(i_inst->_handler->messageHandler!=NULL){\r
597                         if(!i_inst->_handler->messageHandler(i_inst,NULL,0,o_out)){\r
598                                 i_inst->_rcode=500;\r
599                                 NyLPC_OnErrorGoto(Error);\r
600                         }\r
601                 }\r
602                 NyLPC_cStr_clear(ws);\r
603                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;\r
604         default:\r
605                 //メッセージフィールドの追記\r
606                 if(i_inst->_handler->messageHandler!=NULL){\r
607                         if(!i_inst->_handler->messageHandler(i_inst,NULL,i_c,o_out)){\r
608                                 i_inst->_rcode=500;\r
609                                 NyLPC_OnErrorGoto(Error);\r
610                         }\r
611                 }\r
612                 break;\r
613         }\r
614         //URLパーサへ通知\r
615         return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし\r
616 Error:\r
617         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
618 }\r
619 \r
620 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage1(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
621 {\r
622         const static char* KNOWN_MSG[]={"CONNECTION","CONTENT-LENGTH","TRANSFER-ENCODING",NULL};\r
623         int i;\r
624 \r
625         switch(i_c){\r
626         case HTTP_DM:\r
627         //メッセージの名前確定。遷移先判定\r
628                 //ヘッダ名を大文字にする。\r
629                 NyLPC_cStr_toUpper(&(i_inst->_wsb));\r
630                 for(i=0;KNOWN_MSG[i]!=NULL;i++){\r
631                         if(NyLPC_cStr_isEqual(&(i_inst->_wsb),KNOWN_MSG[i])){\r
632                                 //確定。\r
633                                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
634                                 switch(i){\r
635                                 case 0://CONNECTION\r
636                                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;\r
637                                 case 1://CONTENT-LENGTH\r
638                                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;\r
639                                 case 2://TRANSFER-ENCODING\r
640                                         return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;\r
641                                 default://エラー\r
642                                         break;\r
643                                 }\r
644                                 i_inst->_rcode=500;\r
645                                 NyLPC_OnErrorGoto(Error);\r
646                         }\r
647                 }\r
648                 //メッセージフィールドの名前を通知\r
649                 if(i_inst->_handler->messageHandler!=NULL){\r
650                         if(!i_inst->_handler->messageHandler(i_inst,NyLPC_cStr_str(&(i_inst->_wsb)),0,o_out)){\r
651                                 i_inst->_rcode=500;\r
652                                 NyLPC_OnErrorGoto(Error);\r
653                         }\r
654                         NyLPC_cStr_clear(&(i_inst->_wsb));\r
655                 }\r
656                 //カスタムヘッダ解析へ。\r
657                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;\r
658         case HTTP_CR:\r
659                 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし\r
660         case HTTP_LF:\r
661                 //1文字で終了ならパースエンド。バリデーションチェックへ\r
662                 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){\r
663                         NyLPC_cStr_clear(&(i_inst->_wsb));\r
664                         return NyLPC_TcHttpBasicHeaderParser_ST_EOH;\r
665                 }\r
666                 //これはひどい。\r
667                 i_inst->_rcode=400;\r
668                 NyLPC_OnErrorGoto(Error);\r
669         default:\r
670                 break;\r
671         }\r
672         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
673                 i_inst->_rcode=500;\r
674                 NyLPC_OnErrorGoto(Error);\r
675         }\r
676         return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし;\r
677 Error:\r
678         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
679 }\r
680 \r
681 static NyLPC_TcHttpBasicHeaderParser_ST parseVersion(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,NyLPC_TcHttpBasicHeaderParser_ST i_next,struct NyLPC_THttpBasicHeader* o_out)\r
682 {\r
683         //先頭のスペース除外\r
684         if(NyLPC_cStr_len(&(i_inst->_wsb))==0){\r
685                 if(i_c==HTTP_SP){\r
686                         return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし\r
687                 }\r
688         }\r
689         if(i_c==HTTP_CR){\r
690         //CRの無視\r
691                 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし\r
692         }else if(i_c==HTTP_LF){\r
693         //LFで確定\r
694                 if(!parseHttpVersionStr(&(i_inst->_wsb),&(o_out->startline.req.version))){\r
695                         i_inst->_rcode=505;\r
696                         NyLPC_cStr_clear(&(i_inst->_wsb));\r
697                         NyLPC_OnErrorGoto(Error);\r
698                 }\r
699                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
700                 return i_next;//遷移(エラーの時はそのままエラーコードが渡る。)\r
701         }\r
702         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
703                 //追記処理しっぱい\r
704                 i_inst->_rcode=500;\r
705                 NyLPC_OnErrorGoto(Error);\r
706         }\r
707         return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし\r
708 Error:\r
709         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
710 }\r
711 \r
712 /**\r
713 URLパーサ。登録した関数に転送する?\r
714 */\r
715 static NyLPC_TcHttpBasicHeaderParser_ST parseRequestUrl(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
716 {\r
717         //先頭のスペース除外\r
718         if(NyLPC_cStr_len(&(i_inst->_wsb))==0){\r
719                 if(i_c==HTTP_SP){\r
720                         return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし\r
721                 }else{\r
722                         NyLPC_cStr_put(&(i_inst->_wsb),'C');//開始フラグ\r
723                 }\r
724         }\r
725         //次のスペースがくるまで。\r
726         if(i_c==HTTP_SP){\r
727                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
728                 //URLハンドラへ通知\r
729                 if(i_inst->_handler->urlHandler!=NULL){\r
730                         if(!i_inst->_handler->urlHandler(i_inst,0,o_out)){\r
731                                 i_inst->_rcode=500;\r
732                                 NyLPC_OnErrorGoto(Error);\r
733                         }\r
734                 }\r
735                 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;\r
736         }\r
737         //URLパーサへ通知\r
738         if(i_inst->_handler->urlHandler!=NULL){\r
739                 if(!i_inst->_handler->urlHandler(i_inst,i_c,o_out)){\r
740                         i_inst->_rcode=500;\r
741                         NyLPC_OnErrorGoto(Error);\r
742                 }\r
743         }\r
744         return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし\r
745 Error:\r
746         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
747 }\r
748 \r
749 /**\r
750 Methodパーサ\r
751         [:HTTPMETHOD:]を得る。\r
752 */\r
753 static NyLPC_TcHttpBasicHeaderParser_ST parseStartLine(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)\r
754 {\r
755         if(i_c==HTTP_SP){\r
756         //SPがデリミタ\r
757                 //HTTPステータスを試す。\r
758                 if(parseHttpVersionStr(&(i_inst->_wsb),&(o_out->startline.res.version))){\r
759                         //これはHTTPステータス\r
760                         o_out->type=NyLPC_THttpHeaderType_RESPONSE;\r
761                         NyLPC_cStr_clear(&(i_inst->_wsb));\r
762                         return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;\r
763                 }\r
764                 //HTTPリクエストを試す。\r
765                 if(!parseRequestMethodStr(&(i_inst->_wsb),&(o_out->startline.req.method))){\r
766                         i_inst->_rcode=400;\r
767                         NyLPC_OnErrorGoto(ERROR);\r
768                 }\r
769                 //これはHTTPリクエスト\r
770                 o_out->type=NyLPC_THttpHeaderType_REQUEST;\r
771                 NyLPC_cStr_clear(&(i_inst->_wsb));\r
772                 return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;\r
773         }\r
774         if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){\r
775                 i_inst->_rcode=500;\r
776                 NyLPC_OnErrorGoto(ERROR);\r
777         }\r
778         return NyLPC_TcHttpBasicHeaderParser_ST_START;//変化なし\r
779 ERROR:\r
780         return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;\r
781 }\r
782 \r
783 \r
784 \r
785 \r
786 \r
787 static NyLPC_TBool parseHttpVersionStr(NyLPC_TcStr_t* i_str,NyLPC_THttpVersion* o_out)\r
788 {\r
789         NyLPC_TChar* p;\r
790         char* e;\r
791         long ma,mi;\r
792 \r
793         p=NyLPC_cStr_str(i_str);\r
794         if(NyLPC_cStr_len(i_str)<6){\r
795                 NyLPC_OnErrorGoto(Error);\r
796         }\r
797         if(strncmp(p,"HTTP/",5)!=0){\r
798                 NyLPC_OnErrorGoto(Error);\r
799         }\r
800         p+=5;\r
801         ma=strtol(p,&e,10);\r
802         if(p==e){\r
803                 NyLPC_OnErrorGoto(Error);\r
804         }\r
805         p=e;//.をチェック\r
806         if(*p!='.'){\r
807                 NyLPC_OnErrorGoto(Error);\r
808         }\r
809         p++;\r
810         mi=strtoul(p,&e,10);\r
811         if(p==e){\r
812                 NyLPC_OnErrorGoto(Error);\r
813         }\r
814         if(ma<0 ||mi<0){\r
815                 NyLPC_OnErrorGoto(Error);\r
816         }\r
817         switch(ma){\r
818         case 0:\r
819                 if(mi>=9){\r
820                         //HTTP0.9相当\r
821                         *o_out=NyLPC_THttpVersion_09;\r
822                 }\r
823                 break;\r
824         case 1:\r
825                 if(mi==0){\r
826                         //HTTP1.0\r
827                         *o_out=NyLPC_THttpVersion_10;\r
828                 }else if(mi>=1){\r
829                         //HTTP1.1\r
830                         *o_out=NyLPC_THttpVersion_11;\r
831                 }else{\r
832                         *o_out=NyLPC_THttpVersion_UNKNOWN;\r
833                 }\r
834                 break;\r
835         default:\r
836                 //お前など知らん\r
837                 *o_out=NyLPC_THttpVersion_UNKNOWN;\r
838                 break;\r
839         }\r
840         return NyLPC_TBool_TRUE;//変化なし\r
841 Error:\r
842         return NyLPC_TBool_FALSE;\r
843 }\r
844 \r