This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Fork of libMiMic by
Revision 57:bc4330dfa62f, committed 2013-09-13
- Comitter:
- nyatla
- Date:
- Fri Sep 13 06:38:16 2013 +0000
- Parent:
- 56:d38b6ce8c63b
- Child:
- 58:03b89038b21a
- Commit message:
- update mimic core r329;
Changed in this revision
--- a/core/NyLPC_cMiMicEnv.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/NyLPC_cMiMicEnv.h Fri Sep 13 06:38:16 2013 +0000 @@ -13,7 +13,7 @@ #endif /* __cplusplus */ -#define NyLPC_cMiMicEnv_VERSION "MiMic/1.4.52" +#define NyLPC_cMiMicEnv_VERSION "MiMic/1.4.62" #ifdef __cplusplus
--- a/core/NyLPC_cRingBuffer.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/NyLPC_cRingBuffer.c Fri Sep 13 06:38:16 2013 +0000 @@ -119,7 +119,7 @@ } //右側の書込みサイズの計算 rw=i_inst->bl-wo; - l=wsize<rw?wsize:rw; + l=(wsize<rw)?wsize:rw; //書込みポインタを設定 p=(s+wo); for(i=l-1;i>=0;i--){ @@ -178,8 +178,8 @@ NyLPC_cRingBuffer_dump(s); b=NyLPC_cRingBuffer_getReadPtr(s,&l); printf("readable:%d\n",l); - NyLPC_cRingBuffer_seekReadPtr(s,l>1?l-1:1); - printf("read:%d\n",l>1?l-1:1); + NyLPC_cRingBuffer_seekReadPtr(s,(l>1)?l-1:1); + printf("read:%d\n",(l>1)?l-1:1); NyLPC_cRingBuffer_dump(s); }
--- a/core/NyLPC_cRomPtrStream.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/NyLPC_cRomPtrStream.c Fri Sep 13 06:38:16 2013 +0000 @@ -101,7 +101,7 @@ NyLPC_Assert(inst->_rom!=NULL); size=inst->_rom_size-inst->_ed; //残り長さ計算 - psize=size>inst->_packet_size?inst->_packet_size:size; //パケットサイズ計算 + psize=(size>inst->_packet_size)?inst->_packet_size:size; //パケットサイズ計算 *o_buf_ptr=(inst->_rom+inst->_ed); //現在位置を返す inst->_ed+=psize;//読出し位置更新 return psize;
--- a/core/NyLPC_cStr.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/NyLPC_cStr.h Fri Sep 13 06:38:16 2013 +0000 @@ -82,10 +82,16 @@ */ #define NyLPC_cStr_clear(i_inst) (i_inst)->l=0 /** -文字列が同一か返します。 -*/ + * NULL terminated文字列が同一か返します。 + */ #define NyLPC_cStr_isEqual(i_inst,i_str) (strcmp(NyLPC_cStr_str(i_inst),(i_str))==0) /** + * NULL terminated文字列が同一か返します。 + * 大文字小文字を区別しません。 + */ +#define NyLPC_cStr_isEqualIgnoreCase(i_inst,i_str) (NyLPC_stricmp(NyLPC_cStr_str(i_inst),(i_str))==0) + +/** * 文字列を大文字にします。 * *
--- a/core/NyLPC_stdlib.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/NyLPC_stdlib.c Fri Sep 13 06:38:16 2013 +0000 @@ -149,7 +149,7 @@ i = 0; do{ v=(NyLPC_TInt8)(i_n % i_base); - o_out[i++] = v<10?(v+'0'):(v+'a'-10); + o_out[i++] = (v<10)?(v+'0'):(v+'a'-10); }while ((i_n /= i_base) > 0); if (sign < 0){ o_out[i++] = '-'; @@ -164,7 +164,7 @@ NyLPC_TInt8 v; do{ v=(NyLPC_TInt8)(i_n % i_base); - o_out[i++] = v<10?(v+'0'):(v+'a'-10); + o_out[i++] = (v<10)?(v+'0'):(v+'a'-10); }while ((i_n /= i_base) > 0); o_out[i] = '\0'; NyLPC_reverse(o_out); @@ -180,7 +180,7 @@ NyLPC_TInt8 v; do{ v=(NyLPC_TInt8)(i_n % i_base); - o_out[i++] = v<10?(v+'0'):(v+'a'-10); + o_out[i++] = (v<10)?(v+'0'):(v+'a'-10); }while ((i_n /= i_base) > 0); while(i<i_digit){ o_out[i++] = '0';
--- a/core/flash/NyLPC_cOnchipFlashWriter.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/flash/NyLPC_cOnchipFlashWriter.c Fri Sep 13 06:38:16 2013 +0000 @@ -41,7 +41,7 @@ //書込み可能サイズを計算 free_size=256-s_padding; //書込みサイズを決定 - wsize=free_size>size?size:free_size; + wsize=(free_size>size)?size:free_size; //Flashから一時RAMへ前方パディングを読む if(s_padding>0){ memcpy(_work,fblock_addr,s_padding);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/http/NyLPC_cBase64.c Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,52 @@ +/* + * NyLPC_cBase64.c + * + * Created on: 2013/09/04 + * Author: nyatla + */ + +#ifndef NYLPC_CBASE64_C_ +#define NYLPC_CBASE64_C_ + +#include "NyLPC_cBase64.h" + +/** + * @param i_src + * @param length + * @param i_dest + * Base64文字列の出力領域. length/3*4+1の長さが必要。 + */ +void NyLPC_cBase64_encode(const NyLPC_TChar* i_src,NyLPC_TUInt16 length,char* i_dest) +{ + const static char* B64CODE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + NyLPC_TUInt16 s,d; + d=0; + for(s=0; s<(length-2); s+=3){ + i_dest[d++]=B64CODE[((0xfc&i_src[s+0])>>2)]; + i_dest[d++]=B64CODE[((0x03&i_src[s+0])<<4)|((0xf0&i_src[s+1])>>4)]; + i_dest[d++]=B64CODE[((0x0f&i_src[s+1])<<2)|((0xc0&i_src[s+2])>>6)]; + i_dest[d++]=B64CODE[((0x3f&i_src[s+2])>>0)]; + } + s=length-length%3; + switch(length%3){ + case 1: + i_dest[d++]=B64CODE[((0xfc&i_src[s+0])>>2)]; + i_dest[d++]=B64CODE[((0x03&i_src[s+0])<<4)]; + break; + case 2: + i_dest[d++]=B64CODE[((0xfc&i_src[s+0])>>2)]; + i_dest[d++]=B64CODE[((0x03&i_src[s+0])<<4)|((0xf0&i_src[s+1])>>4)]; + i_dest[d++]=B64CODE[((0x0f&i_src[s+1])<<2)]; + break; + } + //文字数 + while(d%4!=0){ + i_dest[d++]='='; + } + i_dest[d]='\0'; +} + + + +#endif /* NYLPC_CBASE64_C_ */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/http/NyLPC_cBase64.h Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,29 @@ +/* + * NyLPC_cBase64.h + * + * Created on: 2013/09/04 + * Author: nyatla + */ + +#ifndef NYLPC_CBASE64_H_ +#define NYLPC_CBASE64_H_ +#include "NyLPC_stdlib.h" +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @param i_src + * @param length + * @param i_dest + * Base64文字列の出力領域. length/3*4+1の長さが必要。 + */ +void NyLPC_cBase64_encode(const NyLPC_TChar* i_src,NyLPC_TUInt16 length,char* i_dest); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NYLPC_CBASE64_H_ */ +
--- a/core/http/NyLPC_cHttpBasicHeaderParser.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpBasicHeaderParser.c Fri Sep 13 06:38:16 2013 +0000 @@ -135,7 +135,7 @@ void NyLPC_cHttpBasicHeaderParser_initialize(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const struct NyLPC_TcHttpBasicHeaderParser_Handler* i_handler) { NyLPC_cStr_initialize(&(i_inst->_wsb),i_inst->_wsb_buf,NyLPC_cHttpBasicHeaderParser_SIZE_OF_WBS); - i_inst->_handler=(i_handler==NULL?&_default_handler:i_handler); + i_inst->_handler=((i_handler==NULL)?&_default_handler:i_handler); } /** @@ -450,7 +450,18 @@ static NyLPC_TcHttpBasicHeaderParser_ST parseMessage_Connection(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) { - + const static NyLPC_TUInt8 id[]={ + NyLPC_THttpMessgeHeader_Connection_CLOSE, + NyLPC_THttpMessgeHeader_Connection_KEEPALIVE, + NyLPC_THttpMessgeHeader_Connection_UPGRADE, + NyLPC_THttpMessgeHeader_Connection_UNKNOWN + }; + const static NyLPC_TChar* str[]={ + "CLOSE", + "KEEP-ALIVE", + "UPGRADE" + }; + NyLPC_TUInt8 i; //先頭のスペース除外 if(NyLPC_cStr_len(&(i_inst->_wsb))==0){ if(i_c==HTTP_SP){ @@ -463,13 +474,13 @@ }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; + //Convert to ID + o_out->connection=NyLPC_THttpMessgeHeader_Connection_UNKNOWN; + for(i=0;id[i]!=NyLPC_THttpMessgeHeader_Connection_UNKNOWN;i++){ + if(NyLPC_cStr_isEqual(&(i_inst->_wsb),str[i])){ + o_out->connection=id[i]; + break; + } } NyLPC_cStr_clear(&(i_inst->_wsb)); return NyLPC_TcHttpBasicHeaderParser_ST_MSGHEAD; @@ -638,6 +649,7 @@ i_inst->_rcode=500; NyLPC_OnErrorGoto(Error); } + NyLPC_cStr_clear(&(i_inst->_wsb)); } //カスタムヘッダ解析へ。 return NyLPC_TcHttpBasicHeaderParser_ST_MSGPARAM;
--- a/core/http/NyLPC_cHttpBasicHeaderParser.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpBasicHeaderParser.h Fri Sep 13 06:38:16 2013 +0000 @@ -97,6 +97,7 @@ #define NyLPC_THttpMessgeHeader_Connection_NONE ((NyLPC_THttpMessgeHeader_Connection)0x01) #define NyLPC_THttpMessgeHeader_Connection_CLOSE ((NyLPC_THttpMessgeHeader_Connection)0x02) #define NyLPC_THttpMessgeHeader_Connection_KEEPALIVE ((NyLPC_THttpMessgeHeader_Connection)0x03) +#define NyLPC_THttpMessgeHeader_Connection_UPGRADE ((NyLPC_THttpMessgeHeader_Connection)0x04) #define NyLPC_THttpMessgeHeader_Connection_UNKNOWN ((NyLPC_THttpMessgeHeader_Connection)0x10) typedef NyLPC_TUInt8 NyLPC_THttpMessgeHeader_TransferEncoding;
--- a/core/http/NyLPC_cHttpBodyWriter.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpBodyWriter.c Fri Sep 13 06:38:16 2013 +0000 @@ -210,7 +210,7 @@ // NyLPC_cHttpResponseWriter_setClose(&hw); body_len=100; NyLPC_cHttpHeaderWriter_setContentLength(&hw,body_len); - NyLPC_cHttpHeaderWriter_writeHeader(&hw,500); + NyLPC_cHttpHeaderWriter_writeResponseHeader(&hw,500); NyLPC_cHttpHeaderWriter_close(&hw); NyLPC_cHttpBodyWriter_initialize(&bw,&st);
--- a/core/http/NyLPC_cHttpHeaderWriter.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpHeaderWriter.c Fri Sep 13 06:38:16 2013 +0000 @@ -117,13 +117,84 @@ } +NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRequestHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_THttpMethodType i_method,const struct NyLPC_TIPv4Addr* i_host,NyLPC_TUInt16 i_port,const NyLPC_TChar* i_path) +{ + const NyLPC_TChar* t; + NyLPC_TChar v[16]; + //エラー状態ならなにもしない。 + if(i_inst->_is_error){ + return NyLPC_TBool_FALSE; + } -#define TIMEOUT 10*1000 + t=NyLPC_THttpMethodType_toString(i_method); + if(t==NULL){ + return NyLPC_TBool_FALSE; + } + //リクエストラインの記述 + //Method + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,t,-1)){ + NyLPC_OnErrorGoto(Error); + } + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){ + NyLPC_OnErrorGoto(Error); + } + //Path + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_path,-1)){ + NyLPC_OnErrorGoto(Error); + } + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," HTTP/1.1\r\n",11)){ + NyLPC_OnErrorGoto(Error); + } + //HOSTの記述 + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Host: ",6)){ + NyLPC_OnErrorGoto(Error); + } + NyLPC_TIPv4Addr_toString(i_host,v); + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){ + NyLPC_OnErrorGoto(Error); + } + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,":",1)){ + NyLPC_OnErrorGoto(Error); + } + NyLPC_uitoa(i_port,v,10); + if(!writeln(i_inst->_ref_stream,v,-1)){ + NyLPC_OnErrorGoto(Error); + } + + //close + if(i_inst->_is_close){ + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){ + NyLPC_OnErrorGoto(Error); + } + } + + //chunked + if(i_inst->_is_chunked){ + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){ + NyLPC_OnErrorGoto(Error); + } + }else{ + if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){ + NyLPC_OnErrorGoto(Error); + } + NyLPC_uitoa(i_inst->_content_length,v,10); + if(!writeln(i_inst->_ref_stream,v,-1)){ + NyLPC_OnErrorGoto(Error); + } + } + //送信サイズをリセット + i_inst->_size_of_sent=0; + return NyLPC_TBool_TRUE; +Error: + i_inst->_is_error=NyLPC_TUInt8_FALSE; + return NyLPC_TBool_FALSE; + +} /** * ステータスラインと、標準メッセージヘッダを出力します。 */ -NyLPC_TBool NyLPC_cHttpHeaderWriter_writeHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status) +NyLPC_TBool NyLPC_cHttpHeaderWriter_writeResponseHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status) { NyLPC_TChar v[12]; const char* m=getStatusMessage(i_status);
--- a/core/http/NyLPC_cHttpHeaderWriter.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpHeaderWriter.h Fri Sep 13 06:38:16 2013 +0000 @@ -27,6 +27,7 @@ #define NYLPC_CHTTPHEADERWRITER_H_ #include "NyLPC_stdlib.h" +#include "NyLPC_uipService.h" #include "NyLPC_cHttpStream.h" #include "NyLPC_cHttpBasicHeaderParser.h" #include "NyLPC_cHttpdConfig.h" @@ -60,8 +61,8 @@ NyLPC_TBool NyLPC_cHttpHeaderWriter_initialize(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TiHttpPtrStream_t* i_ref_stream,const struct NyLPC_THttpBasicHeader* i_req_header); #define NyLPC_cHttpHeaderWriter_finalize(i) - -NyLPC_TBool NyLPC_cHttpHeaderWriter_writeHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status); +NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRequestHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_THttpMethodType i_method,const struct NyLPC_TIPv4Addr* i_host,NyLPC_TUInt16 i_port,const NyLPC_TChar* i_path); +NyLPC_TBool NyLPC_cHttpHeaderWriter_writeResponseHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status); NyLPC_TBool NyLPC_cHttpHeaderWriter_writeMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_name,const NyLPC_TChar* i_field); /** * \r\n区切りのメッセージをそのままヘッダに挿入します。i_additional_headerの終端は\r\nで閉じてください。
--- a/core/http/NyLPC_cHttpStream.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/http/NyLPC_cHttpStream.c Fri Sep 13 06:38:16 2013 +0000 @@ -50,7 +50,7 @@ } NyLPC_TInt32 NyLPC_cTcpSocket_precv(void* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec) { - int l=_rbuf_len>100?100:_rbuf_len; + int l=(_rbuf_len>100)?100:_rbuf_len; *o_buf_ptr=_rbuf; return l; } @@ -142,7 +142,7 @@ NyLPC_TUInt16 s,free_size; NyLPC_TUInt32 l; const char* src=(const char*)i_data; - l=(i_length<0?strlen(src):i_length); + l=((i_length<0)?strlen(src):i_length); while(l>0){ //送信バッファがNULLなら、割り当て。 if(inst->txb==NULL){
--- a/core/include/NyLPC_http.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/include/NyLPC_http.h Fri Sep 13 06:38:16 2013 +0000 @@ -41,6 +41,7 @@ #include "../http/NyLPC_cUrlEncode.h" #include "../http/NyLPC_cHttpBasicBodyParser.h" #include "../http/NyLPC_cHttpBodyParser.h" +#include "../http/NyLPC_cBase64.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */
--- a/core/include/NyLPC_net.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/include/NyLPC_net.h Fri Sep 13 06:38:16 2013 +0000 @@ -41,10 +41,14 @@ #include "../net/httpd/mod/NyLPC_cModFileIoBaseClass.h" #include "../net/httpd/mod/NyLPC_cModRemoteMcu.h" #include "../net/httpd/mod/NyLPC_cModMiMicSetting.h" +#include "../net/httpd/mod/NyLPC_cModWebSocket.h" #include "../net/httpd/mod/NyLPC_cModRomFiles.h" #include "../net/httpd/mod/NyLPC_cModUrl.h" #include "../net/httpd/mod/NyLPC_cModUPnPDevice.h" +#include "../net/httpcl/NyLPC_cHttpClient.h" + + #include "../net/upnp/NyLPC_cSsdpSocket.h" #include "../net/upnp/NyLPC_cUPnP.h"
--- a/core/include/NyLPC_stdlib.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/include/NyLPC_stdlib.h Fri Sep 13 06:38:16 2013 +0000 @@ -74,19 +74,19 @@ * Abortマクロです。eが偽の時に、異常終了します。 * デバック時/リリース時のどちらでも有効です。 * @param e - * 評価式です。 + * 評価式です. */ #define NyLPC_AbortIfNot(e) if(!(e)){NyLPC_abortHook(__FILE__,__LINE__);}; /** - * 警告表示用のマクロです。デバックに使います。 - * デバック時のみ有効です。 + * 警告表示用のマクロです.デバックに使います. + * デバック時のみ有効です. */ #define NyLPC_Warning() {NyLPC_debugHook(__FILE__,__LINE__);}; /** - * 警告表示用のマクロです。eが偽の時に、警告を出します。 - * デバック時のみ有効です。 + * 警告表示用のマクロです.eが偽の時に、警告を出します. + * デバック時のみ有効です. * @param e * 評価式です。 */ @@ -95,7 +95,7 @@ /* * トレースマクロです。デバックに使います。 * 内部変数に、最後にコールされたファイル名と、行番号を保存します。 - * デバック時のみ有効です。 + * デバック時のみ有効です. */ #define NyLPC_Trace() {NyLPC_debugHook(__FILE__,__LINE__);}; #else @@ -480,9 +480,9 @@ */ NyLPC_TUInt8 NyLPC_TTextIdTbl_getMatchIdIgnoreCase(const NyLPC_TChar* i_str,const struct NyLPC_TTextIdTbl i_tbl[]); /** - * テーブルからIDに一致する文字列を返す。 + * テーブルからIDに一致する文字列を返す. * @return - * IDに一致する文字列。 + * IDに一致する文字列. * 存在しなければNULL */ const NyLPC_TChar* NyLPC_TTextIdTbl_getTextById(NyLPC_TUInt8 i_id,const struct NyLPC_TTextIdTbl i_tbl[]);
--- a/core/include/NyLPC_utils.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/include/NyLPC_utils.h Fri Sep 13 06:38:16 2013 +0000 @@ -35,6 +35,8 @@ #include "../utils/NyLPC_cFormatWriter.h" #include "../utils/NyLPC_cUuid.h" +#include "../utils/sha1/sha1.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/net/httpcl/NyLPC_cHttpClient.c Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,263 @@ +/* + * NyLPC_cHttpClient.c + * + * Created on: 2013/08/24 + * Author: nyatla + */ +#include "NyLPC_cHttpClient.h" +typedef NyLPC_TUInt8 NyLPC_TcHttpClient_ST; +#define NyLPC_TcHttpClient_ST_CLOSED 0x00 //ソケット切断 +#define NyLPC_TcHttpClient_ST_IDLE 0x01 //メソッド選択待ち + +#define NyLPC_TcHttpClient_ST_SEND_REQ_BODY 0x21 //POSTリクエスト送信中 +#define NyLPC_TcHttpClient_ST_RECV_RES_HEAD 0x23 +#define NyLPC_TcHttpClient_ST_RECV_RES_BODY 0x24 + + + +void NyLPC_cHttpClient_initialize(NyLPC_TcHttpClient_t* i_inst,void* i_rx_buf,NyLPC_TUInt16 i_rx_size) +{ + NyLPC_cTcpSocket_initialize(&i_inst->_sock,i_rx_buf,i_rx_size); + i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED; +} +void NyLPC_cHttpClient_finalize(NyLPC_TcHttpClient_t* i_inst) +{ + NyLPC_cHttpClient_close(i_inst); + NyLPC_cTcpSocket_finalize(&i_inst->_sock); +} + +void NyLPC_cHttpClient_close(NyLPC_TcHttpClient_t* i_inst) +{ + //ステータスをclosedへ遷移 + switch(i_inst->_state){ + case NyLPC_TcHttpClient_ST_RECV_RES_BODY: + NyLPC_cHttpBodyParser_finalize(&i_inst->pw.body_parser); + break; + case NyLPC_TcHttpClient_ST_SEND_REQ_BODY: + NyLPC_cHttpBodyWriter_finalize(&(i_inst->pw.body_writer)); + break; + case NyLPC_TcHttpClient_ST_RECV_RES_HEAD: + //開放するものとくにない + break; + case NyLPC_TcHttpClient_ST_IDLE: + break; + case NyLPC_TcHttpClient_ST_CLOSED: + return; + } + NyLPC_cTcpSocket_close(&i_inst->_sock,1000); + i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED; +} + +/** + * サーバに接続する。 + * 関数はステータスをIDLEへ遷移する。 + * インスタンスのステータスは何でも構わない。 + * @return + * TRUE - ステータスはIDLEへ遷移する。 + * FALSE - ステータスはCLOSEDへ遷移する。 + */ +NyLPC_TBool NyLPC_cHttpClient_connect(NyLPC_TcHttpClient_t* i_inst,struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port) +{ + //ステータスをclosedへ遷移 + NyLPC_cHttpClient_close(i_inst); + //接続 + if(!NyLPC_cTcpSocket_connect(&i_inst->_sock,i_addr,i_port,3000)){ + return NyLPC_TBool_FALSE; + } + //streamの生成 + if(!NyLPC_cHttpStream_initialize(&i_inst->_stream,&(i_inst->_sock))){ + NyLPC_OnErrorGoto(ERROR); + } + //ステータス遷移 + i_inst->_state=NyLPC_TcHttpClient_ST_IDLE; + return NyLPC_TBool_TRUE; +ERROR: + return NyLPC_TBool_FALSE; +} + + + +/** + * POSTリクエストを送信する。 + * @return + * 引き続き処理が可能かを返す。 + */ +NyLPC_TBool NyLPC_cHttpClient_sendMethod( + NyLPC_TcHttpClient_t* i_inst, + NyLPC_THttpMethodType i_method, + const NyLPC_TChar* i_path, + NyLPC_TUInt32 i_content_length, + const NyLPC_TChar* i_mime_type, + const NyLPC_TChar* i_additional_header) +{ + //ステータスチェック + if(i_inst->_state!=NyLPC_TcHttpClient_ST_IDLE){ + NyLPC_OnErrorGoto(Error_0); + } + //POSTリクエストの送信 + if(!NyLPC_cHttpHeaderWriter_initialize(&i_inst->pw.head_writer,&i_inst->_stream.super,NULL)){ + NyLPC_OnErrorGoto(Error_0); + } + //ヘッダを送信 + NyLPC_cHttpHeaderWriter_setConnectionClose(&i_inst->pw.head_writer,NyLPC_TBool_TRUE);//Connection closeを強制 + if(i_content_length==NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED){ + NyLPC_cHttpHeaderWriter_setChunked(&i_inst->pw.head_writer); + }else{ + NyLPC_cHttpHeaderWriter_setContentLength(&i_inst->pw.head_writer,i_content_length); + } + if(!NyLPC_cHttpHeaderWriter_writeRequestHeader( + &i_inst->pw.head_writer, + i_method, + NyLPC_cTcpSocket_getPeerAddr(&(i_inst->_sock)), + NyLPC_cTcpSocket_getPeerPort(&(i_inst->_sock)),i_path)){ + NyLPC_OnErrorGoto(Error_1); + } + //MimeType + if(i_mime_type!=NULL){ + if(!NyLPC_cHttpHeaderWriter_writeMessage(&i_inst->pw.head_writer,"Content-type",i_mime_type)){ + NyLPC_OnErrorGoto(Error_1); + } + } + if(i_additional_header!=NULL){ + if(!NyLPC_cHttpHeaderWriter_writeRawMessage(&i_inst->pw.head_writer,i_additional_header)){ + NyLPC_OnErrorGoto(Error_1); + } + } + NyLPC_cHttpHeaderWriter_close(&i_inst->pw.head_writer); + NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer); + + //BodyWriter生成 + NyLPC_cHttpBodyWriter_initialize(&(i_inst->pw.body_writer),&(i_inst->_stream)); + //bodyのchunkedもセット + if(i_content_length==0xffffffff){ + NyLPC_cHttpBodyWriter_setChunked(&(i_inst->pw.body_writer)); + }else{ + NyLPC_cHttpBodyWriter_setContentLength(&(i_inst->pw.body_writer),i_content_length); + } + i_inst->_state=NyLPC_TcHttpClient_ST_SEND_REQ_BODY; + return NyLPC_TBool_TRUE; +Error_0: + return NyLPC_TBool_FALSE; +Error_1: + NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer); + return NyLPC_TBool_FALSE; +} + +/** + * POSTリクエストのデータを送信する。 + * @return + * 0:EOF + */ +NyLPC_TBool NyLPC_cHttpClient_write(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size) +{ + if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){ + return NyLPC_TBool_FALSE; + } + if(!NyLPC_cHttpBodyWriter_write(&i_inst->pw.body_writer,i_buf,i_buf_size)){ + //ERROR + NyLPC_cHttpClient_close(i_inst); + NyLPC_OnErrorGoto(Error); + } + return NyLPC_TBool_TRUE; +Error: + return NyLPC_TBool_FALSE; +} + +NyLPC_TBool NyLPC_cHttpClient_writeFormat(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,...) +{ + NyLPC_TBool ret; + va_list a; + if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){ + return NyLPC_TBool_FALSE; + } + va_start(a,i_fmt); + ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,a); + va_end(a); + if(!ret){ + NyLPC_cHttpClient_close(i_inst); + } + return ret; +} +NyLPC_TBool NyLPC_cHttpClient_writeFormatV(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args) +{ + NyLPC_TBool ret; + if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){ + return NyLPC_TBool_FALSE; + } + ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,i_args); + if(!ret){ + NyLPC_cHttpClient_close(i_inst); + } + return ret; +} + + +/** + * ステータスコードを返す。 + * @return + * ステータスコード + */ +NyLPC_TUInt16 NyLPC_cHttpClient_getStatus(NyLPC_TcHttpClient_t* i_inst) +{ + struct NyLPC_THttpBasicHeader header; + if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){ + return 0; + } + // + if(!NyLPC_cHttpBodyWriter_close(&i_inst->pw.body_writer)){ + NyLPC_OnErrorGoto(Error_1); + } + i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_HEAD; + //100を無視してHTTPヘッダをパース + //@todo POSTの時だけに制限したら? + do{ + NyLPC_cHttpBasicHeaderParser_initialize(&i_inst->pw.head_parser,NULL); + NyLPC_cHttpBasicHeaderParser_parseInit(&i_inst->pw.head_parser,&header); + if(!NyLPC_cHttpBasicHeaderParser_parseStream(&i_inst->pw.head_parser,&i_inst->_stream.super,&header)){ + NyLPC_OnErrorGoto(Error_2); + } + if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&i_inst->pw.head_parser,&header)){ + NyLPC_OnErrorGoto(Error_2); + } + NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser); + //レスポンスヘッダか確認 + if(header.type!=NyLPC_THttpHeaderType_RESPONSE){ + NyLPC_OnErrorGoto(Error_1); + } + }while(header.startline.res.status==100); + //BodyParserを起動 + NyLPC_cHttpBodyParser_initialize(&i_inst->pw.body_parser); + NyLPC_cHttpBodyParser_parseInit(&i_inst->pw.body_parser,&header); + i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_BODY; + return header.startline.res.status; +Error_1: + NyLPC_cHttpClient_close(i_inst); + return 0; +Error_2: + NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser); + NyLPC_cHttpClient_close(i_inst); + return 0; +} + + +/** + * GET/POSTリクエストで受信したデータを読み出す。 + * @param o_read_len + * 戻り値TRUEの場合のみ有効。 + * 終端の場合は0 + * @return + * TRUE:正常読み出し。o_read_lenの値で終端判定 + * FALSE:失敗。コネクションはクローズされる。 + */ +NyLPC_TBool NyLPC_cHttpClient_read(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size,NyLPC_TInt16* o_read_len) +{ + if(i_inst->_state!=NyLPC_TcHttpClient_ST_RECV_RES_BODY){ + return NyLPC_TBool_FALSE; + } + if(!NyLPC_cHttpBodyParser_parseStream(&i_inst->pw.body_parser,&i_inst->_stream.super,i_buf,i_buf_size,o_read_len)){ + NyLPC_cHttpClient_close(i_inst); + return NyLPC_TBool_FALSE; + } + return NyLPC_TBool_TRUE; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/net/httpcl/NyLPC_cHttpClient.h Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,133 @@ +/* + * NyLPC_cHttpClient.h + * + * Created on: 2013/08/24 + * Author: nyatla + */ + +#ifndef NYLPC_CHTTPCLIENT_H_ +#define NYLPC_CHTTPCLIENT_H_ + +#include "NyLPC_stdlib.h" +#include "NyLPC_net.h" +#include "NyLPC_http.h" +#include "NyLPC_uipService.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct NyLPC_TcHttpClient NyLPC_TcHttpClient_t; + +#define NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED 0xffffffff +struct NyLPC_TcHttpClient +{ + NyLPC_TUInt8 _state; + NyLPC_TUInt8 _padding1; + NyLPC_TcTcpSocket_t _sock; + NyLPC_TcHttpStream_t _stream; + union{ + NyLPC_TcHttpHeaderWriter_t head_writer; + NyLPC_TcHttpBodyWriter_t body_writer; + NyLPC_TcHttpBasicHeaderParser_t head_parser; + NyLPC_TcHttpBodyParser_t body_parser; + }pw; +}; + + +void NyLPC_cHttpClient_initialize(NyLPC_TcHttpClient_t* i_inst,void* i_rx_buf,NyLPC_TUInt16 i_rx_size); + +void NyLPC_cHttpClient_finalize(NyLPC_TcHttpClient_t* i_inst); + +/** + * サーバとの接続を切断する。 + * ステータスはCLOSEDになる。 + */ +void NyLPC_cHttpClient_close(NyLPC_TcHttpClient_t* i_inst); + + +/** + * サーバに接続する。 + * 関数はステータスをIDLEへ遷移する。 + * インスタンスのステータスは何でも構わない。 + * @return + * TRUE - ステータスはIDLEへ遷移する。 + * FALSE - ステータスはCLOSEDへ遷移する。 + */ +NyLPC_TBool NyLPC_cHttpClient_connect(NyLPC_TcHttpClient_t* i_inst,struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port); + + + +/** + * POSTリクエストを送信する。 + * ステータスはIDLEである必要がある。 + * @param i_content_length + * 送信bodyのサイズ。最大 0xfffffffe + * NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITEDの場合はChunked転送になる。 + * @return + * 引き続き処理が可能かを返す。 + * TRUE - 成功。ステータスはSEND_REQ_BODYになる。write/getStatusを呼び出せる。 + * FALSE - 失敗。ステータスはCLOSEDになる。 + */ +NyLPC_TBool NyLPC_cHttpClient_sendMethod( + NyLPC_TcHttpClient_t* i_inst, + NyLPC_THttpMethodType i_method, + const NyLPC_TChar* i_path, + NyLPC_TUInt32 i_content_length, + const NyLPC_TChar* i_mime_type, + const NyLPC_TChar* i_additional_header); + + +/** + * POSTリクエストのデータを送信する。 + * ステータスはSEND_REQ_BODYである必要がある。 + * @return + * TRUE - 成功。 + * FALSE - 失敗。ステータスはCLOSEDになる。 + */ +NyLPC_TBool NyLPC_cHttpClient_write(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size); + +/** + * 書式文字列としてPOSTリクエストのデータを送信する。 + * ステータスはSEND_REQ_BODYである必要がある。 + * @param i_fmt + * printfライクなフォーマット文字列 + * @return + * TRUE - 成功。 + * FALSE - 失敗。ステータスはCLOSEDになる。 + */ +NyLPC_TBool NyLPC_cHttpClient_writeFormat(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,...); +NyLPC_TBool NyLPC_cHttpClient_writeFormatV(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args); + +/** + * ステータスコードを返す。 + * ステータスはSEND_REQ_BODYである必要がある。 + * @return + * 0 - 失敗。ステータスはCLOSEDになる。 + * その他 - ステータスコード。ステータスはRECV_RES_BODYになる。 + */ +NyLPC_TUInt16 NyLPC_cHttpClient_getStatus(NyLPC_TcHttpClient_t* i_inst); + + +/** + * GET/POSTリクエストで受信したデータを読み出す。 + * ステータスはRECV_RES_BODYである必要がある。 + * @param o_read_len + * 戻り値TRUEの場合のみ有効。データ終端に達した場合は0になる。 + * @return + * TRUE:正常読み出し。o_read_lenの値で終端判定 + * FALSE:失敗。コネクションはクローズされる。 + */ +NyLPC_TBool NyLPC_cHttpClient_read(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size,NyLPC_TInt16* o_read_len); + + + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NYLPC_CHTTPCLIENT_H_ */ +
--- a/core/net/httpd/NyLPC_cHttpdConnection.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/net/httpd/NyLPC_cHttpdConnection.c Fri Sep 13 06:38:16 2013 +0000 @@ -81,7 +81,7 @@ //continueにセットされていたらcloseをFALSEに NyLPC_cHttpHeaderWriter_setConnectionClose(h,(i_inst->_connection_message_mode!=NyLPC_TcHttpdConnection_CONNECTION_MODE_CONTINUE)); - if(!NyLPC_cHttpHeaderWriter_writeHeader(h,i_response_code)){ + if(!NyLPC_cHttpHeaderWriter_writeResponseHeader(h,i_response_code)){ NyLPC_OnErrorGoto(ERROR_SEND); } if(!NyLPC_cHttpHeaderWriter_writeMessage(h,"Content-type",i_content_type)){ @@ -169,15 +169,13 @@ if(NyLPC_cHttpHeaderWriter_initialize(h,&i_inst->_in_stream.super,NULL)){ //ヘッダを送信 NyLPC_cHttpHeaderWriter_setConnectionClose(h,NyLPC_TBool_TRUE); - NyLPC_cHttpHeaderWriter_writeHeader(h,i_status); + NyLPC_cHttpHeaderWriter_writeResponseHeader(h,i_status); NyLPC_cHttpHeaderWriter_close(h); NyLPC_cHttpHeaderWriter_finalize(h); } } /** * 関数を実行後、_res_statusはCLOSEDかHEADかERRORに遷移する。 - * @return - * TRUE/FALSE TCPコネクションを切断するかどうかのフラグ */ NyLPC_TBool NyLPC_cHttpdConnection_closeResponse(NyLPC_TcHttpdConnection_t* i_inst) {
--- a/core/net/httpd/NyLPC_cHttpdConnection_protected.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/net/httpd/NyLPC_cHttpdConnection_protected.h Fri Sep 13 06:38:16 2013 +0000 @@ -42,9 +42,8 @@ /** - * 関数を実行後、_res_statusはCLOSEDかHEADかERRORに遷移する。 - * @return - * TRUE/FALSE TCPコネクションを切断するかどうかのフラグ + * コネクションをHTTPレベルで閉じます。 + * ResponseステータスはCLOSEDになります。Requestステータスは変化しません。 */ NyLPC_TBool NyLPC_cHttpdConnection_closeResponse(NyLPC_TcHttpdConnection_t* i_inst); @@ -62,7 +61,8 @@ NyLPC_TBool NyLPC_cHttpdConnection_acceptSocket(NyLPC_TcHttpdConnection_t* i_inst); /** - * ソケットをLISTEN状態に戻します。 + * コネクションのソケットを閉じます。 + * ResponseステータスはCLOSEDになり、RequestステータスはLISTENになります。 */ void NyLPC_cHttpdConnection_closeSocket(NyLPC_TcHttpdConnection_t* i_inst);
--- a/core/net/httpd/mod/NyLPC_cModFileIoBaseClass.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/net/httpd/mod/NyLPC_cModFileIoBaseClass.c Fri Sep 13 06:38:16 2013 +0000 @@ -30,8 +30,6 @@ #include "../NyLPC_cHttpdUtils.h" #include "NyLPC_net.h" -#define MVM_VERSION "ModFileIo/1.0;Json/1.0" - #define FNAME_MAX 48 #define STRBUF_MAX 48
--- a/core/net/httpd/mod/NyLPC_cModRomFiles.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/net/httpd/mod/NyLPC_cModRomFiles.c Fri Sep 13 06:38:16 2013 +0000 @@ -115,7 +115,7 @@ { NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); } - return NyLPC_cHttpdUtils_sendFixedContentBatch(i_connection,i_inst->_data[i].content_type,i_inst->_data[i].data,i_inst->_data[i].size>0?i_inst->_data[i].size:strlen(i_inst->_data[i].data)); + return NyLPC_cHttpdUtils_sendFixedContentBatch(i_connection,i_inst->_data[i].content_type,i_inst->_data[i].data,(i_inst->_data[i].size>0)?i_inst->_data[i].size:strlen(i_inst->_data[i].data)); } //404Error NyLPC_cHttpdUtils_sendErrorResponse(i_connection,404);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/net/httpd/mod/NyLPC_cModWebSocket.c Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,600 @@ +/********************************************************************************* + * 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_cModWebSocket.h" +#include "NyLPC_utils.h" + + + +#define NyLPC_TcModWebSocket_FRAME_TYPE_BIN 0x01 +#define NyLPC_TcModWebSocket_FRAME_TYPE_TXT 0x02 + + + +#define STRBUF_MAX 32 +struct TModWebSocketHeader +{ + struct NyLPC_THttpBasicHeader super; + NyLPC_TcStr_t _tstr; + NyLPC_TChar _tstr_buf[STRBUF_MAX]; + NyLPC_TChar key[24+4]; + NyLPC_TInt16 version; + NyLPC_TUInt8 sub_protocol_id; + NyLPC_TUInt8 message_id; + const NyLPC_TChar* _ref_sub_protocol; +}; + + + +#define MESSAGE_ID_UNKNOWN 0x00 +#define MESSAGE_ID_UPGRADE 0x01 +#define MESSAGE_ID_SEC_WEBSOCKET_KEY 0x02 +#define MESSAGE_ID_ORIGIN 0x03 +#define MESSAGE_ID_SEC_WEBSOCKET_PROTOCL 0x04 +#define MESSAGE_ID_SEC_WEBSOCKET_VERSION 0x05 + +static const struct NyLPC_TTextIdTbl msg_tbl[]= +{ + {"Upgrade",MESSAGE_ID_UPGRADE}, + {"Sec-WebSocket-Key",MESSAGE_ID_SEC_WEBSOCKET_KEY}, + {"Origin",MESSAGE_ID_ORIGIN}, + {"Sec-WebSocket-Protocol",MESSAGE_ID_SEC_WEBSOCKET_PROTOCL}, + {"Sec-WebSocket-Version",MESSAGE_ID_SEC_WEBSOCKET_VERSION}, + {NULL,MESSAGE_ID_UNKNOWN} +}; + +static NyLPC_TBool messageHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const NyLPC_TChar* i_name,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) +{ + struct TModWebSocketHeader* out=(struct TModWebSocketHeader*)o_out; + if(i_name!=NULL){ + out->message_id=NyLPC_TTextIdTbl_getMatchIdIgnoreCase(i_name,msg_tbl); + NyLPC_cStr_clear(&(out->_tstr)); + }else{ + switch(out->message_id) + { + case MESSAGE_ID_UPGRADE: + if(i_c!='\0'){ + if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ + NyLPC_OnErrorGoto(ERROR); + } + }else{ + //websocketかチェック + if(!NyLPC_cStr_isEqualIgnoreCase(&out->_tstr,"websocket")){ + return NyLPC_TBool_FALSE;//不一致 + } + } + break; + case MESSAGE_ID_SEC_WEBSOCKET_KEY: + if(i_c!='\0'){ + if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ + NyLPC_OnErrorGoto(ERROR); + } + }else{ + //HASH値をコピー + strcpy(out->key,NyLPC_cStr_str(&out->_tstr)); + } + break; + case MESSAGE_ID_SEC_WEBSOCKET_PROTOCL: + if(i_c!='\0' && i_c!=','){ + if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ + NyLPC_OnErrorGoto(ERROR); + } + }else{ + //トークン終端 + if(out->_ref_sub_protocol!=NULL){ + //サブプロトコルが指定されている場合はチェック + if(NyLPC_stricmp(NyLPC_cStr_str(&out->_tstr),out->_ref_sub_protocol)==0){ + out->sub_protocol_id=1;//SubProtocol一致 + } + } + //','の時はリセット + if(i_c!=','){ + NyLPC_cStr_clear(&(out->_tstr)); + } + } + break; + case MESSAGE_ID_SEC_WEBSOCKET_VERSION: + if(i_c!='\0'){ + if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ + NyLPC_OnErrorGoto(ERROR); + } + }else{ + //VERSION + out->version=atoi(NyLPC_cStr_str(&out->_tstr)); + if(out->version<0){ + NyLPC_OnErrorGoto(ERROR); + } + } + } + } + return NyLPC_TBool_TRUE; + ERROR: + return NyLPC_TBool_FALSE; +} + + + + +/** + * デフォルトハンドラ + */ +static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler= +{ + messageHandler, + NULL +}; +#define NyLPC_TcModWebSocket_ST_START_PAYLOAD 0x01 +#define NyLPC_TcModWebSocket_ST_READ_PAYLOAD 0x02 +#define NyLPC_TcModWebSocket_ST_CLOSED 0x03 + + +/** + * コンストラクタ。 + */ +void NyLPC_cModWebSocket_initialize(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_ref_root_path) +{ + NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_root_path,NULL,0); + i_inst->_frame_type=NyLPC_TcModWebSocket_FRAME_TYPE_TXT; + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED; +} +void NyLPC_cModWebSocket_finalize(NyLPC_TcModWebSocket_t* i_inst) +{ + NyLPC_cModRomFiles_finalize(&i_inst->super); +} +/** + * モジュールがコネクションをハンドリングできるかを返します。 + */ +NyLPC_TBool NyLPC_cModWebSocket_canHandle(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) +{ + return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection); +} + +static union{ + struct TModWebSocketHeader header; +}work; + + + +/** + * モジュールを実行します。 + */ +NyLPC_TBool NyLPC_cModWebSocket_execute(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) +{ + union{ + NyLPC_TcHttpBasicHeaderParser_t parser; + SHA1_CTX sh1; + }sh; + + //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却) + NyLPC_cHttpdConnection_setReqStatusParsed(i_connection); + + + + //排他ロック + NyLPC_cHttpdConnection_lock(i_connection); + {//parser + + //初期化 + work.header.version=0; + work.header.sub_protocol_id=0; + NyLPC_cStr_initialize(&work.header._tstr,work.header._tstr_buf,STRBUF_MAX); + + NyLPC_cHttpBasicHeaderParser_initialize(&sh.parser,&handler); + + //プリフェッチしたデータを流す + NyLPC_cHttpBasicHeaderParser_parseInit(&sh.parser,&(work.header.super)); + NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&sh.parser,&work.header.super); + //後続をストリームから取り込む + if(!NyLPC_cHttpBasicHeaderParser_parseStream(&sh.parser,NyLPC_cHttpdConnection_refStream(i_connection),&(work.header.super))){ + NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); + NyLPC_OnErrorGoto(Error1); + } + if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&sh.parser,&(work.header.super))){ + NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); + NyLPC_OnErrorGoto(Error1); + } + //HeaderParserはここで破棄(URLEncode,cSTRも) + NyLPC_cHttpBasicHeaderParser_finalize(&sh.parser); + + NyLPC_cStr_finalize(&single_header._tstr); + + + //HTTP/1.1であること。Connection:Upgradeはチェックしない。 + if(work.header.super.startline.req.version!=NyLPC_THttpVersion_11) + { + NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400); + NyLPC_OnErrorGoto(Error2); + } + if(NyLPC_cHttpdConnection_getMethod(i_connection)!=NyLPC_THttpMethodType_GET){ + NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400); + NyLPC_OnErrorGoto(Error2); + } + //WebSocket version 13であること + if(work.header.version!=13){ + NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400); + NyLPC_OnErrorGoto(Error2); + } + + //レスポンスの生成(生データを直接ストリームへ書きこむ) + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection), + "HTTP/1.1 101 Switching Protocols\r\n" //32+2 + "Upgrade: websocket\r\n" //18+2 + "Connection: Upgrade\r\n" //19+2 + "Sec-WebSocket-Accept: " //22 + ,32+2+18+2+19+2+22)){ + NyLPC_OnErrorGoto(Error3); + } + //SH1キーの生成 + SHA1Init(&sh.sh1); + SHA1Update(&sh.sh1,(const unsigned char*)work.header.key,strlen(work.header.key)); + SHA1Update(&sh.sh1,(const unsigned char*)"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",36); + //ワークメモリ32バイトはstrの使いまわし + SHA1Final((unsigned char*)(work.header._tstr_buf),&sh.sh1); + //BASE64化(single_header.keyへ出力) + NyLPC_cBase64_encode(work.header._tstr_buf,20,work.header.key); + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection),work.header.key,28)){ + NyLPC_OnErrorGoto(Error3); + } + //SubProtocolの認証が有る場合 + if(work.header.sub_protocol_id!=0){ + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection) + ,"\r\nSec-WebSocket-Protocol: " //24 + ,24)){ + NyLPC_OnErrorGoto(Error3); + } + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection) + ,work.header._ref_sub_protocol + ,strlen(work.header._ref_sub_protocol))) + { + NyLPC_OnErrorGoto(Error3); + } + } + //Sec-WebSocket-Protocol + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection),"\r\n\r\n",4)){ + NyLPC_OnErrorGoto(Error3); + } + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD; + } +//占有解除 + NyLPC_cHttpdConnection_unlock(i_connection); + //参照コネクションの設定 + i_inst->_ref_connection=i_connection; + NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection)); + return NyLPC_TBool_TRUE; +Error3: +Error2: + //VM排他ロックの解除 + NyLPC_cHttpdConnection_unlock(i_connection); + return NyLPC_TBool_FALSE; +Error1: + NyLPC_cHttpBasicHeaderParser_finalize(&parser); + NyLPC_cStr_finalize(&single_header._tstr); + //VM排他ロックの解除 + NyLPC_cHttpdConnection_unlock(i_connection); + return NyLPC_TBool_FALSE; +} + + + +static void writeClosePacket(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code) +{ + char w[4]; + w[0]=0x88; + w[1]=0x02; + *((NyLPC_TUInt16*)(&w[2]))=NyLPC_htons(i_code); //REASON + //CloseFrame送信 + NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,4); + NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection)); +} + + +#define FLAGS_MASK_BIT 7 +/** + * @return + * n>0:データ受信 + * 0 :タイムアウト。コネクションの状態は変化しない。 + * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。 + */ +NyLPC_TInt16 NyLPC_cModWebSocket_read(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_buf_len) +{ + const NyLPC_TUInt8* rx; + NyLPC_TInt32 rs,i; + NyLPC_TUInt16 header_size; + NyLPC_TUInt8 w8[2]; + if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){ + return -1; + } +START: + rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx); + //Error? + if(rs<0){ + NyLPC_OnErrorGoto(Error); + } + //Timeout? + if(rs==0){ + goto Timeout; + } + switch(i_inst->_payload_st){ + case NyLPC_TcModWebSocket_ST_START_PAYLOAD: + //ペイロード + //2バイト溜まるまで待つ + if(rs<2){ + //Timeout? + goto Timeout; + } + //ペイロードサイズの分析 + if((0x7f&rx[1])<=125){ + header_size=2+(((rx[1]&0x80)==0x80)?4:0); + i_inst->payload_size=(0x7f&rx[1]); + }else if((0x7f&rx[1])==126){ + if(rs<4){ + //Timeout? + goto Timeout; + } + header_size=2+2+(((rx[1]&0x80)==0x80)?4:0); + i_inst->payload_size=(rx[2]<<8)|rx[3]; + }else{ + //CLOSEの送信 + writeClosePacket(i_inst,1009); + NyLPC_OnErrorGoto(Error); + } + //十分なヘッダが集まったかチェック + if(rs<header_size){ + goto Timeout; + } + i_inst->_frame_flags_bits=0; + //FINがセットされていること.断片化禁止! + if((rx[0]&0x80)!=0x80){ + NyLPC_OnErrorGoto(Error); + } + //必要ならMaskをコピー + if((rx[1]&0x80)==0x80){ + memcpy(i_inst->_frame_mask,(rx+header_size-4),4); + NyLPC_TUInt8_setBit(i_inst->_frame_flags_bits,FLAGS_MASK_BIT); + } + i_inst->payload_ptr=0; + + //パケットサイズの確定(基本ヘッダ+マスク) + switch(rx[0]&0x0f){ + case 0x00: + //継続パケットは扱わない + NyLPC_OnErrorGoto(Error); + case 0x01: + if(i_inst->_frame_type!=NyLPC_TcModWebSocket_FRAME_TYPE_TXT){ + NyLPC_OnErrorGoto(Error); + } + break; + case 0x02: + if(i_inst->_frame_type==NyLPC_TcModWebSocket_FRAME_TYPE_BIN){ + NyLPC_OnErrorGoto(Error); + } + break; + case 0x08://close(非断片) + //CloseFrame送信 + writeClosePacket(i_inst,1009); + //Errorとして処理 + NyLPC_OnErrorGoto(Error); + case 0x09://ping(非断片) + //PONGを送信 + w8[0]=0x0a; + NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w8,1); + NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx+1,header_size-1); + NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection)); + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size); + while(i_inst->payload_size!=i_inst->payload_ptr){ + rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx); + if(rs<=0){ + if(rs<0){ + //Error + NyLPC_OnErrorGoto(Error); + } + //Timeout + goto Timeout; + } + //読み込みサイズを決定 + rs=(rs<i_buf_len)?rs:i_buf_len; + NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx,rs); + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs); + i_inst->payload_ptr+=rs; + } + //Timeout(パケットスタートに戻る?) + goto START; + case 0x0a://pong(非断片) + //パケットの読み捨て + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size); + while(i_inst->payload_size!=i_inst->payload_ptr){ + rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx); + if(rs<=0){ + if(rs<0){ + //Error + NyLPC_OnErrorGoto(Error); + } + //Timeout + goto Timeout; + } + //読み込みサイズを決定 + rs=(rs<i_buf_len)?rs:i_buf_len; + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs); + i_inst->payload_ptr+=rs; + } + //Timeout(パケットスタートに戻る?) + goto START; + default: + //知らないコードはエラー + NyLPC_OnErrorGoto(Error); + } + //読み出し位置のシーク(Header部) + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size); + //ペイロード読み出しへ + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_READ_PAYLOAD; + //継続してペイロード受信処理 + case NyLPC_TcModWebSocket_ST_READ_PAYLOAD: + rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx); + if(rs<=0){ + if(rs<0){ + //Error + NyLPC_OnErrorGoto(Error); + } + //Timeout + goto Timeout; + } + //読み込みサイズを決定 + rs=(rs<i_buf_len)?rs:i_buf_len; + //アンマスク + if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){ + for(i=0;i<rs;i++){ + *(((NyLPC_TUInt8*)i_buf)+i)=rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4]; + } + }else{ + memcpy(i_buf,rx,rs); + } + //読取位置を移動 + NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs); + i_inst->payload_ptr+=rs; + if(i_inst->payload_size==i_inst->payload_ptr){ + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD; + } + return rs; + } + //処理されなければエラー +Error: + NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection); + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED; + return -1; +Timeout: + return 0; +} + +static NyLPC_TBool fmt_handler(void* i_inst,const void* i_buf,NyLPC_TUInt32 i_len) +{ + return NyLPC_iHttpPtrStream_write((NyLPC_TiHttpPtrStream_t*)i_inst,i_buf,i_len); +} + +NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...) +{ + va_list a; + NyLPC_TInt16 l; + NyLPC_TUInt16 s; + NyLPC_TChar w[4]; + //データサイズで切り分け + if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){ + return NyLPC_TBool_FALSE; + } + //書式文字列の長さを計算 + va_start(a,i_fmt); + l=NyLPC_cFormatWriter_length(i_fmt,a); + va_end(a); + switch(i_inst->_frame_type) + { + case NyLPC_TcModWebSocket_FRAME_TYPE_TXT: + w[0]=0x80|0x01; + break; + case NyLPC_TcModWebSocket_FRAME_TYPE_BIN: + w[0]=0x80|0x02; + break; + default: + NyLPC_OnErrorGoto(Error); + } + if(l<126){ + w[1]=(NyLPC_TUInt8)l; + s=2; + }else{ + w[1]=126; + s=3; + *((NyLPC_TUInt16*)(&(w[2])))=NyLPC_htons(l); + } + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,s)){ + //CLOSE + NyLPC_OnErrorGoto(Error); + } + va_start(a,i_fmt); + if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,a)){ + va_end(a); + NyLPC_OnErrorGoto(Error); + } + va_end(a); + NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection)); + return NyLPC_TBool_TRUE; +Error: + NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection); + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED; + return NyLPC_TBool_FALSE; +} + +NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_len) +{ + NyLPC_TChar w[4]; + NyLPC_TUInt16 s; + //データサイズで切り分け + if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){ + return NyLPC_TBool_FALSE; + } + //OP CODE + switch(i_inst->_frame_type) + { + case NyLPC_TcModWebSocket_FRAME_TYPE_TXT: + w[0]=0x80|0x01; + break; + case NyLPC_TcModWebSocket_FRAME_TYPE_BIN: + w[0]=0x80|0x02; + break; + default: + NyLPC_OnErrorGoto(Error); + } + if(i_len<126){ + w[1]=(NyLPC_TUInt8)i_len; + s=2; + }else{ + w[1]=126; + s=3; + *((NyLPC_TUInt16*)(&(w[2])))=NyLPC_htons(i_len); + } + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,s)){ + //CLOSE + NyLPC_OnErrorGoto(Error); + } + if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_buf,i_len)){ + //CLOSE + NyLPC_OnErrorGoto(Error); + } + NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection)); + return NyLPC_TBool_TRUE; +Error: + NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection); + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED; + return NyLPC_TBool_FALSE; +} + +void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code) +{ + if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){ + return; + } + //CLOSE送信 + writeClosePacket(i_inst,i_code); + i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED; + //切断 + NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/net/httpd/mod/NyLPC_cModWebSocket.h Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,122 @@ +#ifndef NYLPC_CMODWEBSOCKET_H_ +#define NYLPC_CMODWEBSOCKET_H_ + +/********************************************************************************* + * 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_stdlib.h" +#include "NyLPC_http.h" +#include "../NyLPC_cHttpdConnection_protected.h" +#include "../NyLPC_cHttpdUtils.h" +#include "NyLPC_net.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * ファイルアップロードの為の基本シーケンスを提供する抽象クラスです。 + * 継承クラスで_abstruct_function以下の関数に実体を設定して使います。 + */ +typedef struct NyLPC_TcModWebSocket NyLPC_TcModWebSocket_t; + + +#define NyLPC_TcModWebSocket_FRAME_TYPE_BIN 0x01 +#define NyLPC_TcModWebSocket_FRAME_TYPE_TXT 0x02 + +/** + * クラス構造体 + */ +struct NyLPC_TcModWebSocket +{ + NyLPC_TcModRomFiles_t super; + /** + * サブプロトコル。NULLの場合0 + */ + const NyLPC_TChar* _ref_sub_protocol; + /**ペイロードの解析ステータス*/ + NyLPC_TUInt8 _payload_st; + NyLPC_TUInt8 _frame_type; + /** + * BIT0: MASK value + */ + NyLPC_TUInt8 _frame_flags_bits; + NyLPC_TUInt8 _frame_mask[4]; + /** ペイロードサイズ*/ + NyLPC_TUInt16 payload_size; + /** ペイロード位置*/ + NyLPC_TUInt16 payload_ptr; + NyLPC_TcHttpdConnection_t* _ref_connection; +}; + +/** + * コンストラクタ。 + */ +void NyLPC_cModWebSocket_initialize(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_ref_root_path); + +void NyLPC_cModWebSocket_finalize(NyLPC_TcModWebSocket_t* i_inst); + +/** + * モジュールがコネクションをハンドリングできるかを返します。 + */ +NyLPC_TBool NyLPC_cModWebSocket_canHandle(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection); + +/** + * モジュールを実行します。 + */ +NyLPC_TBool NyLPC_cModWebSocket_execute(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection); + + +/** + * i_bufに最大i_buf_lenバイトのデータを受信します。 + * @return + * n>0:受信成功。nバイトのデータを受信した。 + * 0 :タイムアウト。コネクションの状態は変化しない。 + * -1 :エラー。 コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。 + */ +NyLPC_TInt16 NyLPC_cModWebSocket_read(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_buf_len); +/** + * i_bufからi_lenバイトのデータを送信します。データは1ペーロードとしてクライアントへ送信されます。 + * @return + * true: 送信に成功した。 + * false:送信に失敗した。 コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。 + */ +NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_len); +/** + * 書式文字列を出力します。 + */ +NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...); + +/** + * CLOSEパケットを送信してコネクションを閉じます。 + * i_codeにはWebsocketのコード + */ +void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NYLPC_CMODWEBSOCKET_H_ */
--- a/core/net/upnp/NyLPC_cSsdpSocket.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/net/upnp/NyLPC_cSsdpSocket.c Fri Sep 13 06:38:16 2013 +0000 @@ -75,38 +75,7 @@ // *であるかを確認 未実装 return NyLPC_TBool_TRUE; } -static NyLPC_TInt16 printIpAddr(const struct NyLPC_TIPv4Addr* i_ip,NyLPC_TChar* i_buf) -{ - NyLPC_TUInt32 ip; - NyLPC_TUInt8 v; - NyLPC_TInt8 l; - NyLPC_TChar* p=i_buf; - //IPをホストオーダーにする。 - ip=NyLPC_NTOHL(i_ip->v); - for(l=3;l>=0;l--){ - v=(ip>>(8*l))&0xff; - if(v<10){ - //1桁 - *(p+0)=v+'0'; - *(p+1)='.'; - p+=2; - }else if(v<100){ - //2桁 - *(p+0)=(v/10)+'0'; - *(p+1)=(v%10)+'0'; - *(p+2)='.'; - p+=3; - }else{ - //3桁 - *(p+0)=(v/100)+'0'; - *(p+1)=((v/10)%10)+'0'; - *(p+2)=(v%10)+'0'; - *(p+3)='.'; - p+=4; - } - } - return p-i_buf-1; -} + #define TIMEOUT_IN_MS 100 /** @@ -137,7 +106,7 @@ { NyLPC_TChar* obuf; NyLPC_TUInt16 l; - NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)(i_usn!=NULL?strlen(i_usn):0); + NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)((i_usn!=NULL)?strlen(i_usn):0); NyLPC_TUInt16 len_udn=(NyLPC_TUInt16)strlen(i_udn); NyLPC_TUInt16 len_location=(NyLPC_TUInt16)strlen(i_inst->location_path); @@ -171,7 +140,7 @@ "LOCATION: http://"); l+=strlen(obuf); //IP addr:port\r\n - l+=printIpAddr(NyLPC_cUdpSocket_getSockIP(&i_inst->super),obuf+l); + l+=NyLPC_TIPv4Addr_toString(NyLPC_cUdpSocket_getSockIP(&i_inst->super),obuf+l); *(obuf+l)=':'; l+=1+NyLPC_itoa(i_inst->location_port,obuf+l+1,10); *(obuf+l)='/';l++; @@ -220,7 +189,7 @@ { NyLPC_TChar* obuf; NyLPC_TUInt16 l,l2; - NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)(i_usn!=NULL?strlen(i_usn):0); + NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)((i_usn!=NULL)?strlen(i_usn):0); NyLPC_TUInt16 len_udn=(NyLPC_TUInt16)strlen(i_udn); NyLPC_TUInt16 len_location=(NyLPC_TUInt16)strlen(i_inst->location_path); @@ -233,7 +202,7 @@ // "LOCATION: http://xxx.xxx.xxx.xxx:nnnnn/%s/d.xml\r\n"//44+2=46 // "USN: %s%s\r\n" //5+2=7 // "NT: %s\r\n\r\n" //4+4=8 - l2=204+len_location+len_usn+len_udn+(len_usn>0?len_usn:len_udn); + l2=204+len_location+len_usn+len_udn+((len_usn>0)?len_usn:len_udn); obuf=NyLPC_cUdpSocket_allocSendBuf(&(i_inst->super),l2,&l,TIMEOUT_IN_MS); if(obuf==NULL){ return NULL; @@ -255,7 +224,7 @@ "LOCATION: http://"); l+=strlen(obuf); //IP addr:port\r\n - l+=printIpAddr(NyLPC_cUdpSocket_getSockIP(&i_inst->super),obuf+l); + l+=NyLPC_TIPv4Addr_toString(NyLPC_cUdpSocket_getSockIP(&i_inst->super),obuf+l); *(obuf+l)=':'; l+=1+NyLPC_itoa(i_inst->location_port,obuf+l+1,10); *(obuf+l)='/';l++;
--- a/core/uip/NyLPC_cBaseSocket.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cBaseSocket.c Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,9 @@ +#include "NyLPC_cBaseSocket.h" +#include "NyLPC_cUipService_protected.h" + +void NyLPC_cBaseSocket_initialize(NyLPC_TcBaseSocket_t* i_inst,NyLPC_TUInt8 i_typeid) +{ + NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst; + i_inst->_typeid=i_typeid; + i_inst->_parent_ipv4=&(srv->_tcpv4); +}
--- a/core/uip/NyLPC_cBaseSocket.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cBaseSocket.h Fri Sep 13 06:38:16 2013 +0000 @@ -30,6 +30,7 @@ #endif /* __cplusplus */ #include "NyLPC_stdlib.h" +#include "NyLPC_cIPv4_typedef.h" /** * Base socket class @@ -44,9 +45,13 @@ struct NyLPC_TcBaseSocket { /**タイプID 継承クラスのinitializerで設定。 */ - NyLPC_TUInt32 _typeid; + NyLPC_TUInt8 _typeid; + NyLPC_TUInt8 _padding8; + NyLPC_TUInt16 _padding16; + /** 所属してるIPv4コンローラ*/ + NyLPC_TcIPv4_t* _parent_ipv4; }; -#define NyLPC_cBaseSocket_initialize(i_inst,i_typeid) ((i_inst)->_typeid=i_typeid) +void NyLPC_cBaseSocket_initialize(NyLPC_TcBaseSocket_t* i_inst,NyLPC_TUInt8 i_typeid); #define NyLPC_cBaseSocket_finalize(i_inst)
--- a/core/uip/NyLPC_cIPv4.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cIPv4.c Fri Sep 13 06:38:16 2013 +0000 @@ -170,7 +170,40 @@ } return NULL; } - +/** + * 指定番号のTCPポートが未使用かを返す。 + * @return + * i_lport番のポートが未使用であればTRUE + */ +static NyLPC_TBool cSocketTbl_isClosedTcpPort( + NyLPC_TcPtrTbl_t* i_inst, + NyLPC_TUInt16 i_lport) +{ + NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf); + NyLPC_TcTcpSocket_t* tp; + int i; + //一致するポートを検索 + for(i=i_inst->size-1;i>=0;i--){ + if(p[i]==NULL){ + continue; + } + if(p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_TCP_SOCK){ + tp=((NyLPC_TcTcpSocket_t*)p[i]); + //TCPソケット && !クローズ && ポート一致なら使用中 + if((tp->tcpstateflags!=UIP_CLOSED) && tp->uip_connr.lport==i_lport){ + return NyLPC_TBool_FALSE; + } + } + if(p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_TCP_LISTENER){ + //Listenerソケット && ポート一致なら使用中 + if(((NyLPC_TcTcpListener_t*)p[i])->_port==i_lport){ + return NyLPC_TBool_FALSE; + } + } + } + //未使用 + return NyLPC_TBool_TRUE; +} /** * テーブルにある有効なソケットのperiodicをすべて呼び出します。 */ @@ -273,6 +306,7 @@ //instanceの初期化 NyLPC_cMutex_initialize(&(i_inst->_sock_mutex)); NyLPC_cMutex_initialize(&(i_inst->_listener_mutex)); + i_inst->tcp_port_counter=0; i_inst->_ref_config=NULL; return; } @@ -399,10 +433,24 @@ return NyLPC_TBool_FALSE; } +NyLPC_TUInt16 NyLPC_cIPv4_getNewPortNumber(NyLPC_TcIPv4_t* i_inst) +{ + NyLPC_TUInt16 i,n; + for(i=0;i<0x0fff;i--){ + i_inst->tcp_port_counter=(i_inst->tcp_port_counter+1)%0x0fff; + n=i_inst->tcp_port_counter+49152; + if(cSocketTbl_isClosedTcpPort(&i_inst->_socket_tbl,n)) + { + return n; + } + } + return 0; +} + /********************************************************************** * - * public function + * packet handler * **********************************************************************/
--- a/core/uip/NyLPC_cIPv4.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cIPv4.h Fri Sep 13 06:38:16 2013 +0000 @@ -71,24 +71,14 @@ #endif /* __cplusplus */ -/** - * クラス型を定義します。 - * NyLPC_cIPv4クラスは、NyLPC_cUipServiceクラスの一部として働きます。 - * 通常ユーザが操作することはありません。 - * IPv4における、ソケットクラス(NyLPC_cTcpSocketとNyLPC_cTcpListener)の管理を担当します。 - * クラスのインスタンスは、NyLPC_cUipServiceのインスタンスにより生成されます。 - * インスタンスは2つのポインタリストをもち、ここにこれらのインスタンスを登録します。 - * インスタンスは、NyLPC_cUipServiceから送られてきた受信パケットを、登録されているソケットクラスに - * ディスパッチする機能を持ちます。 - */ -typedef struct NyLPC_TcIPv4 NyLPC_TcIPv4_t; + /********************************************************************** * * class NyLPC_TcIPv4 * **********************************************************************/ - +#include "NyLPC_cIPv4_typedef.h" ///** // * 環境定数です。NyLPC_TcTcpListenerインスタンスリストの数を設定します。 @@ -119,6 +109,8 @@ NyLPC_TcPtrTbl_t _socket_tbl; /** _socket_tblが使用するメモリ領域です。*/ NyLPC_TcBaseSocket_t* _socket_array_buf[NyLPC_cIPv4_MAX_SOCKET]; + /** 0-0xfffまでを巡回するカウンタ*/ + NyLPC_TUInt16 tcp_port_counter; }; /** @@ -225,6 +217,15 @@ */ #define NyLPC_cIPv4_getListenerMutex(i_inst) (&((i_inst)->_listener_mutex)) +/** + * ポート0で使用するポート番号を返します。 + * @return + * 49152 - (49152+0x0ffff)番までのポートのうち、使用中でないポート番号を返します。 + * エラー時は0です。 + */ +NyLPC_TUInt16 NyLPC_cIPv4_getNewPortNumber(NyLPC_TcIPv4_t* i_inst); + + #ifdef __cplusplus } #endif /* __cplusplus */
--- a/core/uip/NyLPC_cIPv4Config.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cIPv4Config.h Fri Sep 13 06:38:16 2013 +0000 @@ -57,15 +57,15 @@ */ struct NyLPC_TcIPv4Config { - /** イーサネットアドレスを格納します。*/ + /** イーサネットアドレスを格納します。 */ struct NyLPC_TEthAddr eth_mac; - /** IPアドレスを格納します。Network orderです。*/ + /** IPアドレスを格納します。Network orderです。 */ struct NyLPC_TIPv4Addr ip_addr; - /** ネットマスクを格納します。Network orderです。*/ + /** ネットマスクを格納します。Network orderです。 */ struct NyLPC_TIPv4Addr netmask; - /** デフォルトゲートウェイアドレスを格納します。Network orderです。*/ + /** デフォルトゲートウェイアドレスを格納します。Network orderです。 */ struct NyLPC_TIPv4Addr dr_addr; - /** デフォルトMMSサイズです。送信パケットのMSS値、受信パケットのデフォルトMSS値として使います。*/ + /** デフォルトMMSサイズです。送信パケットのMSS値、受信パケットのデフォルトMSS値として使います。 */ NyLPC_TUInt16 default_mss; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/uip/NyLPC_cIPv4_typedef.h Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,17 @@ +#ifndef NYLPC_CIPV4_TYPEDEF_H_ +#define NYLPC_CIPV4_TYPEDEF_H_ + +/** + * クラス型を定義します。 + * NyLPC_cIPv4クラスは、NyLPC_cUipServiceクラスの一部として働きます。 + * 通常ユーザが操作することはありません。 + * IPv4における、ソケットクラス(NyLPC_cTcpSocketとNyLPC_cTcpListener)の管理を担当します。 + * クラスのインスタンスは、NyLPC_cUipServiceのインスタンスにより生成されます。 + * インスタンスは2つのポインタリストをもち、ここにこれらのインスタンスを登録します。 + * インスタンスは、NyLPC_cUipServiceから送られてきた受信パケットを、登録されているソケットクラスに + * ディスパッチする機能を持ちます。 + */ +typedef struct NyLPC_TcIPv4 NyLPC_TcIPv4_t; + +#endif /* NYLPC_CIPV4_PUBLIC_H_ */ +
--- a/core/uip/NyLPC_cTcpListener.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cTcpListener.c Fri Sep 13 06:38:16 2013 +0000 @@ -98,9 +98,10 @@ - -#define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_mutex)) -#define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_mutex)) +//#define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_mutex)) +//#define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_mutex)) +#define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getListenerMutex(((i_inst)->_super._parent_ipv4))) +#define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getListenerMutex(((i_inst)->_super._parent_ipv4))) /** @@ -114,8 +115,8 @@ //uipサービスは初期化済であること。 NyLPC_Assert(NyLPC_TcUipService_isInitService()); //初期化 - // NyLPC_cMutex_initialize(&(i_inst->_mutex)); - i_inst->_mutex=NyLPC_cIPv4_getListenerMutex(&srv->_tcpv4);// NyLPC_cMutex_initialize(&(i_inst->_mutex)); +// // NyLPC_cMutex_initialize(&(i_inst->_mutex)); +// i_inst->_mutex=NyLPC_cIPv4_getListenerMutex(&srv->_tcpv4);// NyLPC_cMutex_initialize(&(i_inst->_mutex)); i_inst->_port=NyLPC_htons(i_port); //管理リストへ登録。 return NyLPC_cIPv4_addSocket(&(srv->_tcpv4),&(i_inst->_super));
--- a/core/uip/NyLPC_cTcpListener.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cTcpListener.h Fri Sep 13 06:38:16 2013 +0000 @@ -65,11 +65,11 @@ { NyLPC_TcBaseSocket_t _super; NyLPC_TUInt16 _port; /**<ネットワークオーダーのポート番号*/ - /** - * タスク間の調停用Mutex - * Listener用の共通Mutexポインタ - */ - NyLPC_TcMutex_t* _mutex; +// /** +// * タスク間の調停用Mutex +// * Listener用の共通Mutexポインタ +// */ +// NyLPC_TcMutex_t* _mutex; /** * SYNパケットのキュー */
--- a/core/uip/NyLPC_cTcpSocket.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cTcpSocket.c Fri Sep 13 06:38:16 2013 +0000 @@ -31,6 +31,29 @@ static NyLPC_TUInt32 iss32=3939; #define SIZE_OF_IPv4_TCPIP_HEADER 40 +/** + * TCPのRTOの最大値。 + * ms単位である。 + * defaultは64SEC + */ +#define UIP_IP_RTO_MAX_RTO 64000 +/** + * TCPのRTOの初期値。 + * ms単位である。 + * 伝送路の特性に合わせて調整すること。 + */ +#define UIP_TCP_RTO_INITIAL 3000 + +/** + * CONNECTION時のRTO + */ +#define UIP_TCP_RTO_CONNECTION_INITIAL 200 + +/** + * 下限値 + */ +#define UIP_TCP_RTO_MINIMUM 100 + /** * for Debug @@ -44,11 +67,10 @@ #define DEBUG_RTO_LOG(i_inst) #endif - //#define lockResource(i_inst) NyLPC_cMutex_lock(&((i_inst)->_smutex)) //#define unlockResource(i_inst) NyLPC_cMutex_unlock(&((i_inst)->_smutex)) -#define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_smutex)) -#define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_smutex)) +#define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4))) +#define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4))) static void sendRst(NyLPC_TcTcpSocket_t* i_inst); @@ -225,8 +247,8 @@ break; } NyLPC_cStopwatch_finalize(&sw); - if(new_rto<UIP_IP_RTO_MINIMUM){ - new_rto=UIP_IP_RTO_MINIMUM; + if(new_rto<UIP_TCP_RTO_MINIMUM){ + new_rto=UIP_TCP_RTO_MINIMUM; } i_inst->uip_connr.current_rto32=new_rto; } @@ -312,7 +334,7 @@ NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len); // NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));//個別Mutex - i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex +// i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex i_inst->tcpstateflags=UIP_CLOSED; i_inst->txbuf.rp=i_inst->txbuf.wp=0; for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){ @@ -356,7 +378,7 @@ { //localipとdefault_mmsは別枠で設定 /* Fill in the necessary fields for the new connection. */ - i_inst->uip_connr.current_rto32 = UIP_IP_RTOP_INITIAL; + i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL; i_inst->uip_connr.lport = i_lport; i_inst->uip_connr.rport = i_lq->rport; i_inst->uip_connr.ripaddr=i_lq->srcaddr; @@ -364,20 +386,17 @@ /* rcv_nxt should be the seqno from the incoming packet + 1. */ i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32; //MSSの設定 - i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss; - if(i_lq->mss!=0){ - i_inst->uip_connr.peer_mss=i_lq->mss; - } + i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss; i_inst->uip_connr.peer_win=0; NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf)); + //ここでステータスがかわる。 + i_inst->tcpstateflags = UIP_SYN_RCVD; //前回のデータが残っていた場合の保険 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){ resetTxQWithUnlock(i_inst); }else{ unlockResource(i_inst); } - //ここでステータスがかわる。 - i_inst->tcpstateflags = UIP_SYN_RCVD; return NyLPC_TBool_TRUE; } unlockResource(i_inst); @@ -496,7 +515,7 @@ s=i_len; } //ACK番号の計算 - next_ack=i_inst->uip_connr.snd_nxt32+s+((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00?1:0); + next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0); txq->rto32=i_inst->uip_connr.current_rto32; txq->tick_of_sent=NyLPC_cStopwatch_now(); @@ -561,6 +580,7 @@ //エラー:ドロップする。 return NyLPC_TBool_FALSE; } + return NyLPC_TBool_TRUE; } @@ -571,6 +591,77 @@ * Public function */ +NyLPC_TBool NyLPC_cTcpSocket_connect(NyLPC_TcTcpSocket_t* i_inst,struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec) +{ + volatile NyLPC_TUInt8 f; + NyLPC_TUInt32 sq; + NyLPC_TcStopwatch_t sw; + NyLPC_TUInt16 lport; + lockResource(i_inst); + //ソケットが無効であること。 + if(i_inst->tcpstateflags!=UIP_CLOSED) + { + NyLPC_OnErrorGoto(Error); + } + //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して) + lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(i_inst->_super._parent_ipv4)); + if(lport==0){ + NyLPC_OnErrorGoto(Error); + } + //connectの為の準備 + + //localipとdefault_mmsは別枠で設定 + /* Fill in the necessary fields for the new connection. */ + i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。 + i_inst->uip_connr.lport = lport; + i_inst->uip_connr.rport = NyLPC_htons(i_peer_port); + i_inst->uip_connr.ripaddr=*i_addr; + i_inst->uip_connr.snd_nxt32=iss32;//should be random + /* rcv_nxt should be the seqno from the incoming packet + 1. */ + i_inst->uip_connr.rcv_nxt32=0; + //MSSの設定 + i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss; + i_inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。 + NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf)); + //ここでステータスがかわる。 + i_inst->tcpstateflags = UIP_SYN_SENT; + //前回のデータが残っていた場合の保険 + if(i_inst->txbuf.rp!=i_inst->txbuf.wp){ + resetTxQWithUnlock(i_inst); + }else{ + unlockResource(i_inst); + } + + NyLPC_cStopwatch_initialize(&sw); + + NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec); + if(sendWithRetransmit(i_inst,TCP_SYN,NULL,0,&sw,&sq)==0){ + //ちょっと待つ。 + NyLPC_cThread_yield(); + //キューにあるTXが消えるのを待つ。 + if(waitForTxRemove(i_inst,sq,&sw)){ + //ACK受信に成功して、TXが消失 + NyLPC_cStopwatch_finalize(&sw); + return NyLPC_TBool_TRUE; + } + } + //ロックして、強制的なステータス遷移 + lockResource(i_inst); + f=i_inst->tcpstateflags; + if(f!=UIP_CLOSED){ + //もし、強制CLOSE遷移であれば、RSTも送信。 + i_inst->tcpstateflags=UIP_CLOSED; + unlockResource(i_inst); + sendRst(i_inst); + }else{ + unlockResource(i_inst); + } + return NyLPC_TBool_FALSE; +Error: + unlockResource(i_inst); + return NyLPC_TBool_FALSE; +} + /** * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。 * cTcpListener_listen関数を通過したインスタンスに実行してください。 @@ -612,12 +703,12 @@ lockResource(i_inst); f=i_inst->tcpstateflags; if(f!=UIP_CLOSED){ + //もし、強制CLOSE遷移であれば、RSTも送信。 i_inst->tcpstateflags=UIP_CLOSED; - } - unlockResource(i_inst); - //もし、強制CLOSE遷移であれば、RSTも送信。 - if(f!=UIP_CLOSED){ + unlockResource(i_inst); sendRst(i_inst); + }else{ + unlockResource(i_inst); } return NyLPC_TBool_FALSE; } @@ -861,7 +952,7 @@ if(i_len<1){ return 0; } - hint=(i_len>32767)?32767:0; + hint=(i_len>32767)?32767:i_len; buf=NyLPC_cTcpSocket_allocSendBuf(i_inst,hint,&s,i_wait_in_msec); if(buf==NULL){ return -1; @@ -967,12 +1058,12 @@ lockResource(i_inst); f=i_inst->tcpstateflags; if(f!=UIP_CLOSED){ + //もし、強制CLOSE遷移であれば、RSTも送信。 i_inst->tcpstateflags=UIP_CLOSED; - } - unlockResource(i_inst); - //もし、強制CLOSE遷移であれば、RSTも送信。 - if(f!=UIP_CLOSED){ + unlockResource(i_inst); sendRst(i_inst); + }else{ + unlockResource(i_inst); } NyLPC_cStopwatch_finalize(&sw); return; @@ -1149,8 +1240,8 @@ } } } - //MSSとWNDの更新 - i_inst->uip_connr.peer_mss = i_inst->uip_connr.default_mss; +// //MSSとWNDの更新 +// i_inst->uip_connr.peer_mss = i_inst->uip_connr.default_mss;//@bug じゃないのこれ。peer_mss勝手に上書きしたらダメだろ //どちらにしろ、ACK送信 if(is_new_packet && (in_tcpflag & TCP_FIN)){ //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。 @@ -1200,10 +1291,21 @@ break; case UIP_CLOSED: //何もできない。何もしない。 - break;//goto DROP; + break; case UIP_TIME_WAIT: //最終ACKを送り続ける。 break; + case UIP_SYN_SENT: + //connect関数実行中しか起動しないステータス + if(num_of_noack==0){ + i_inst->tcpstateflags=UIP_ESTABLISHED; + i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(o_ipp->payload.tcp->seqno32)+1; + }else{ + //それ以外のパケットはドロップする。 + break;//goto DROP; + } + //ACKを送る。 + break; default: goto DROP; }
--- a/core/uip/NyLPC_cTcpSocket.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cTcpSocket.h Fri Sep 13 06:38:16 2013 +0000 @@ -139,10 +139,12 @@ struct NyLPC_TcTcpSocket_TxQItem txq[NyLPC_TcTcpSocket_NUMBER_OF_TXQ]; }txbuf; volatile NyLPC_TUInt8 tcpstateflags; /**< TCP state and flags. */ - /** 共通MUTEXへのポインタ(うまくいtったらこのままで)*/ - NyLPC_TcMutex_t* _smutex; }; + +#define NyLPC_cTcpSocket_getPeerAddr(i_inst) (&((i_inst)->uip_connr.ripaddr)) +#define NyLPC_cTcpSocket_getPeerPort(i_inst) (((i_inst)->uip_connr.rport)) + /** * 初期化関数です。 * uipserviceは初期化済である必要があります。 @@ -159,6 +161,12 @@ void NyLPC_cTcpSocket_finalize(NyLPC_TcTcpSocket_t* i_inst); NyLPC_TBool NyLPC_cTcpSocket_accept(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec); +/** + * @return + * 1 - 以上:受信に成功した。 + * 0 - タイムアウト + * -1 - ソケットがクローズしている + */ NyLPC_TInt32 NyLPC_cTcpSocket_precv(NyLPC_TcTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec); void NyLPC_cTcpSocket_pseek(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek); /** @@ -205,6 +213,11 @@ */ NyLPC_TBool NyLPC_cTcpSocket_psend(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec); +/** + * TCPソケットをクライアントとしてサーバへ接続します。 + */ +NyLPC_TBool NyLPC_cTcpSocket_connect(NyLPC_TcTcpSocket_t* i_inst,struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec); + #ifdef __cplusplus }
--- a/core/uip/NyLPC_cUipService.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_cUipService.c Fri Sep 13 06:38:16 2013 +0000 @@ -95,7 +95,7 @@ struct NyLPC_TArpHeader arp; struct NyLPC_TIPv4Header ipv4; }data; -}; +}PACK_STRUCT_END; @@ -122,7 +122,7 @@ static NyLPC_TBool sendIPv4Tx(struct NyLPC_TTxBufferHeader* i_eth_buf); static void copyAndSendIPv4Tx(const struct TEthPacket* i_buf); -static void sendArpReqest(const struct TEthPacket* i_eth_packet); +//static void sendArpReqest(const struct TEthPacket* i_eth_packet); static void sendRawEthFrame(void* i_buf,NyLPC_TUInt16 i_len); static void emacIsrHandler(unsigned long i_status); @@ -136,7 +136,6 @@ NyLPC_TcThread_t th; -void led(int i); NyLPC_TBool NyLPC_cUipService_initialize(void) { NyLPC_TcUipService_t* inst=&_service_instance; @@ -396,31 +395,10 @@ } - - /** - * allocTxBufで取得したメモリを"IPパケットとして"送信します。 - * @param i_eth_payload - * [NyLPC_TTxBufferHeader][NyLPC_TEthernetIIHeader][payload]メモリの、[payload]のアドレスを指定します。 - * 通常は、NyLPC_cUipService_allocTxBufの返却したメモリを指定します。 + * IPv4パケットのpeerIPを問い合わせるARPパケットを送信します。 */ - -void NyLPC_cUipService_sendIPv4Tx(void* i_eth_payload) -{ - NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; - NyLPC_cMutex_lock(&(inst->_mutex)); - //IPパケットの送信を試行 - if(!sendIPv4Tx(((struct NyLPC_TTxBufferHeader*)(((struct NyLPC_TEthernetIIHeader*)i_eth_payload)-1))-1)){ - //ARPリクエストを代わりに送信 - sendArpReqest(((struct TEthPacket*)i_eth_payload)-1); - } - NyLPC_cMutex_unlock(&(inst->_mutex)); - return; -} -/** - * 指定したIPアドレスに対してARPRequestを送信します。 - */ -void NyLPC_cUipService_sendArpRequest(const struct NyLPC_TIPv4Addr* i_addr) +static void sendArpReqest(const struct NyLPC_TIPv4Addr* i_addr) { NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; NyLPC_TUInt16 tx_len; @@ -431,10 +409,48 @@ } //ARPパケットを作る。 ethbuf=(struct TEthPacket*)(inst->stx.buf); - NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_ref_config->ip_addr,&(inst->_ref_config->eth_mac),*i_addr); + NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_ref_config->ip_addr,&(inst->_ref_config->eth_mac),i_addr); tx_len=NyLPC_TEthernetIIHeader_setArpTx(&(ethbuf->header),&(inst->_ref_config->eth_mac)); //送信 inst->_ethif->sendTxEthFrame(&(inst->stx.h),tx_len); +} + + + + +/** + * allocTxBufで取得したペイロードメモリを"IPパケットとして"送信します。 + * @param i_eth_payload + * [NyLPC_TTxBufferHeader][NyLPC_TEthernetIIHeader][payload]メモリの、[payload]のアドレスを指定します。 + * 通常は、NyLPC_cUipService_allocTxBufの返却したメモリを指定します。 + */ + +void NyLPC_cUipService_sendIPv4Tx(void* i_eth_payload) +{ + NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; + struct NyLPC_TTxBufferHeader* p=((struct NyLPC_TTxBufferHeader*)(((struct NyLPC_TEthernetIIHeader*)i_eth_payload)-1))-1; + NyLPC_cMutex_lock(&(inst->_mutex)); + + //IPパケットの送信を試行 + if(!sendIPv4Tx(p)){ + //ARPリクエストを代わりに送信 + sendArpReqest(&((struct NyLPC_TIPv4Header*)i_eth_payload)->destipaddr); + } + NyLPC_cMutex_unlock(&(inst->_mutex)); + return; +} + + + +/** + * 指定したIPアドレスに対してARPRequestを送信します。 + */ +void NyLPC_cUipService_sendArpRequest(const struct NyLPC_TIPv4Addr* i_addr) +{ + NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; + NyLPC_cMutex_lock(&(inst->_mutex)); + sendArpReqest(i_addr); + NyLPC_cMutex_unlock(&(inst->_mutex)); return; } @@ -448,6 +464,8 @@ } + + /** * 送信ペイロードメモリを返します。 * この関数は、リエントラントを許容します。 @@ -501,7 +519,7 @@ */ /** - * 新たにメモリを確保して、"IPv4パケットを格納した"イーサフレームを送信します。 + * "IPv4パケットを格納した"イーサフレームを送信します。 * コール前に、必ずロックしてから呼び出してください。 */ static void copyAndSendIPv4Tx(const struct TEthPacket* i_buf) @@ -517,29 +535,13 @@ memcpy(inst->stx.buf,i_buf,s); if(!sendIPv4Tx(&(inst->stx.h))){ //失敗した場合はARPリクエストに変換して再送 - sendArpReqest(i_buf); +//@todo unchecked PASS! + sendArpReqest(&i_buf->data.ipv4.destipaddr); } return; } -/** - * IPv4パケットのpeerIPを問い合わせるARPパケットを送信します。 - */ -static void sendArpReqest(const struct TEthPacket* i_eth_packet) -{ - NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; - NyLPC_TUInt16 tx_len; - struct TEthPacket* ethbuf; - //ACK送信用の自己バッファが空くまで待つ - while(inst->stx.h.is_lock){ - inst->_ethif->processTx(); - } - //ARPパケットを作る。 - ethbuf=(struct TEthPacket*)(inst->stx.buf); - NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_ref_config->ip_addr,&(inst->_ref_config->eth_mac),i_eth_packet->data.ipv4.destipaddr); - tx_len=NyLPC_TEthernetIIHeader_setArpTx(&(ethbuf->header),&(inst->_ref_config->eth_mac)); - //送信 - inst->_ethif->sendTxEthFrame(&(inst->stx.h),tx_len); -} + + /** * uipタスクが所有するTXバッファを使用してデータを送信します。 @@ -623,36 +625,4 @@ -//static void startEther() -//{ -// NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst; -// -// //Ethernetの起動待ち -// while(lEMACInit(_NyLPC_TcUipService_inst->_emac_semapho,&(inst->_ref_config->eth_mac))!= pdPASS ) -// { -// vTaskDelay( 100 / portTICK_RATE_MS ); -// } -// //Ethernetの割込み開始設定 -// portENTER_CRITICAL(); -// { -// LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE ); -// /* Set the interrupt priority to the max permissible to cause some -// interrupt nesting. */ -// NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY ); -// -// /* Enable the interrupt. */ -// NVIC_EnableIRQ( ENET_IRQn ); -// } -// portEXIT_CRITICAL(); -//} -// -//static void stopEther() -//{ -// portENTER_CRITICAL(); -// { -// LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable; -// NVIC_DisableIRQ( ENET_IRQn ); -// } -// portEXIT_CRITICAL(); -//}
--- a/core/uip/NyLPC_uip.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_uip.c Fri Sep 13 06:38:16 2013 +0000 @@ -63,6 +63,34 @@ const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_MULTICAST_MASK = NyLPC_TIPv4Addr_pack(224,0,0,0); const struct NyLPC_TIPv4Addr NyLPC_TIPv4Addr_APIPA_MASK = NyLPC_TIPv4Addr_pack(255,255,0,0); +NyLPC_TInt16 NyLPC_TIPv4Addr_toString(const struct NyLPC_TIPv4Addr* i_ip,NyLPC_TChar* i_buf) +{ + NyLPC_TUInt32 ip; + NyLPC_TChar* p=i_buf; + NyLPC_TUInt8 v; + NyLPC_TInt8 l; + //IPをホストオーダーにする。 + ip=NyLPC_NTOHL(i_ip->v); + for(l=3;l>=0;l--){ + v=(ip>>(8*l))&0xff; + if(v>100){ + *p=(v/100)+'0'; + v=v%100; + p++; + } + if(v>10){ + *p=(v/10)+'0'; + v=v%10; + p++; + } + *p=v+'0'; + *(p+1)='.'; + p+=2; + } + *(p-1)='\0'; + return p-i_buf-1; +} + NyLPC_TUInt16 NyLPC_uip_chksum(NyLPC_TUInt16 sum, const NyLPC_TUInt8 *data, NyLPC_TUInt16 len) { @@ -356,17 +384,17 @@ * *------------------------------------------------------------------------------*/ /** - * 指定したIPアドレスに対する、ARP REQUESTをセットする。 + * i_req_addrを問い合わせるARP_REQUESTを生成します。 */ void NyLPC_TArpHeader_setArpRequest( struct NyLPC_TArpHeader* i_struct, const struct NyLPC_TIPv4Addr i_saddr, const struct NyLPC_TEthAddr* i_srceth, - const struct NyLPC_TIPv4Addr i_daddr) + const struct NyLPC_TIPv4Addr* i_req_addr) { memset(i_struct->dhwaddr.addr, 0x00, 6); memcpy(i_struct->shwaddr.addr, i_srceth, 6); - i_struct->dipaddr=i_daddr; + i_struct->dipaddr=*i_req_addr; i_struct->sipaddr=i_saddr; i_struct->opcode = NyLPC_HTONS(ARP_REQUEST); /* ARP request. */ i_struct->hwtype = NyLPC_HTONS(ARP_HWTYPE_ETH);
--- a/core/uip/NyLPC_uip.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/uip/NyLPC_uip.h Fri Sep 13 06:38:16 2013 +0000 @@ -119,6 +119,12 @@ #define NyLPC_TIPv4Addr_set(s,a0,a1,a2,a3) (s)->v=NyLPC_htonl((0xff000000&(((NyLPC_TUInt32)(a0))<<24))|(0x00ff0000&(((NyLPC_TUInt32)(a1))<<16))|(0x0000ff00&(((NyLPC_TUInt32)(a2))<<8))|(0x000000ff&((NyLPC_TUInt32)(a3)))) #define NyLPC_TIPv4Addr_pack(a0,a1,a2,a3) {NyLPC_HTONL((0xff000000&(((NyLPC_TUInt32)(a0))<<24))|(0x00ff0000&(((NyLPC_TUInt32)(a1))<<16))|(0x0000ff00&(((NyLPC_TUInt32)(a2))<<8))|(0x000000ff&((NyLPC_TUInt32)(a3))))} +/** + * IPアドレスを文字列に変換して返します。 + */ +NyLPC_TInt16 NyLPC_TIPv4Addr_toString(const struct NyLPC_TIPv4Addr* i_ip,NyLPC_TChar* i_buf); + + @@ -139,19 +145,6 @@ */ #define UIP_DEFAULT_IP_TTL 64 -/** - * RTOの最大値。ms単位である。 - * 64sが標準値である。 - */ -#define UIP_IP_RTO_MAX_RTO 64000 - -/** - * RTOの初期値。ms単位である。 - * 伝送路の特性に合わせて調整すること。 - */ -#define UIP_IP_RTOP_INITIAL 3000 - -#define UIP_IP_RTO_MINIMUM 100 /** @@ -188,7 +181,7 @@ # define NyLPC_ntohl(n) (n) # define NyLPC_HTONS(n) (n) # define NyLPC_NTOHS(n) (n) -# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# else # define NyLPC_htonl(n) NyLPC_TUInt32_bswap(n) # define NyLPC_ntohl(n) NyLPC_TUInt32_bswap(n) # define NyLPC_htons(n) NyLPC_TUInt16_bswap(n) @@ -429,11 +422,14 @@ } PACK_STRUCT_END; +/** + * i_req_addrを問い合わせるARP_REQUESTを生成します。 + */ void NyLPC_TArpHeader_setArpRequest( struct NyLPC_TArpHeader* i_struct, const struct NyLPC_TIPv4Addr i_saddr, const struct NyLPC_TEthAddr* i_srceth, - const struct NyLPC_TIPv4Addr i_daddr); + const struct NyLPC_TIPv4Addr* i_req_addr); typedef struct NyLPC_TcEthernetIIPayload NyLPC_TcEthernetIIPayload_t;
--- a/core/utils/NyLPC_cFormatWriter.c Sat Aug 10 02:52:22 2013 +0000 +++ b/core/utils/NyLPC_cFormatWriter.c Fri Sep 13 06:38:16 2013 +0000 @@ -1,8 +1,8 @@ #include "NyLPC_cFormatWriter.h" -#define FTYPE_LENGTH 0x00000001 -#define FTYPE_NOTHING 0x00000000 +#define FTYPE_LENGTH 0x01 +#define FTYPE_NOTHING 0x00 #define NUM_OF_WORK 16 NyLPC_TBool NyLPC_cFormatWriter_print(NyLPC_cFormatWriter_printHandler i_handler,void* i_inst,const NyLPC_TChar* i_fmt,va_list args) @@ -10,9 +10,9 @@ const char* rp=i_fmt; const char* sp; char wk[NUM_OF_WORK]; - NyLPC_TUInt32 ftype; + NyLPC_TUInt8 ftype; NyLPC_TUInt32 ut; - int ol=0; + NyLPC_TInt16 ol=0; while(*rp!='\0'){ if(*rp=='%'){ ftype=FTYPE_NOTHING; @@ -132,3 +132,132 @@ //どこかでエラーが起こってればFALSE返す。 return i_handler(i_inst,wk,ol); } + +NyLPC_TInt16 NyLPC_cFormatWriter_length(const NyLPC_TChar* i_fmt,va_list args) +{ + const char* rp=i_fmt; + const char* sp; + char wk[NUM_OF_WORK]; + NyLPC_TUInt32 ut; + NyLPC_TUInt8 ftype; + NyLPC_TInt16 len=0; + NyLPC_TInt16 ol=0; + while(*rp!='\0'){ + if(*rp=='%'){ + ftype=FTYPE_NOTHING; + rp++; + FMT_NEXT: + switch (*rp){ + case '.': + //%.*(s) + if(*(rp+1)=='*'){ + //%.* + ftype=FTYPE_LENGTH; + rp+=2; + goto FMT_NEXT; + } + //その他 + wk[ol]=*rp; + ol++; + rp++; + break; + case 's': + switch(ftype){ + case FTYPE_LENGTH: + //%.*sの場合 + ut=va_arg(args,NyLPC_TUInt32); + break; + default: + ut=0x7FFFFFFF; + } + sp=va_arg(args,const char*); + while(*sp!=0 && ut>0){ + wk[ol]=*sp; + ol++; + sp++; + //バッファフルなら書込み。 + if(ol>=NUM_OF_WORK){ + len+=NUM_OF_WORK; + ol=0; + } + ut--; + } + rp++; + continue; + case 'c': + wk[ol]=(char)va_arg(args,int); + rp++; + ol++; + break; + case 'd': + //ワークを空にする。 + if(ol>0){ + len+=ol; + ol=0; + } + NyLPC_itoa((va_arg(args,int)),wk,10); + //強制コミット + len+=(NyLPC_TInt16)strlen(wk); + rp++; + continue; + case 'u': + //ワークを空にする。 + if(ol>0){ + len+=ol; + } + ut=va_arg(args,NyLPC_TUInt32); + ol=15; + wk[ol--]='\0'; + do{ + wk[ol--]='0'+(ut%10); + ut/=10; + }while(ut>0); + len+=14-ol; + ol=0; + rp++; + continue; + case 'x': + //ワークを空にする。 + if(ol>0){ + len+=ol; + ol=0; + } + NyLPC_uitoa((va_arg(args,unsigned int)),wk,16); + //強制コミット + len+=(NyLPC_TInt16)strlen(wk); + rp++; + continue; +// case 'X': + case '%': + wk[ol]='%'; + ol++; + rp++; + break; + case '\0': + //オワタ(ループ抜けるためにrpはそのまま。) + break; + default: + wk[ol]=*rp; + ol++; + } + //バッファフルなら書込み。 + if(ol>=NUM_OF_WORK){ + len+=NUM_OF_WORK; + ol=0; + } + }else if(*rp==0){ + //オワタ + break; + }else{ + wk[ol]=*rp; + ol++; + rp++; + if(ol>=NUM_OF_WORK){ + len+=NUM_OF_WORK; + ol=0; + } + } + } + //どこかでエラーが起こってればFALSE返す。 + return len+ol; +}
--- a/core/utils/NyLPC_cFormatWriter.h Sat Aug 10 02:52:22 2013 +0000 +++ b/core/utils/NyLPC_cFormatWriter.h Fri Sep 13 06:38:16 2013 +0000 @@ -21,6 +21,11 @@ */ NyLPC_TBool NyLPC_cFormatWriter_print(NyLPC_cFormatWriter_printHandler i_handler,void* i_inst,const NyLPC_TChar* i_fmt,va_list args); +/** + * 書式文字列を出力した時のバイト長さを求めます。 + */ +NyLPC_TInt16 NyLPC_cFormatWriter_length(const NyLPC_TChar* i_fmt,va_list args); + #ifdef __cplusplus }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/utils/sha1/sha1.c Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,229 @@ +/* +SHA-1 in C +By Steve Reid <steve@edmweb.com> +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ +/** + * modified by nyatla + * Still public domain. + */ + +/* #define LITTLE_ENDIAN * This should be #define'd if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#include <stdio.h> +#include <string.h> +#include "sha1.h" +#include "NyLPC_config.h" + + +# if UIP_BYTE_ORDER == NyLPC_ENDIAN_BIG +# else +# define LITTLE_ENDIAN 1 +#endif + + + + +/* +void SHA1Transform(unsigned long state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); +*/ +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#ifdef LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +#define SHA1HANDSOFF 1 +void SHA1Transform(unsigned long state[5],const unsigned char buffer[64]) +{ +unsigned long a, b, c, d, e; +typedef union { + unsigned char c[64]; + unsigned long l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context,const void* data, unsigned int len) +{ +unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, ((const unsigned char*)data)+i); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], ((const unsigned char*)data)+i, len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ + unsigned long i, j; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[((i >= 4) ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + + +/*************************************************************/ +//#define TEST_SHA1 +#ifdef TEST_SHA1 + +int main(int argc, char** argv) +{ +int i, j; +SHA1_CTX context; +unsigned char digest[20], buffer[16384]; +FILE* file; + + if (argc > 2) { + puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>"); + puts("Produces the SHA-1 hash of a file, or stdin if no file is specified."); + exit(0); + } + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + exit(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + for (i = 0; i < 5; i++) { + for (j = 0; j < 4; j++) { + printf("%02X", digest[i*4+j]); + } + putchar(' '); + } + putchar('\n'); + exit(0); +} +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/utils/sha1/sha1.h Fri Sep 13 06:38:16 2013 +0000 @@ -0,0 +1,40 @@ +/* sha1.h */ +#include "NyLPC_stdlib.h" +/* If OpenSSL is in use, then use that version of SHA-1 */ +#ifdef OPENSSL +#include <t_sha.h> +#define __SHA1_INCLUDE_ +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef __SHA1_INCLUDE_ + +#ifndef SHA1_SIGNATURE_SIZE +#ifdef SHA_DIGESTSIZE +#define SHA1_SIGNATURE_SIZE SHA_DIGESTSIZE +#else +#define SHA1_SIGNATURE_SIZE 20 +#endif +#endif + + +typedef struct { + NyLPC_TUInt32 state[5]; + NyLPC_TUInt32 count[2]; + unsigned char buffer[64]; +}SHA1_CTX; + +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context,const void* data, unsigned int len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define __SHA1_INCLUDE_ +#endif /* __SHA1_INCLUDE_ */ +