Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
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_ */
+
MiMic Webservice library