/*********************************************************************************
 * PROJECT: MiMic
 * --------------------------------------------------------------------------------
 *
 * This file is part of MiMic
 * Copyright (C)2011 Ryo Iizuka
 *
 * MiMic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by　the Free Software Foundation, either version 3 of the　License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * For further information please contact.
 *	http://nyatla.jp/
 *	<airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
 *
 *********************************************************************************/
#include "NyLPC_cHttpBasicHeaderParser_protected.h"
#include <stdlib.h>

NyLPC_TBool NyLPC_THttpBasicHeader_isPersistent(const struct NyLPC_THttpBasicHeader* i_struct)
{
	switch(i_struct->type)
	{
	case NyLPC_THttpHeaderType_REQUEST:
		return (i_struct->connection!=NyLPC_THttpMessgeHeader_Connection_CLOSE)&&(i_struct->startline.req.version==NyLPC_THttpVersion_11);
	case NyLPC_THttpHeaderType_RESPONSE:
	default:
		break;
	}
	return NyLPC_TBool_FALSE;
}




/**
 * HeaderParserのステータス定義値。
 */
typedef NyLPC_TUInt8 NyLPC_TcHttpBasicHeaderParser_ST;
#define NyLPC_TcHttpBasicHeaderParser_ST_START					((NyLPC_TcHttpBasicHeaderParser_ST)0x01)//HTTPステータスラインか、リクエストライン
#define NyLPC_TcHttpBasicHeaderParser_ST_RL_URL					((NyLPC_TcHttpBasicHeaderParser_ST)0x12)//URL
#define NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION				((NyLPC_TcHttpBasicHeaderParser_ST)0x13)//VERSION
#define NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE			((NyLPC_TcHttpBasicHeaderParser_ST)0x21)//ステータスコード
#define NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON				((NyLPC_TcHttpBasicHeaderParser_ST)0x22)//Reason-Phrase
#define NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD				((NyLPC_TcHttpBasicHeaderParser_ST)0x31)//MESSAGE
#define NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM				((NyLPC_TcHttpBasicHeaderParser_ST)0x32)//MESSAGEパラメータ部
#define NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH		((NyLPC_TcHttpBasicHeaderParser_ST)0x33)//MESSAGEContentLength
#define NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION			((NyLPC_TcHttpBasicHeaderParser_ST)0x34)//MESSAGEConnection
#define NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING	((NyLPC_TcHttpBasicHeaderParser_ST)0x35)//TransferEncoding
#define NyLPC_TcHttpBasicHeaderParser_ST_MSG_RANGE				((NyLPC_TcHttpBasicHeaderParser_ST)0x36)//Range
#define NyLPC_TcHttpBasicHeaderParser_ST_EOH					((NyLPC_TcHttpBasicHeaderParser_ST)0x7F)//終わり
#define NyLPC_TcHttpBasicHeaderParser_ST_ERROR					((NyLPC_TcHttpBasicHeaderParser_ST)0x80)//終わり



/*
	文字コードの定義
*/
#define HTTP_SP 0x20
#define HTTP_LF 0x0A
#define HTTP_CR 0x0D
#define HTTP_DM ':' 


/*
	プライベート関数
*/
#define NyLPC_TcHttpBasicHeaderParser_ST_isError(i_v) ((i_v)==NyLPC_TcHttpBasicHeaderParser_ST_ERROR)

static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_ContentLength(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseMessage1(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseVersion(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,NyLPC_TcHttpBasicHeaderParser_ST i_next,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseRequestUrl(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseMessageParam(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseStartLine(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseStatusCode(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);
static NyLPC_TcHttpBasicHeaderParser_ST parseReason(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c);
static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_TransferEncoding(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out);


static NyLPC_TBool parseHttpVersionStr(NyLPC_TcStr_t* i_str,NyLPC_THttpVersion* o_out);
static NyLPC_TBool parseRequestMethodStr(NyLPC_TcStr_t* i_str,NyLPC_THttpMethodType* o_out);

static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error);


/*----------------------------------------
	デフォルトハンドラ
----------------------------------------*/

static NyLPC_TBool default_message_handler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const NyLPC_TChar* i_name,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	(void)i_inst;
	(void)i_name;
	(void)i_c;
	return NyLPC_TBool_TRUE;
}
static NyLPC_TBool default_urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	(void)i_inst;
	(void)i_c;
	return NyLPC_TBool_TRUE;
}
/**
 * デフォルトハンドラ
 */
static const struct NyLPC_TcHttpBasicHeaderParser_Handler _default_handler=
{
		default_message_handler,
		default_urlHandler
};



/*----------------------------------------
	Public/Protected関数
----------------------------------------*/


void NyLPC_cHttpBasicHeaderParser_initialize(NyLPC_TcHttpBasicHeaderParser_t* i_inst)
{
	NyLPC_cStr_initialize(&(i_inst->_wsb),i_inst->_wsb_buf,NyLPC_cHttpBasicHeaderParser_SIZE_OF_WBS);
	i_inst->_handler=&_default_handler;
}

/**
 * ストリームから読み出して、パースします。
 */
NyLPC_TBool NyLPC_cHttpBasicHeaderParser_parse(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TcHttpStream_t* i_stream,struct NyLPC_THttpBasicHeader* o_out)
{
	NyLPC_TcHttpBasicHeaderParser_ST st;
	const char* rp_base;
	NyLPC_TInt32 rsize;
	char c;
	int i;

	//出力構造体を初期化
	st=NyLPC_TcHttpBasicHeaderParser_ST_START;
	o_out->connection=NyLPC_THttpMessgeHeader_Connection_NONE;
	o_out->content_length=NyLPC_THttpContentLength_INVALID_LENGTH;
	o_out->transfer_encoding=NyLPC_THttpMessgeHeader_TransferEncoding_NONE;

	for(;;){
		//タイムアウト付でストリームから読み出し。
		rsize=NyLPC_iHttpPtrStream_pread(i_stream,(const void**)(&rp_base));
		if(rsize<=0){
			return NyLPC_TBool_FALSE;
		}
		for(i=0;i<rsize;i++){
			c=*(rp_base+i);
			switch(st)
			{
			case NyLPC_TcHttpBasicHeaderParser_ST_START:
				st=parseStartLine(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM:
				st=parseMessageParam(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD:
				st=parseMessage1(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_RL_URL:
				st=parseRequestUrl(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION:
				st=parseVersion(i_inst,c,NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE:
				st=parseStatusCode(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON:
				st=parseReason(i_inst,c);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH:
				st=parseMessage_ContentLength(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION:
				st=parseMessage_Connection(i_inst,c,o_out);
				break;
			case NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING:
				st=parseMessage_TransferEncoding(i_inst,c,o_out);
				break;
			default:
				i_inst->_rcode=500;
				st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
			}
			//エラー起こしたら終了。
			if(NyLPC_TcHttpBasicHeaderParser_ST_isError(st)){
				return NyLPC_TBool_FALSE;
			}
			//パース成功
			if(st==NyLPC_TcHttpBasicHeaderParser_ST_EOH){
				//整合性チェック
				if(!testHeader(o_out,&i_inst->_rcode)){
					st=NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
					return NyLPC_TBool_FALSE;
				}
				//シーク
				NyLPC_iHttpPtrStream_rseek(i_stream,i+1);
				return NyLPC_TBool_TRUE;
			}
		}
		//シーク
		NyLPC_iHttpPtrStream_rseek(i_stream,(NyLPC_TUInt16)rsize);
	}
	return NyLPC_TBool_FALSE;
}



/*----------------------------------------
	private関数
----------------------------------------*/
/**
ヘッダの整合性をとる。
*/
static NyLPC_TBool testHeader(struct NyLPC_THttpBasicHeader* i_header,NyLPC_TUInt16* o_error)
{
	switch(i_header->startline.req.version){
	case NyLPC_THttpVersion_09:
		if(i_header->type==NyLPC_THttpHeaderType_REQUEST){
			//Requestの時だけmethodチェック
			//GETだけ
			if(i_header->startline.req.method!=NyLPC_THttpMethodType_GET){
				*o_error=400;
				break;
			}
		}
		//TEは受け付けない。
		if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
			*o_error=400;
			break;
		}
		//ContentLength=0,Connection=Closedに修正。
		i_header->content_length=0;
		i_header->connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;
		return NyLPC_TBool_TRUE;
	case NyLPC_THttpVersion_10:
		//TEは受け付けない。
		if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
			*o_error=406;
			break;
		}
		//ContentLengthが無いときは0
		if(i_header->content_length==NyLPC_THttpContentLength_INVALID_LENGTH){
			i_header->content_length=0;
		}
		//Connection=Closedに修正。(1.0のKeepaliveは難しいから無視)
		i_header->connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;
		return NyLPC_TBool_TRUE;
	case NyLPC_THttpVersion_11:
		if(i_header->content_length==NyLPC_THttpContentLength_INVALID_LENGTH){
			//Contentlength無しのChunked指定はOK
			if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_CHUNKED){
				//Chunkedが無い場合はContent-Lengthは0と仮定
				i_header->content_length=0;
			}
		}
		//ContentLengthあるのにChunkedとは何事
		if(i_header->transfer_encoding!=NyLPC_THttpMessgeHeader_TransferEncoding_NONE){
			*o_error=400;
			break;
		}
		return NyLPC_TBool_TRUE;
	case NyLPC_THttpVersion_UNKNOWN:
		//おい馬鹿やめろ
		*o_error=505;
		break;
	default:
		*o_error=500;
		break;
	}
	return NyLPC_TBool_FALSE;
}

static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_TransferEncoding(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{

	//先頭のスペース除外
	if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし
		}
	}
	if(i_c==HTTP_CR){
		//CRの無視
		return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし
	}else if(i_c==HTTP_LF){
		//大文字化
		NyLPC_cStr_toUpper(&(i_inst->_wsb));
		//close?
		o_out->transfer_encoding=NyLPC_cStr_isEqual(&(i_inst->_wsb),"CHUNKED")?NyLPC_THttpMessgeHeader_TransferEncoding_CHUNKED:NyLPC_THttpMessgeHeader_TransferEncoding_UNKNOWN;
		NyLPC_cStr_clear(&(i_inst->_wsb));
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;//変化なし;
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}


static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{

	//先頭のスペース除外
	if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし
		}
	}
	if(i_c==HTTP_CR){
		//CRの無視
		return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし
	}else if(i_c==HTTP_LF){
		//大文字化
		NyLPC_cStr_toUpper(&(i_inst->_wsb));
		//close?
		if(NyLPC_cStr_isEqual(&(i_inst->_wsb),"CLOSE")){
			o_out->connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;
		}else if(NyLPC_cStr_isEqual(&(i_inst->_wsb),"KEEP-ALIVE")){
			o_out->connection=NyLPC_THttpMessgeHeader_Connection_KEEPALIVE;
		}else{
			o_out->connection=NyLPC_THttpMessgeHeader_Connection_UNKNOWN;
		}
		NyLPC_cStr_clear(&(i_inst->_wsb));
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;//変化なし;
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}


static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_ContentLength(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	char* e;
	char* p;

	//先頭のスペース除外
	if(NyLPC_cStr_len(&(i_inst->_wsb))==0)
	{
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし
		}
	}
	if(i_c==HTTP_CR){
		//CRの無視
		return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし
	}else if(i_c==HTTP_LF){
		p=NyLPC_cStr_str(&(i_inst->_wsb));
		o_out->content_length=strtol(p,&e,10);
		if(e==p){
			i_inst->_rcode=400;
			NyLPC_OnErrorGoto(Error);//ｷﾞｬｰ
		}
		NyLPC_cStr_clear(&(i_inst->_wsb));
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;//変化なし;
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

static NyLPC_TcHttpBasicHeaderParser_ST parseStatusCode(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	NyLPC_TcStr_t* ws=&(i_inst->_wsb);
	char* e;
	char* p;

	//先頭のスペース除外
	if(NyLPC_cStr_len(ws)==0)
	{
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし
		}
	}
	if(i_c==HTTP_SP){
	//SPで終了
		p=NyLPC_cStr_str(ws);
		o_out->startline.res.status=(strtol(p,&e,10));
		if(e==p){
			i_inst->_rcode=400;
			NyLPC_OnErrorGoto(Error);//ｷﾞｬｰ
		}
		NyLPC_cStr_clear(ws);
		return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;
	}
	if(!NyLPC_cStr_put(ws,i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;//変化なし;
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}
static NyLPC_TcHttpBasicHeaderParser_ST parseReason(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c)
{
	NyLPC_TcStr_t* ws=&(i_inst->_wsb);
	//LFくるまで飛ばす。
	switch(i_c){
	case HTTP_LF:
		NyLPC_cStr_clear(ws);
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
	default:
		break;
	}
	//URLパーサへ通知
	return NyLPC_TcHttpBasicHeaderParser_ST_SL_REASON;//変化なし
}
static NyLPC_TcHttpBasicHeaderParser_ST parseMessageParam(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	NyLPC_TcStr_t* ws=&(i_inst->_wsb);
	//先頭のスペース除外
	if(NyLPC_cStr_len(ws)==0){
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
		}else{
			NyLPC_cStr_put(ws,'C');//開始フラグ
		}
	}
	switch(i_c){
	case HTTP_CR:
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
	case HTTP_LF:
		//メッセージフィールドの終端を通知
		if(!i_inst->_handler->messageHandler(i_inst,NULL,0,o_out)){
			i_inst->_rcode=500;
			NyLPC_OnErrorGoto(Error);
		}
		NyLPC_cStr_clear(ws);
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;
	default:
		//メッセージフィールドの追記
		if(!i_inst->_handler->messageHandler(i_inst,NULL,i_c,o_out)){
			i_inst->_rcode=500;
			NyLPC_OnErrorGoto(Error);
		}
		break;
	}
	//URLパーサへ通知
	return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;//変化なし
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

static NyLPC_TcHttpBasicHeaderParser_ST parseMessage1(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	const static char* KNOWN_MSG[]={"CONNECTION","CONTENT-LENGTH","TRANSFER-ENCODING",NULL};
	int i;

	switch(i_c){
	case HTTP_DM:
	//メッセージの名前確定。遷移先判定
		//ヘッダ名を大文字にする。
		NyLPC_cStr_toUpper(&(i_inst->_wsb));
		for(i=0;KNOWN_MSG[i]!=NULL;i++){
			if(NyLPC_cStr_isEqual(&(i_inst->_wsb),KNOWN_MSG[i])){
				//確定。
				NyLPC_cStr_clear(&(i_inst->_wsb));
				switch(i){
				case 0://CONNECTION
					return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONNECTION;
				case 1://CONTENT-LENGTH
					return NyLPC_TcHttpBasicHeaderParser_ST_MSG_CONTENTLENGTH;
				case 2://TRANSFER-ENCODING
					return NyLPC_TcHttpBasicHeaderParser_ST_MSG_TRANSFERENCODING;
				default://エラー
					break;
				}
				i_inst->_rcode=500;
				NyLPC_OnErrorGoto(Error);
			}
		}
		//メッセージフィールドの名前を通知
		if(!i_inst->_handler->messageHandler(i_inst,(NyLPC_TChar*)&(i_inst->_wsb),0,o_out)){
			i_inst->_rcode=500;
			NyLPC_OnErrorGoto(Error);
		}
		//カスタムヘッダ解析へ。
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;
	case HTTP_CR:
		return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし
	case HTTP_LF:
		//1文字で終了ならパースエンド。バリデーションチェックへ
		if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
			NyLPC_cStr_clear(&(i_inst->_wsb));
			return NyLPC_TcHttpBasicHeaderParser_ST_EOH;
		}
		//これはひどい。
		i_inst->_rcode=400;
		NyLPC_OnErrorGoto(Error);
	default:
		break;
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD;//変化なし;
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

static NyLPC_TcHttpBasicHeaderParser_ST parseVersion(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,NyLPC_TcHttpBasicHeaderParser_ST i_next,struct NyLPC_THttpBasicHeader* o_out)
{
	//先頭のスペース除外
	if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
		}
	}
	if(i_c==HTTP_CR){
	//CRの無視
		return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
	}else if(i_c==HTTP_LF){
	//LFで確定
		if(!parseHttpVersionStr(&(i_inst->_wsb),&(o_out->startline.req.version))){
			i_inst->_rcode=505;
			NyLPC_cStr_clear(&(i_inst->_wsb));
			NyLPC_OnErrorGoto(Error);
		}
		NyLPC_cStr_clear(&(i_inst->_wsb));
		return i_next;//遷移(エラーの時はそのままエラーコードが渡る。)
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		//追記処理しっぱい
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;//変化なし
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

/**
URLパーサ。登録した関数に転送する？
*/
static NyLPC_TcHttpBasicHeaderParser_ST parseRequestUrl(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	//先頭のスペース除外
	if(NyLPC_cStr_len(&(i_inst->_wsb))==0){
		if(i_c==HTTP_SP){
			return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし
		}else{
			NyLPC_cStr_put(&(i_inst->_wsb),'C');//開始フラグ
		}
	}
	//次のスペースがくるまで。
	if(i_c==HTTP_SP){
		NyLPC_cStr_clear(&(i_inst->_wsb));
		//URLハンドラへ通知
		if(!i_inst->_handler->urlHandler(i_inst,0,o_out)){
			i_inst->_rcode=500;
			NyLPC_OnErrorGoto(Error);
		}
		return NyLPC_TcHttpBasicHeaderParser_ST_RL_VERSION;
	}
	//URLパーサへ通知
	if(!i_inst->_handler->urlHandler(i_inst,i_c,o_out)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(Error);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;//変化なし
Error:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

/**
Methodパーサ
	[:HTTPMETHOD:]を得る。
*/
static NyLPC_TcHttpBasicHeaderParser_ST parseStartLine(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
{
	if(i_c==HTTP_SP){
	//SPがデリミタ
		//HTTPステータスを試す。
		if(parseHttpVersionStr(&(i_inst->_wsb),&(o_out->startline.res.version))){
			//これはHTTPステータス
			o_out->type=NyLPC_THttpHeaderType_RESPONSE;
			NyLPC_cStr_clear(&(i_inst->_wsb));
			return NyLPC_TcHttpBasicHeaderParser_ST_SL_STATUSCODE;
		}
		//HTTPリクエストを試す。
		if(!parseRequestMethodStr(&(i_inst->_wsb),&(o_out->startline.req.method))){
			i_inst->_rcode=400;
			NyLPC_OnErrorGoto(ERROR);
		}
		//これはHTTPリクエスト
		o_out->type=NyLPC_THttpHeaderType_REQUEST;
		NyLPC_cStr_clear(&(i_inst->_wsb));
		return NyLPC_TcHttpBasicHeaderParser_ST_RL_URL;
	}
	if(!NyLPC_cStr_put(&(i_inst->_wsb),i_c)){
		i_inst->_rcode=500;
		NyLPC_OnErrorGoto(ERROR);
	}
	return NyLPC_TcHttpBasicHeaderParser_ST_START;//変化なし
ERROR:
	return NyLPC_TcHttpBasicHeaderParser_ST_ERROR;
}

static NyLPC_TBool parseRequestMethodStr(NyLPC_TcStr_t* i_str,NyLPC_THttpMethodType* o_out)
{
	static const char* METHOD[]={
		"GET","POST","HEAD",NULL};
	static const NyLPC_THttpMethodType MT[]={
		NyLPC_THttpMethodType_GET,NyLPC_THttpMethodType_POST,NyLPC_THttpMethodType_HEAD,0x00};
	int i;

	//解析処理
	for(i=0;METHOD[i]!=0x00;i++){
		NyLPC_cStr_toUpper(i_str);//大文字化
		if(NyLPC_cStr_isEqual(i_str,METHOD[i])){
			*o_out=MT[i];
			return NyLPC_TBool_TRUE;
		}
	}
	NyLPC_OnErrorGoto(ERROR);
ERROR:
	return NyLPC_TBool_FALSE;
}



static NyLPC_TBool parseHttpVersionStr(NyLPC_TcStr_t* i_str,NyLPC_THttpVersion* o_out)
{
	NyLPC_TChar* p;
	char* e;
	long ma,mi;

	p=NyLPC_cStr_str(i_str);
	if(NyLPC_cStr_len(i_str)<6){
		NyLPC_OnErrorGoto(Error);
	}
	if(strncmp(p,"HTTP/",5)!=0){
		NyLPC_OnErrorGoto(Error);
	}
	p+=5;
	ma=strtol(p,&e,10);
	if(p==e){
		NyLPC_OnErrorGoto(Error);
	}
	p=e;//.をチェック
	if(*p!='.'){
		NyLPC_OnErrorGoto(Error);
	}
	p++;
	mi=strtoul(p,&e,10);
	if(p==e){
		NyLPC_OnErrorGoto(Error);
	}
	if(ma<0 ||mi<0){
		NyLPC_OnErrorGoto(Error);
	}
	switch(ma){
	case 0:
		if(mi>=9){
			//HTTP0.9相当
			*o_out=NyLPC_THttpVersion_09;
		}
		break;
	case 1:
		if(mi==0){
			//HTTP1.0
			*o_out=NyLPC_THttpVersion_10;
		}else if(mi>=1){
			//HTTP1.1
			*o_out=NyLPC_THttpVersion_11;
		}else{
			*o_out=NyLPC_THttpVersion_UNKNOWN;
		}
		break;
	default:
		//お前など知らん
		*o_out=NyLPC_THttpVersion_UNKNOWN;
		break;
	}
	return NyLPC_TBool_TRUE;//変化なし
Error:
	return NyLPC_TBool_FALSE;
}

