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
26 #include "NyLPC_cHttpBasicHeaderParser_protected.h"
\r
29 #define HTTP_TIMEOUT NyLPC_TiHttpPtrStream_DEFAULT_HTTP_TIMEOUT
\r
31 static const struct NyLPC_TTextIdTbl method_id_table[]=
\r
34 {"GET",NyLPC_THttpMethodType_GET},
\r
35 {"POST",NyLPC_THttpMethodType_POST},
\r
36 {"HEAD",NyLPC_THttpMethodType_HEAD},
\r
38 {"M-SEARCH",NyLPC_THttpMethodType_M_SEARCH},
\r
39 {"NOTIFY",NyLPC_THttpMethodType_NOTIFY},
\r
40 {NULL,NyLPC_THttpMethodType_NULL}
\r
42 /*--------------------------------------------------------------------------------
\r
44 * NyLPC_THttpMethodType
\r
46 --------------------------------------------------------------------------------*/
\r
47 const char* NyLPC_THttpMethodType_toString(NyLPC_THttpMethodType i_method)
\r
49 const char* ret=NyLPC_TTextIdTbl_getTextById(i_method,method_id_table);
\r
56 static NyLPC_TBool parseRequestMethodStr(NyLPC_TcStr_t* i_str,NyLPC_THttpMethodType* o_out)
\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
63 return NyLPC_TBool_TRUE;
\r
65 return NyLPC_TBool_FALSE;
\r
67 /*--------------------------------------------------------------------------------
\r
69 * NyLPC_THttpBasicHeader
\r
71 --------------------------------------------------------------------------------*/
\r
73 NyLPC_TBool NyLPC_THttpBasicHeader_isPersistent(const struct NyLPC_THttpBasicHeader* i_struct)
\r
75 switch(i_struct->type)
\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
83 return NyLPC_TBool_FALSE;
\r
96 #define HTTP_SP 0x20
\r
97 #define HTTP_LF 0x0A
\r
98 #define HTTP_CR 0x0D
\r
99 #define HTTP_DM ':'
\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
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
119 static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error);
\r
125 static const struct NyLPC_TcHttpBasicHeaderParser_Handler _default_handler=
\r
132 /*----------------------------------------
\r
134 ----------------------------------------*/
\r
137 void NyLPC_cHttpBasicHeaderParser_initialize(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const struct NyLPC_TcHttpBasicHeaderParser_Handler* i_handler)
\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
146 void NyLPC_cHttpBasicHeaderParser_parseInit(NyLPC_TcHttpBasicHeaderParser_t* i_inst,struct NyLPC_THttpBasicHeader* o_out)
\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
155 * parseCharがNyLPC_TcHttpBasicHeaderParser_ST_EOHを返却したらコールすること。
\r
157 NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parseFinish(NyLPC_TcHttpBasicHeaderParser_t* i_inst,struct NyLPC_THttpBasicHeader* o_out)
\r
159 if(i_inst->_st!=NyLPC_TcHttpBasicHeaderParser_ST_EOH)
\r
161 return NyLPC_TBool_FALSE;
\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
168 return NyLPC_TBool_TRUE;
\r
172 * コール前にNyLPC_cHttpBasicHeaderParser_parseInitでパーサを開始してください。
\r
174 * パースした文字列の長さ。-1の場合はエラー。
\r
175 * TRUEの場合、NyLPC_cHttpBasicHeaderParser_getParseStatus関数で状態をチェックして、後続の処理を選択してください。
\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
182 if(NyLPC_TcHttpBasicHeaderParser_ST_ERROR==i_inst->_st)
\r
186 for(i=0;i<i_size;i++){
\r
188 switch(i_inst->_st)
\r
190 case NyLPC_TcHttpBasicHeaderParser_ST_START:
\r
191 i_inst->_st=parseStartLine(i_inst,c,o_out);
\r
193 case NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM:
\r
194 i_inst->_st=parseMessageParam(i_inst,c,o_out);
\r
196 case NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD:
\r
197 i_inst->_st=parseMessage1(i_inst,c,o_out);
\r
199 case NyLPC_TcHttpBasicHeaderParser_ST_RL_URL:
\r
200 i_inst->_st=parseRequestUrl(i_inst,c,o_out);
\r
202 case NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION:
\r
203 i_inst->_st=parseVersion(i_inst,c,NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD,o_out);
\r
205 case NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE:
\r
206 i_inst->_st=parseStatusCode(i_inst,c,o_out);
\r
208 case NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON:
\r
209 i_inst->_st=parseReason(i_inst,c);
\r
211 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH:
\r
212 i_inst->_st=parseMessage_ContentLength(i_inst,c,o_out);
\r
214 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION:
\r
215 i_inst->_st=parseMessage_Connection(i_inst,c,o_out);
\r
217 case NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING:
\r
218 i_inst->_st=parseMessage_TransferEncoding(i_inst,c,o_out);
\r
221 i_inst->_rcode=500;
\r
222 i_inst->_st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
224 if(NyLPC_TcHttpBasicHeaderParser_ST_isError(i_inst->_st)){
\r
227 }else if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){
\r
238 * ストリームから読み出して、パースします。
\r
239 * コール前にNyLPC_cHttpBasicHeaderParser_parseInitでパーサを開始してください。
\r
242 * 関数が成功した場合、NyLPC_cHttpBasicHeaderParser_parseFinishでパーサを閉じることが出来ます。
\r
244 NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parseStream(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TiHttpPtrStream_t* i_stream,struct NyLPC_THttpBasicHeader* o_out)
\r
246 const char* rp_base;
\r
247 NyLPC_TInt32 rsize;
\r
249 //タイムアウト付でストリームから読み出し。
\r
250 rsize=NyLPC_iHttpPtrStream_pread(i_stream,(const void**)(&rp_base),HTTP_TIMEOUT);
\r
252 return NyLPC_TBool_FALSE;
\r
254 rsize=NyLPC_cHttpBasicHeaderParser_parseChar(i_inst,rp_base,rsize,o_out);
\r
255 if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_ERROR){
\r
257 NyLPC_iHttpPtrStream_rseek(i_stream,rsize);
\r
258 return NyLPC_TBool_FALSE;
\r
260 if(i_inst->_st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){
\r
262 NyLPC_iHttpPtrStream_rseek(i_stream,rsize);
\r
263 return NyLPC_TBool_TRUE;
\r
265 NyLPC_iHttpPtrStream_rseek(i_stream,(NyLPC_TUInt16)rsize);
\r
267 return NyLPC_TBool_FALSE;
\r
272 // * ストリームから読み出して、パースします。
\r
274 //NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parse(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TcHttpStream_t* i_stream,struct NyLPC_THttpBasicHeader* o_out)
\r
276 // NyLPC_TcHttpBasicHeaderParser_ST st;
\r
277 // const char* rp_base;
\r
278 // NyLPC_TInt32 rsize;
\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
289 // //タイムアウト付でストリームから読み出し。
\r
290 // rsize=NyLPC_iHttpPtrStream_pread(i_stream,(const void**)(&rp_base));
\r
292 // return NyLPC_TBool_FALSE;
\r
294 // for(i=0;i<rsize;i++){
\r
298 // case NyLPC_TcHttpBasicHeaderParser_ST_START:
\r
299 // st=parseStartLine(i_inst,c,o_out);
\r
301 // case NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM:
\r
302 // st=parseMessageParam(i_inst,c,o_out);
\r
304 // case NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD:
\r
305 // st=parseMessage1(i_inst,c,o_out);
\r
307 // case NyLPC_TcHttpBasicHeaderParser_ST_RL_URL:
\r
308 // st=parseRequestUrl(i_inst,c,o_out);
\r
310 // case NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION:
\r
311 // st=parseVersion(i_inst,c,NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD,o_out);
\r
313 // case NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE:
\r
314 // st=parseStatusCode(i_inst,c,o_out);
\r
316 // case NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON:
\r
317 // st=parseReason(i_inst,c);
\r
319 // case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH:
\r
320 // st=parseMessage_ContentLength(i_inst,c,o_out);
\r
322 // case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION:
\r
323 // st=parseMessage_Connection(i_inst,c,o_out);
\r
325 // case NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING:
\r
326 // st=parseMessage_TransferEncoding(i_inst,c,o_out);
\r
329 // i_inst->_rcode=500;
\r
330 // st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
333 // if(NyLPC_TcHttpBasicHeaderParser_ST_isError(st)){
\r
334 // return NyLPC_TBool_FALSE;
\r
337 // if(st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){
\r
339 // if(!testHeader(o_out,&i_inst->_rcode)){
\r
340 // st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
341 // return NyLPC_TBool_FALSE;
\r
344 // NyLPC_iHttpPtrStream_rseek(i_stream,i+1);
\r
345 // return NyLPC_TBool_TRUE;
\r
349 // NyLPC_iHttpPtrStream_rseek(i_stream,(NyLPC_TUInt16)rsize);
\r
351 // return NyLPC_TBool_FALSE;
\r
356 /*----------------------------------------
\r
358 ----------------------------------------*/
\r
362 static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error)
\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
369 if(i_header->startline.req.method!=NyLPC_THttpMethodType_GET){
\r
375 if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
\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
385 if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
\r
389 //ContentLengthが無いときは0
\r
390 if(i_header->content_length==NyLPC_THttpContentLength_INVALID_LENGTH){
\r
391 i_header->content_length=0;
\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
403 //content-length無し && Chunked有
\r
406 }else if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
\r
407 //ContentLengthあるのにChunkedとは何事
\r
411 return NyLPC_TBool_TRUE;
\r
412 case NyLPC_THttpVersion_UNKNOWN:
\r
420 return NyLPC_TBool_FALSE;
\r
423 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_TransferEncoding(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
427 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
\r
429 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし
\r
434 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし
\r
435 }else if(i_c==HTTP_LF){
\r
437 NyLPC_cStr_toUpper(&(i_inst->_wsb));
\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
443 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
444 i_inst->_rcode=500;
\r
445 NyLPC_OnErrorGoto(Error);
\r
447 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし;
\r
449 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
453 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\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
461 const static NyLPC_TChar* str[]={
\r
468 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
\r
470 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし
\r
475 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし
\r
476 }else if(i_c==HTTP_LF){
\r
478 NyLPC_cStr_toUpper(&(i_inst->_wsb));
\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
487 NyLPC_cStr_clear(&(i_inst->_wsb));
\r
488 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
\r
490 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
491 i_inst->_rcode=500;
\r
492 NyLPC_OnErrorGoto(Error);
\r
494 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし;
\r
496 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
500 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_ContentLength(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
506 if(NyLPC_cStr_len(&(i_inst->_wsb))==0)
\r
509 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし
\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
519 i_inst->_rcode=400;
\r
520 NyLPC_OnErrorGoto(Error);//ギャー
\r
522 NyLPC_cStr_clear(&(i_inst->_wsb));
\r
523 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
\r
525 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
526 i_inst->_rcode=500;
\r
527 NyLPC_OnErrorGoto(Error);
\r
529 return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし;
\r
531 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
534 static NyLPC_TcHttpBasicHeaderParser_ST parseStatusCode(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
536 NyLPC_TcStr_t* ws=&(i_inst->_wsb);
\r
541 if(NyLPC_cStr_len(ws)==0)
\r
544 return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし
\r
549 p=NyLPC_cStr_str(ws);
\r
550 o_out->startline.res.status=(strtol(p,&e,10));
\r
552 i_inst->_rcode=400;
\r
553 NyLPC_OnErrorGoto(Error);//ギャー
\r
555 NyLPC_cStr_clear(ws);
\r
556 return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;
\r
558 if(!NyLPC_cStr_put(ws,i_c)){
\r
559 i_inst->_rcode=500;
\r
560 NyLPC_OnErrorGoto(Error);
\r
562 return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし;
\r
564 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
566 static NyLPC_TcHttpBasicHeaderParser_ST parseReason(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c)
\r
568 NyLPC_TcStr_t* ws=&(i_inst->_wsb);
\r
572 NyLPC_cStr_clear(ws);
\r
573 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
\r
578 return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;//変化なし
\r
580 static NyLPC_TcHttpBasicHeaderParser_ST parseMessageParam(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
582 NyLPC_TcStr_t* ws=&(i_inst->_wsb);
\r
584 if(NyLPC_cStr_len(ws)==0){
\r
586 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
\r
588 NyLPC_cStr_put(ws,'C');//開始フラグ
\r
593 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
\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
602 NyLPC_cStr_clear(ws);
\r
603 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
\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
615 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
\r
617 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
620 static NyLPC_TcHttpBasicHeaderParser_ST parseMessage1(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
622 const static char* KNOWN_MSG[]={"CONNECTION","CONTENT-LENGTH","TRANSFER-ENCODING",NULL};
\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
633 NyLPC_cStr_clear(&(i_inst->_wsb));
\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
644 i_inst->_rcode=500;
\r
645 NyLPC_OnErrorGoto(Error);
\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
654 NyLPC_cStr_clear(&(i_inst->_wsb));
\r
657 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;
\r
659 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし
\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
667 i_inst->_rcode=400;
\r
668 NyLPC_OnErrorGoto(Error);
\r
672 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
673 i_inst->_rcode=500;
\r
674 NyLPC_OnErrorGoto(Error);
\r
676 return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし;
\r
678 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\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
684 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
\r
686 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
\r
691 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
\r
692 }else if(i_c==HTTP_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
699 NyLPC_cStr_clear(&(i_inst->_wsb));
\r
700 return i_next;//遷移(エラーの時はそのままエラーコードが渡る。)
\r
702 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
704 i_inst->_rcode=500;
\r
705 NyLPC_OnErrorGoto(Error);
\r
707 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
\r
709 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
713 URLパーサ。登録した関数に転送する?
\r
715 static NyLPC_TcHttpBasicHeaderParser_ST parseRequestUrl(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
718 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
\r
720 return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし
\r
722 NyLPC_cStr_put(&(i_inst->_wsb),'C');//開始フラグ
\r
727 NyLPC_cStr_clear(&(i_inst->_wsb));
\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
735 return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;
\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
744 return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし
\r
746 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
753 static NyLPC_TcHttpBasicHeaderParser_ST parseStartLine(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
758 if(parseHttpVersionStr(&(i_inst->_wsb),&(o_out->startline.res.version))){
\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
765 if(!parseRequestMethodStr(&(i_inst->_wsb),&(o_out->startline.req.method))){
\r
766 i_inst->_rcode=400;
\r
767 NyLPC_OnErrorGoto(ERROR);
\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
774 if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
\r
775 i_inst->_rcode=500;
\r
776 NyLPC_OnErrorGoto(ERROR);
\r
778 return NyLPC_TcHttpBasicHeaderParser_ST_START;//変化なし
\r
780 return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
\r
787 static NyLPC_TBool parseHttpVersionStr(NyLPC_TcStr_t* i_str,NyLPC_THttpVersion* o_out)
\r
793 p=NyLPC_cStr_str(i_str);
\r
794 if(NyLPC_cStr_len(i_str)<6){
\r
795 NyLPC_OnErrorGoto(Error);
\r
797 if(strncmp(p,"HTTP/",5)!=0){
\r
798 NyLPC_OnErrorGoto(Error);
\r
801 ma=strtol(p,&e,10);
\r
803 NyLPC_OnErrorGoto(Error);
\r
807 NyLPC_OnErrorGoto(Error);
\r
810 mi=strtoul(p,&e,10);
\r
812 NyLPC_OnErrorGoto(Error);
\r
815 NyLPC_OnErrorGoto(Error);
\r
821 *o_out=NyLPC_THttpVersion_09;
\r
827 *o_out=NyLPC_THttpVersion_10;
\r
830 *o_out=NyLPC_THttpVersion_11;
\r
832 *o_out=NyLPC_THttpVersion_UNKNOWN;
\r
837 *o_out=NyLPC_THttpVersion_UNKNOWN;
\r
840 return NyLPC_TBool_TRUE;//変化なし
\r
842 return NyLPC_TBool_FALSE;
\r