OSDN Git Service

Websocketにバルク転送関数を追加
authornyatla <nyatla@47198e57-cb75-475f-84c4-a814cd6f29e0>
Mon, 9 Jun 2014 02:31:13 +0000 (02:31 +0000)
committernyatla <nyatla@47198e57-cb75-475f-84c4-a814cd6f29e0>
Mon, 9 Jun 2014 02:31:13 +0000 (02:31 +0000)
JSONRPC関連のモジュール、クラスを追加

git-svn-id: http://svn.osdn.jp/svnroot/mimic/trunk@356 47198e57-cb75-475f-84c4-a814cd6f29e0

lib/Debug/makefile
lib/Debug/sources.mk
lib/src/http/json/NyLPC_cJsonRpcParser.c [new file with mode: 0644]
lib/src/http/json/NyLPC_cJsonRpcParser.h [new file with mode: 0644]
lib/src/include/NyLPC_http.h
lib/src/net/httpd/mod/NyLPC_cModJsonRpc.c [new file with mode: 0644]
lib/src/net/httpd/mod/NyLPC_cModJsonRpc.h [new file with mode: 0644]
lib/src/net/httpd/mod/NyLPC_cModWebSocket.c
lib/src/net/httpd/mod/NyLPC_cModWebSocket.h
lib/src/net/httpd/mod/NyLPC_cModWebSocket_protected.h

index 4d667d9..a6e4f2d 100644 (file)
@@ -23,6 +23,7 @@ RM := rm -rf
 -include src/net/subdir.mk\r
 -include src/mimicvm/subdir.mk\r
 -include src/include/boot/subdir.mk\r
+-include src/http/json/subdir.mk\r
 -include src/http/subdir.mk\r
 -include src/flash/subdir.mk\r
 -include src/econetlite/subdir.mk\r
index 56a0b7c..ac693bc 100644 (file)
@@ -29,6 +29,7 @@ src/net/apipa \
 src/net \
 src/mimicvm \
 src/include/boot \
+src/http/json \
 src/http \
 src/flash \
 src/econetlite \
diff --git a/lib/src/http/json/NyLPC_cJsonRpcParser.c b/lib/src/http/json/NyLPC_cJsonRpcParser.c
new file mode 100644 (file)
index 0000000..d9fde6f
--- /dev/null
@@ -0,0 +1,644 @@
+#include "NyLPC_cJsonRpcParser.h"\r
+\r
+//\r
+//     NyLPC_TJsonRpcParserResult\r
+//\r
+\r
+\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getUInt32(const union NyLPC_TJsonRpcParserResult* i_struct,NyLPC_TInt16 i_idx,NyLPC_TUInt32* o_val)\r
+{\r
+       if(i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx]!=NyLPC_cJsonRpcParser_TYPE_UINT32){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       *o_val = *((NyLPC_TUInt32*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]));\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getInt32(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TInt32* o_val)\r
+{\r
+       if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_INT32){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       *o_val = *((NyLPC_TInt32*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]));\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getStr(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, const NyLPC_TChar** o_val)\r
+{\r
+       if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_STRING){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       *o_val = ((NyLPC_TChar*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]));\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getByte(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TUInt8* o_val)\r
+{\r
+       if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_BYTE){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       *o_val = *(i_struct->method.param_buf + i_struct->method.param_index[i_idx]);\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+\r
+\r
+//\r
+//     NyLPC_cJsonRpcParser\r
+//\r
+\r
+\r
+\r
+#define NAME_ID_UNKNOWN                0\r
+#define NAME_ID_VERSION                1\r
+#define NAME_ID_METHOD         2\r
+#define NAME_ID_RESULT         3\r
+#define NAME_ID_PARAMS         4\r
+#define NAME_ID_ID                     5\r
+\r
+const struct NyLPC_TTextIdTbl method_name_tbl[]=\r
+{\r
+       {"version",NAME_ID_VERSION},\r
+       {"method",NAME_ID_METHOD},\r
+       {"params",NAME_ID_PARAMS},\r
+       {"id",NAME_ID_ID},\r
+       {NULL,NAME_ID_UNKNOWN}\r
+};\r
+\r
+\r
+static const struct NyLPC_TJsonRpcClassDef* findFunction(const struct NyLPC_TJsonRpcClassDef** i_tbl, const NyLPC_TChar* i_method_path, NyLPC_TUInt8* o_function_idx);\r
+static void putchar_params(NyLPC_TcJsonRpcParser_t* i_inst, char i_c);\r
+static NyLPC_TUInt8 valTerminator2St(NyLPC_TChar i_c);\r
+\r
+\r
+void NyLPC_cJsonRpcParser_initialize(\r
+       NyLPC_TcJsonRpcParser_t* i_inst,\r
+       const struct NyLPC_TJsonRpcClassDef** i_class_def)\r
+{\r
+       i_inst->_class_def=i_class_def;\r
+}\r
+void NyLPC_cJsonRpcParser_initParser(NyLPC_TcJsonRpcParser_t* i_inst,union NyLPC_TJsonRpcParserResult* i_result)\r
+{\r
+       i_inst->_result=i_result;\r
+       i_result->type=NyLPC_TJsonRpcParserResult_TYPE_UNKNOWN;\r
+       i_inst->_st = NyLPC_TcJsonRpcParser_ST_START;\r
+       i_inst->_pcounter = 0;\r
+       memset(i_result->raw.param_index, 0xff, NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX);\r
+}\r
+\r
+\r
+\r
+static const struct NyLPC_TJsonRpcClassDef* findFunction(const struct NyLPC_TJsonRpcClassDef** i_tbl,const NyLPC_TChar* i_method_path,NyLPC_TUInt8* o_function_idx)\r
+{\r
+       const NyLPC_TChar* ns;\r
+       const NyLPC_TChar* class_;\r
+       const NyLPC_TChar* method;\r
+       NyLPC_TUInt8 fidx;\r
+       int l;\r
+       //namespaceの抽出\r
+       ns=i_method_path;\r
+       class_=strchr(i_method_path,':');\r
+       if(class_==NULL){\r
+               return NULL;\r
+       }\r
+       class_++;\r
+       //functionの抽出\r
+       method=strchr(class_,':');\r
+       if(method==NULL){\r
+               return NULL;\r
+       }\r
+       method++;\r
+       while((*i_tbl)!=NULL){\r
+               l=class_-ns-1;\r
+               if(strncmp((*i_tbl)->names_pace,ns,l)!=0 || (*(ns+l))!=':'){\r
+                       i_tbl++;\r
+                       continue;\r
+               }\r
+               l=method-class_-1;\r
+               if(strncmp((*i_tbl)->class_name,class_,l)!=0 || (*(class_+l))!=':'){\r
+                       i_tbl++;\r
+                       continue;\r
+               }\r
+               fidx=0;\r
+               while(((*i_tbl)->functions+fidx)->name!=NULL){\r
+                       if(strcmp(((*i_tbl)->functions+fidx)->name,method)!=0){\r
+                               fidx++;\r
+                               continue;\r
+                       }\r
+                       *o_function_idx=fidx;\r
+                       return (*i_tbl);\r
+               }\r
+               break;\r
+       }\r
+       return NULL;\r
+}\r
+#define PARAM_ST_START 1\r
+#define PARAM_ST_VAL   2\r
+#define PARAM_ST_INT   3\r
+#define PARAM_ST_UINT  4\r
+#define PARAM_ST_STR   5\r
+#define PARAM_ST_NEXT  6\r
+#define PARAM_ST_BYTE  7\r
+\r
+static void putchar_params(NyLPC_TcJsonRpcParser_t* i_inst, char i_c)\r
+{\r
+\r
+       switch (i_inst->_pst){\r
+       case PARAM_ST_START:\r
+               if (i_c == '['){\r
+                       //パース開始\r
+                       i_inst->_work.str.n = 0;\r
+                       i_inst->_pst = PARAM_ST_VAL;\r
+                       return;\r
+               }\r
+               if (strchr(" ", i_c) != NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               //エラー\r
+               goto ERROR;\r
+       case PARAM_ST_VAL:\r
+               if (i_inst->_pcounter >= NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX){\r
+                       goto ERROR;\r
+               }\r
+               if (strchr(" ", i_c) != NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               if (strchr("]", i_c) != NULL){\r
+                       i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT;\r
+                       i_inst->_pcounter = 0xff;\r
+                       return;\r
+               }\r
+               switch (i_inst->_result->method.class_def->functions[i_inst->_result->method.func_number].param_patt[i_inst->_pcounter]){\r
+               case NyLPC_cJsonRpcParser_TYPE_INT32:\r
+                       if (strchr("-0123456789", i_c) == NULL){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_pst = PARAM_ST_INT;\r
+                       i_inst->_work.int32.s = i_c == '-' ? -1 : 1;\r
+                       i_inst->_work.int32.v = i_c == '-' ? 0 : (i_c - '0');\r
+                       i_inst->_work.str.n = ((i_inst->_work.str.n + 3) / 4) * 4;\r
+                       break;\r
+               case NyLPC_cJsonRpcParser_TYPE_UINT32:\r
+                       if (strchr("0123456789", i_c) == NULL){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_pst = PARAM_ST_UINT;\r
+                       i_inst->_work.uint32 = (i_c - '0');\r
+                       //開始位置を4バイト境界に\r
+                       i_inst->_work.str.n = ((i_inst->_work.str.n + 3) / 4) * 4;\r
+                       break;\r
+               case NyLPC_cJsonRpcParser_TYPE_BYTE:\r
+                       if (strchr("0123456789", i_c) == NULL){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_pst = PARAM_ST_BYTE;\r
+                       i_inst->_work.uint32 = (i_c - '0');\r
+                       break;\r
+               case NyLPC_cJsonRpcParser_TYPE_STRING:\r
+                       if (i_c != '"'){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_pst = PARAM_ST_STR;\r
+                       break;\r
+               default:\r
+                       goto ERROR;\r
+               }\r
+               i_inst->_result->method.param_index[i_inst->_pcounter] = i_inst->_work.str.n;\r
+               i_inst->_pcounter++;\r
+               return;\r
+       case PARAM_ST_STR:\r
+               if (i_c == '"'){\r
+                       //完了\r
+                       if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_result->method.param_buf[i_inst->_work.str.n] = '\0';\r
+                       i_inst->_work.str.n++;\r
+                       i_inst->_pst = PARAM_ST_NEXT;\r
+                       return;\r
+               }\r
+               else{\r
+                       if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_result->method.param_buf[i_inst->_work.str.n] = i_c;\r
+                       i_inst->_work.str.n++;\r
+               }\r
+               return;\r
+       case PARAM_ST_INT:\r
+               if (strchr("0123456789", i_c) != NULL){\r
+                       i_inst->_work.int32.v = i_inst->_work.int32.v * 10 + (i_c - '0');\r
+                       return;\r
+               }\r
+               switch (i_c){\r
+               case ' ':\r
+                       i_inst->_pst = PARAM_ST_NEXT; break;\r
+               case ',':\r
+                       i_inst->_pst = PARAM_ST_VAL; break;\r
+               case ']':\r
+                       i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
+               default:\r
+                       goto ERROR;\r
+               }\r
+               //4バイト境界に揃える\r
+               i_inst->_work.str.n += 4;\r
+               if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
+                       goto ERROR;\r
+               }\r
+               *((NyLPC_TInt32*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 4])) = i_inst->_work.int32.v*i_inst->_work.int32.s;\r
+               return;\r
+       case PARAM_ST_UINT:\r
+               if (strchr("0123456789", i_c) != NULL){\r
+                       i_inst->_work.uint32 = i_inst->_work.uint32 * 10 + (i_c - '0');\r
+                       return;\r
+               }\r
+               switch (i_c){\r
+               case ' ':\r
+                       i_inst->_pst = PARAM_ST_NEXT; break;\r
+               case ',':\r
+                       i_inst->_pst = PARAM_ST_VAL; break;\r
+               case ']':\r
+                       i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
+               default:\r
+                       goto ERROR;\r
+               }\r
+               i_inst->_work.str.n += 4;\r
+               if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
+                       goto ERROR;\r
+               }\r
+               *((NyLPC_TUInt32*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 4])) = i_inst->_work.uint32;\r
+               return;\r
+       case PARAM_ST_BYTE:\r
+               if (strchr("0123456789", i_c) != NULL){\r
+                       i_inst->_work.uint32 = i_inst->_work.uint32 * 10 + (i_c - '0');\r
+                       return;\r
+               }\r
+               switch (i_c){\r
+               case ' ':\r
+                       i_inst->_pst = PARAM_ST_NEXT; break;\r
+               case ',':\r
+                       i_inst->_pst = PARAM_ST_VAL; break;\r
+               case ']':\r
+                       i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
+               default:\r
+                       goto ERROR;\r
+               }\r
+               i_inst->_work.str.n ++;\r
+               if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
+                       goto ERROR;\r
+               }\r
+               *((NyLPC_TUInt8*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 1])) = (NyLPC_TUInt8)(i_inst->_work.uint32&0xff);\r
+               return;\r
+       case PARAM_ST_NEXT:\r
+               switch (i_c){\r
+               case ' ':break;\r
+               case ',':\r
+                       i_inst->_pst = PARAM_ST_VAL; break;\r
+               case ']':\r
+                       i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
+               default:\r
+                       goto ERROR;\r
+               }\r
+               return;\r
+       }\r
+ERROR:\r
+       i_inst->_st = NyLPC_TcJsonRpcParser_ST_ERROR;\r
+       return;\r
+}\r
+\r
+\r
+/**\r
+* NyLPC_cJsonRpcParser_putCharのサブ関数\r
+*/\r
+static NyLPC_TUInt8 valTerminator2St(NyLPC_TChar i_c)\r
+{\r
+       switch (i_c){\r
+       case ' ':\r
+               return NyLPC_TcJsonRpcParser_ST_NEXT;\r
+       case '}':\r
+               return NyLPC_TcJsonRpcParser_ST_END;\r
+       case ',':\r
+               return NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
+       default:\r
+               //ないはず\r
+               return NyLPC_TcJsonRpcParser_ST_ERROR;\r
+       }\r
+}\r
+\r
+/** 文字列をパーサに入力してパーサの状態を遷移させます。\r
+\r
+*/\r
+void NyLPC_cJsonRpcParser_putChar(NyLPC_TcJsonRpcParser_t* i_inst,char i_c)\r
+{\r
+       switch(i_inst->_st){\r
+       case NyLPC_TcJsonRpcParser_ST_PARAMS:\r
+               putchar_params(i_inst,i_c);\r
+               return;\r
+       case NyLPC_TcJsonRpcParser_ST_START:\r
+               if(i_c=='{'){\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
+                       return;\r
+               }\r
+               if(strchr(" ",i_c)!=NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               //エラー\r
+               goto ERROR;\r
+       case NyLPC_TcJsonRpcParser_ST_NAME_Q:\r
+               if(i_c=='"'){\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_STR;\r
+                       i_inst->_work.str.n=0;\r
+                       return;\r
+               }\r
+               if(strchr(" ",i_c)!=NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               //エラー\r
+               goto ERROR;\r
+       case NyLPC_TcJsonRpcParser_ST_NAME_STR:\r
+               if(i_c=='"'){\r
+                       //完了\r
+                       i_inst->_work.str.buf[i_inst->_work.str.n]='\0';\r
+                       //メソッドIDを記録\r
+                       i_inst->_name_id=NyLPC_TTextIdTbl_getMatchId(i_inst->_work.str.buf,method_name_tbl);\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_NV_SEP;\r
+                       switch(i_inst->_name_id){\r
+                       case NAME_ID_METHOD:\r
+                       case NAME_ID_RESULT:\r
+                               if(i_inst->_result->type!=NyLPC_TJsonRpcParserResult_TYPE_UNKNOWN){\r
+                                       goto ERROR;\r
+                               }\r
+                               break;\r
+                       case NAME_ID_PARAMS:\r
+                               if (i_inst->_pcounter != 0){\r
+                                       goto ERROR;\r
+                               }\r
+                               break;\r
+                       default:\r
+                               break;\r
+                       }\r
+                       return;\r
+               }\r
+               i_inst->_work.str.n++;\r
+               if(i_inst->_work.str.n>=NyLPC_TcJsonRpcParser_WORK_MAX){\r
+                       //文字列長すぎでござる。\r
+                       goto ERROR;\r
+               }\r
+               i_inst->_work.str.buf[i_inst->_work.str.n-1]=i_c;\r
+               return;\r
+       case NyLPC_TcJsonRpcParser_ST_NV_SEP:\r
+               if(i_c==':'){\r
+                       if (i_inst->_name_id == NAME_ID_PARAMS){\r
+                               i_inst->_pst = PARAM_ST_START;\r
+                               i_inst->_st = NyLPC_TcJsonRpcParser_ST_PARAMS;\r
+                       }\r
+                       else{\r
+                               i_inst->_st = NyLPC_TcJsonRpcParser_ST_VAL;\r
+                               i_inst->_work.str.n = 0;\r
+                       }\r
+                       return;\r
+               }\r
+               if(strchr(" ",i_c)!=NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               //エラー\r
+               goto ERROR;\r
+       case NyLPC_TcJsonRpcParser_ST_VAL:\r
+               if(i_c=='"'){\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_VAL_STR;\r
+                       i_inst->_work.str.n=0;\r
+                       return;\r
+               }\r
+               if(strchr(" ",i_c)!=NULL){\r
+                       //無視\r
+                       return;\r
+               }\r
+               if(strchr("0123456789",i_c)!=NULL){\r
+                       i_inst->_work.uint32=(i_c-'0');\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_VAL_UINT;\r
+                       return;\r
+               }\r
+               //エラー\r
+               goto ERROR;\r
+       case NyLPC_TcJsonRpcParser_ST_VAL_UINT:\r
+               if(strchr("0123456789",i_c)!=NULL){\r
+                       i_inst->_work.uint32=i_inst->_work.uint32*10+(i_c-'0');\r
+                       return;\r
+               }\r
+               if(strchr(" ,}",i_c)!=NULL){\r
+                       //確定\r
+                       switch(i_inst->_name_id){\r
+                       case NAME_ID_ID:\r
+                               i_inst->_result->method.id=i_inst->_work.uint32;\r
+                               break;\r
+                       case NAME_ID_UNKNOWN:\r
+                               //知らないIDは無視\r
+                               break;\r
+                       default:\r
+                               //数値を受け入れないパラメータ\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_st=valTerminator2St(i_c);\r
+                       return;\r
+               }\r
+               goto ERROR;\r
+       case NyLPC_TcJsonRpcParser_ST_VAL_STR:\r
+               if(i_c=='"'){\r
+                       i_inst->_work.str.buf[i_inst->_work.str.n]='\0';\r
+                       //確定\r
+                       switch(i_inst->_name_id){\r
+                       case NAME_ID_VERSION:\r
+                               if(strcmp(i_inst->_work.str.buf,"2.0")!=0){\r
+                                       goto ERROR;\r
+                               }\r
+                               break;\r
+                       case NAME_ID_METHOD:\r
+                               i_inst->_result->method._type=NyLPC_TJsonRpcParserResult_TYPE_METHOD;\r
+                               i_inst->_result->method.class_def=findFunction(i_inst->_class_def,i_inst->_work.str.buf,&(i_inst->_result->method.func_number));\r
+                               if(i_inst->_result->method.class_def==NULL){\r
+                                       goto ERROR;\r
+                               }\r
+                               break;\r
+                       case NAME_ID_UNKNOWN:\r
+                               //知らないIDは無視\r
+                               break;\r
+                       default:\r
+                               //文字列を受け入れないパラメータ\r
+                               goto ERROR;\r
+                       }\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_NEXT;\r
+                       return;\r
+               }\r
+               i_inst->_work.str.n++;\r
+               if(i_inst->_work.str.n>=NyLPC_TcJsonRpcParser_WORK_MAX){\r
+                       //文字列長すぎでござる。\r
+                       goto ERROR;\r
+               }\r
+               i_inst->_work.str.buf[i_inst->_work.str.n-1]=i_c;\r
+               return;\r
+       case NyLPC_TcJsonRpcParser_ST_NEXT:\r
+               if(i_c==','){\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
+               }else if(i_c=='}'){\r
+                       i_inst->_st=NyLPC_TcJsonRpcParser_ST_END;\r
+               }else if(strchr(" ",i_c)!=NULL){\r
+                       //nothing to do\r
+               }else{\r
+                       goto ERROR;\r
+               }\r
+               return;\r
+       default:\r
+               goto ERROR;\r
+       }\r
+ERROR:\r
+       i_inst->_st = NyLPC_TcJsonRpcParser_ST_ERROR;\r
+       return;\r
+}\r
+\r
+#define COMMENT_DEBUG\r
+#ifndef COMMENT_DEBUG\r
+\r
+const struct NyLPC_TJsonRpcMethodDef test_method[]=\r
+{\r
+       { "func" , ""},\r
+       { "func1", "d" },\r
+       { "func2", "dd" },\r
+       { "func3", "u" },\r
+       { "func4", "uu" },\r
+       { "func5", "uss" },\r
+       { "func5", "uss" },\r
+       { "func6", "s" },\r
+       { "func7", "sd" },\r
+       { "func8", "su" },\r
+       { "func9", "ss" },\r
+       { "f10", "suu" },\r
+       { "f11", "bbbb" },\r
+       { NULL, "" }\r
+};\r
+\r
+const struct NyLPC_TJsonRpcClassDef test_def=\r
+{\r
+       "ns","class",\r
+       test_method\r
+};\r
+\r
+/**\r
+ * テスト用のアレイ\r
+ */\r
+const struct NyLPC_TJsonRpcClassDef* test_def_array[]=\r
+{\r
+       &test_def,\r
+       NULL\r
+};\r
+\r
+void NyLPC_cJsonRpcParser_putText(NyLPC_TcJsonRpcParser_t* i_inst, const NyLPC_TChar* i_text,NyLPC_TUInt16 i_size)\r
+{\r
+       NyLPC_TUInt16 i;\r
+       NyLPC_TUInt32 u32;\r
+       NyLPC_TInt32 i32;\r
+       NyLPC_TChar* c;\r
+       NyLPC_TUInt8 u8;\r
+\r
+\r
+       for (i = 0; i < i_size; i++){\r
+               NyLPC_cJsonRpcParser_putChar(i_inst,i_text[i]);\r
+               if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_ERROR){\r
+                       break;\r
+               }\r
+               else if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_END){\r
+                       break;\r
+               }\r
+       }\r
+       if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_ERROR){\r
+               printf("ERROR!\n");\r
+       }\r
+       else if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_END){\r
+               printf("OK!\n");\r
+               for (int i = 0; i_inst->_result->method.param_index[i] != 0xff && i<i_inst->_pcounter; i++){\r
+                       switch (i_inst->_result->method.class_def->functions[i_inst->_result->method.func_number].param_patt[i]){\r
+                       case 'u':NyLPC_TJsonRpcParserResult_getUInt32(i_inst->_result,i, &u32); printf("%u,", u32); break;\r
+                       case 'd':NyLPC_TJsonRpcParserResult_getInt32(i_inst->_result, i, &i32); printf("%d,", i32); break;\r
+                       case 's':NyLPC_TJsonRpcParserResult_getStr(i_inst->_result, i, &c); printf("%s,", c); break;\r
+                       case 'b':NyLPC_TJsonRpcParserResult_getByte(i_inst->_result, i, &u8); printf("%u,", u8); break;\r
+                       }\r
+               }\r
+               printf("\n");\r
+       }\r
+       else{\r
+               printf("CONTINUE...\n");\r
+       }\r
+}\r
+\r
+void main(void)\r
+{\r
+       NyLPC_TcJsonRpcParser_t inst;\r
+       union NyLPC_TJsonRpcParserResult ret;\r
+\r
+//JSONCORE\r
+//#define JSONCORE 1\r
+#ifdef JSONCORE\r
+       const char* t[] = {\r
+               "{\"0123\"\"2.0\"}",//NO\r
+               "{\"01234567890123456789\":\"2.0\"}",//NO\r
+               "{\"0123\":\"01234567890123456789\"}",//NO\r
+               "{\"version\":\"2.0\"}",//YES\r
+               "{\"version\":\"2.1\"}",//NO\r
+               " {  \"version\"  :  \"2.0\"  }",//YES\r
+               "{\"version\":\"2.0\",}",//NO\r
+               "{\"version\":\"2.0\" \"test\":\"t\"}",//NO\r
+               "{\"version\":\"2.0\",\"method\":}",//NO\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\"}",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns2:class:func\"}",//NO\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class2:func\"}",//NO\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\"}",//NO\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"method\":\"\"}",//NO\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"id\":0}",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"id\":\"123\"}",//YES\r
+               "{\"version\":\"2.0\",\"method\":123}",//NO\r
+               "{\"version\":\"2.0\",\"test\":123}",//YES\r
+               "{\"version\":\"2.0\",\"test\":123, \"test\":123 }",//YES\r
+               "{\"version\":\"2.0\",\"test\":123 ,\"test\":123 }",//YES\r
+               NULL\r
+       };\r
+#else\r
+       const char* t[] = {\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"params\":[]}",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"params\": [] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func1\",\"params\": [-123] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func1\",\"params\": [\"123\"] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 1 , 456 ] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123 , 456 a] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123a] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123,456] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [123,456] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func3\",\"params\": [123] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func3\",\"params\": [\"123\"] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123 , 456 ] }",//YES\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123 , 456 a] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123a] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123,456] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func5\",\"params\": [123, \"abc\" , \"abc\"] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func6\",\"params\": [\"01234567890123456789012\"] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func6\",\"params\": [1] }",//NG\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func8\",\"params\": [\"012345678901234567\",1,1] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func8\",\"params\": [\"012345678901234567\",1] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:func7\",\"params\": [\"012345678901234567\",1] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:f10\",\"params\": [\"01234567890123\",22,33] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:f11\",\"params\": [ 0 , 1 ,2,3] }",//OK\r
+               "{\"version\":\"2.0\",\"method\":\"ns:class:f11\",\"params\": [ 15 , 1 ,2,3a] }",//NG\r
+               NULL\r
+       };\r
+#endif\r
+       int i;\r
+\r
+       for (i = 0;t[i]!=NULL; i++){\r
+               NyLPC_cJsonRpcParser_initialize(&inst, test_def_array);\r
+               NyLPC_cJsonRpcParser_initParser(&inst, &ret);\r
+               NyLPC_cJsonRpcParser_putText(&inst, t[i], strlen(t[i]));\r
+       }\r
+       printf("end\n");\r
+       return;\r
+\r
+}\r
+#endif\r
diff --git a/lib/src/http/json/NyLPC_cJsonRpcParser.h b/lib/src/http/json/NyLPC_cJsonRpcParser.h
new file mode 100644 (file)
index 0000000..e0af472
--- /dev/null
@@ -0,0 +1,222 @@
+#ifndef NYLPC_CJSONRPCPARSER_H_\r
+#define NYLPC_CJSONRPCPARSER_H_\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include "NyLPC_stdlib.h"\r
+\r
+\r
+/**\r
+ * JSON RPC定義テーブルの一要素。\r
+ * メソッド名とパラメータパターンのセットを定義します。\r
+ * この構造体は配列としてNyLPC_TJsonRpcFunctionTableから参照されます。\r
+ */\r
+struct NyLPC_TJsonRpcMethodDef\r
+{\r
+       /**\r
+        * 関数名\r
+        */\r
+       const char* name;\r
+       /**\r
+        * パラメータパターン\r
+        * <ul>\r
+        * <li>s - 文字列</li>\r
+        * <li>i - signed int32</li>\r
+        * <li>s - unsigned int32</li>\r
+        * </ul>\r
+        */\r
+       const char* param_patt;\r
+};\r
+\r
+\r
+/**\r
+ * JsonRPCクラスの定義テーブル。\r
+ * JsonRPCは、 [namespace]::[]\r
+ */\r
+struct NyLPC_TJsonRpcClassDef\r
+{\r
+       const char* names_pace;\r
+       const char* class_name;\r
+       const struct NyLPC_TJsonRpcMethodDef* functions;\r
+};\r
+\r
+\r
+\r
+\r
+\r
+#define NyLPC_TJsonRpcParserResult_TYPE_UNKNOWN        0\r
+#define NyLPC_TJsonRpcParserResult_TYPE_RESULT 1\r
+#define NyLPC_TJsonRpcParserResult_TYPE_METHOD 2\r
+\r
+/** NyLPC_TJsonRpcParserResultが格納できる引数の最大数。パラメータの最大数に等しくなります。*/\r
+#define NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX 16\r
+/**\r
+ * NyLPC_TJsonRpcParserResultが格納できるパラメータの総バイト数。\r
+ * (文字数+1)+(uint32|int32)*4+uint8の合計値です。\r
+ */\r
+#define NyLPC_TJsonRpcParserResult_PARAM_BUF 128\r
+\r
+/**\r
+ * JSONRPC構文のパース結果を格納します。\r
+ * 開発メモ\r
+ * 更新する場合は、param_indexまでの構造体のレイアウトを破壊しないようにしてください。\r
+ */\r
+union NyLPC_TJsonRpcParserResult\r
+{\r
+       NyLPC_TUInt8    type;                           //タイプ\r
+       /** この構造体は type==NyLPC_TJsonRpcParserResult_TYPE_METHODのときに有効です。*/\r
+       struct{\r
+               NyLPC_TUInt8    _type;                  //タイプ\r
+               NyLPC_TUInt8    func_number;    //確定した関数番号。\r
+               NyLPC_TUInt8    _padding[2];    //パディング\r
+               NyLPC_TInt32    id;                             //idパラメータの値\r
+               NyLPC_TChar             param_buf[NyLPC_TJsonRpcParserResult_PARAM_BUF];\r
+               NyLPC_TUInt8    param_index[NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX];\r
+               /** 関数の含まれるクラスへのポインタ。*/\r
+               const struct NyLPC_TJsonRpcClassDef* class_def;\r
+       }method;\r
+       struct{\r
+               NyLPC_TUInt8    _type;                  //タイプ\r
+               NyLPC_TUInt8    _padding[3];    //パディング\r
+               NyLPC_TInt32    id;                             //idパラメータの値\r
+               NyLPC_TChar             param_buf[NyLPC_TJsonRpcParserResult_PARAM_BUF];\r
+               NyLPC_TUInt8    param_index[NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX];\r
+       }result;\r
+       struct{\r
+               NyLPC_TUInt8    _type;          //タイプ\r
+               NyLPC_TInt8     _padding[3];//\r
+               NyLPC_TInt32    _id;            //idパラメータの値\r
+               NyLPC_TChar             param_buf[NyLPC_TJsonRpcParserResult_PARAM_BUF];\r
+               NyLPC_TUInt8    param_index[NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX];\r
+       }raw;\r
+};\r
+\r
+/**\r
+ * i_idx番目のパラメータをuint32としてo_valへ取り出します。\r
+ */\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getUInt32(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TUInt32* o_val);\r
+/**\r
+ * i_idx番目のパラメータをint32としてo_valへ取り出します。\r
+ */\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getInt32(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TInt32* o_val);\r
+/**\r
+ * i_idx番目のパラメータをchar[]としてo_valへ取り出します。\r
+ */\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getStr(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, const NyLPC_TChar** o_val);\r
+/**\r
+ * i_idx番目のパラメータをuint8としてo_valへ取り出します。\r
+ */\r
+NyLPC_TBool NyLPC_TJsonRpcParserResult_getByte(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TUInt8* o_val);\r
+\r
+/********************************************************************************\r
+ *\r
+ * NyLPC_TcJsonRpcParser\r
+ *\r
+ ********************************************************************************/\r
+/**\r
+ * JSONRPCの型定義定数です。\r
+ */\r
+#define NyLPC_cJsonRpcParser_TYPE_INT32                'd'\r
+#define NyLPC_cJsonRpcParser_TYPE_UINT32       'u'\r
+#define NyLPC_cJsonRpcParser_TYPE_STRING       's'\r
+#define NyLPC_cJsonRpcParser_TYPE_BYTE         'b'\r
+\r
+/**\r
+* JsonRPCメッセージをパースします。パース出来るメッセージは以下の通りです。\r
+* <p>\r
+* メッセージ形式\r
+* <pre>\r
+* METHOD:\r
+* {"method":METHOD,"version":VERSION,"params":PARAMS,"id":ID}\r
+* METHOD VERSION as string\r
+* ID as uint32\r
+* PARAMS as Array of (string|uint32|int32)\r
+* </pre>\r
+* </p>\r
+*/\r
+typedef struct NyLPC_TcJsonRpcParser NyLPC_TcJsonRpcParser_t;\r
+\r
+\r
+\r
+\r
+/** パーサの状態値*/\r
+typedef NyLPC_TUInt8 NyLPC_TcJsonRpcParser_TStatus;\r
+\r
+#define NyLPC_TcJsonRpcParser_ST_START                 0x01    //開始ブランケット受信待ち\r
+#define NyLPC_TcJsonRpcParser_ST_END                   0x02    //終了受信済\r
+#define NyLPC_TcJsonRpcParser_ST_ERROR                 0x03    //エラー発生\r
+#define NyLPC_TcJsonRpcParser_ST_NAME_Q                        0x04    //名前クオート受信待ち\r
+#define NyLPC_TcJsonRpcParser_ST_NAME_STR              0x05    //名前受信中\r
+#define NyLPC_TcJsonRpcParser_ST_NV_SEP                        0x06    //名前と値のセパレータ待ち\r
+#define NyLPC_TcJsonRpcParser_ST_VAL                   0x07    //値開始待ち\r
+#define NyLPC_TcJsonRpcParser_ST_VAL_STR               0x08    //文字列受信\r
+#define NyLPC_TcJsonRpcParser_ST_VAL_UINT              0x09    //UINT受信中\r
+#define NyLPC_TcJsonRpcParser_ST_VAL_INT               0x10    //INT受信中\r
+#define NyLPC_TcJsonRpcParser_ST_NEXT                  0x11    //次のNAMEもしくは終了ブランケット\r
+#define NyLPC_TcJsonRpcParser_ST_PARAMS                        0x12    //PARAM要素パース中\r
+\r
+\r
+\r
+/** NyLPC_TcJsonRpcParserの定数値です。 字句解析ワークメモリの長さ。256未満8*n-1の数を指定してください。 */\r
+#define NyLPC_TcJsonRpcParser_WORK_MAX 47\r
+\r
+/**\r
+ * クラス構造体です。\r
+ */\r
+struct NyLPC_TcJsonRpcParser\r
+{\r
+       const struct NyLPC_TJsonRpcClassDef** _class_def;\r
+       union{\r
+               struct{\r
+                       NyLPC_TChar     buf[NyLPC_TcJsonRpcParser_WORK_MAX];    //文字解析メモリ\r
+                       NyLPC_TUInt8    n;                                                                              //字句解析の文字数\r
+               }str;\r
+               struct{\r
+                       NyLPC_TInt32 v;\r
+                       NyLPC_TInt8     s;\r
+               }int32;\r
+               NyLPC_TUInt32 uint32;\r
+       }_work;\r
+       NyLPC_TcJsonRpcParser_TStatus   _st;            //パーサステータス\r
+       NyLPC_TUInt8    _pst;           //PARAMS解析ステータス\r
+       NyLPC_TUInt8    _name_id;       //解析中のNAME_ID\r
+       NyLPC_TUInt8    _pcounter;      //パラメタ解析に使うワークカウンタ\r
+       union NyLPC_TJsonRpcParserResult* _result;//出力格納先\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * インスタンスを初期化します。\r
+ * @param i_class_def\r
+ * クラステーブルの配列です。NULLで終端します。\r
+ */\r
+void NyLPC_cJsonRpcParser_initialize(\r
+       NyLPC_TcJsonRpcParser_t* i_inst,\r
+       const struct NyLPC_TJsonRpcClassDef** i_class_def);\r
+\r
+#define NyLPC_cJsonRpcParser_finalize(i)\r
+/**\r
+ * パーサの状態を初期化します。\r
+ * @param i_result\r
+ * パース結果の出力先構造体のアドレスです。\r
+ */\r
+void NyLPC_cJsonRpcParser_initParser(NyLPC_TcJsonRpcParser_t* i_inst, union NyLPC_TJsonRpcParserResult* i_result);\r
+/**\r
+ * パーサに文字列を入力します。入力後は、NyLPC_cJsonRpcParser_getStatusでパーサの状態をチェックしてください。\r
+ */\r
+void NyLPC_cJsonRpcParser_putChar(NyLPC_TcJsonRpcParser_t* i_inst, char i_c);\r
+\r
+#define NyLPC_cJsonRpcParser_getStatus(i) ((i)->_st)\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+\r
+#endif /* NYLPC_CJSONRPCPARSER4_H_ */\r
index 60ab918..e4766c7 100644 (file)
@@ -42,6 +42,7 @@
 #include "../http/NyLPC_cHttpBasicBodyParser.h"\r
 #include "../http/NyLPC_cHttpBodyParser.h"\r
 #include "../http/NyLPC_cBase64.h"\r
+#include "../http/json/NyLPC_cJsonRpcParser.h"\r
 #ifdef __cplusplus\r
 extern "C" {\r
 #endif /* __cplusplus */\r
diff --git a/lib/src/net/httpd/mod/NyLPC_cModJsonRpc.c b/lib/src/net/httpd/mod/NyLPC_cModJsonRpc.c
new file mode 100644 (file)
index 0000000..83b0e93
--- /dev/null
@@ -0,0 +1,110 @@
+#include "NyLPC_cModJsonRpc.h"\r
+\r
+\r
+\r
+\r
+void NyLPC_cModJsonRpc_initialize(NyLPC_TcModJsonRpc_t* i_inst,const NyLPC_TChar* i_ref_root_path,const struct NyLPC_TJsonRpcClassDef** i_class_tbl)\r
+{\r
+       NyLPC_cModWebSocket_initialize(&i_inst->super,i_ref_root_path);\r
+       NyLPC_cJsonRpcParser_initialize(&i_inst->_rpc_parser,i_class_tbl);\r
+}\r
+void NyLPC_cModJsonRpc_finalize(NyLPC_TcModJsonRpc_t* i_inst)\r
+{\r
+       NyLPC_cJsonRpcParser_finalize(&i_inst->_rpc_parser);\r
+       NyLPC_cModWebSocket_finalize(&i_inst->super);\r
+}\r
+#define NyLPC_cModJsonRpc_canHandle(i,c) NyLPC_cModWebSocket_canHandle(&((i)->super),(c))\r
+\r
+#define NyLPC_cModJsonRpc_close(i,t) NyLPC_cModWebSocket_close(&((i)->super),(t))\r
+\r
+\r
+NyLPC_TBool NyLPC_cModJsonRpc_execute(NyLPC_TcModJsonRpc_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)\r
+{\r
+       //executeで強制初期化\r
+       NyLPC_cJsonRpcParser_initParser(&i_inst->_rpc_parser,&i_inst->_result);\r
+       return NyLPC_cModWebSocket_execute(&((i_inst)->super),i_connection);\r
+}\r
+\r
+static NyLPC_TInt32 readHandler(void* i_param,NyLPC_TChar i_c)\r
+{\r
+       NyLPC_TcModJsonRpc_t* inst=(NyLPC_TcModJsonRpc_t*)i_param;\r
+       NyLPC_cJsonRpcParser_putChar(&inst->_rpc_parser,i_c);\r
+       switch(NyLPC_cJsonRpcParser_getStatus(&(inst->_rpc_parser))){\r
+       case NyLPC_TcJsonRpcParser_ST_END:\r
+               return 0;//終端到達。中断\r
+       case NyLPC_TcJsonRpcParser_ST_ERROR:\r
+               return -1;//エラー\r
+       default:\r
+               return 1;//次の文字をリクエスト\r
+       }\r
+}\r
+\r
+\r
+NyLPC_TBool NyLPC_cModJsonRpc_processRpcMessage(NyLPC_TcModJsonRpc_t* i_inst)\r
+{\r
+       //終了した場合のみパーサステータスを初期化。\r
+       switch(NyLPC_cJsonRpcParser_getStatus(&i_inst->_rpc_parser)){\r
+       case NyLPC_TcJsonRpcParser_ST_END:\r
+               NyLPC_cJsonRpcParser_initParser(&i_inst->_rpc_parser,&i_inst->_result);\r
+               break;\r
+       case NyLPC_TcJsonRpcParser_ST_ERROR:\r
+               //パーサがエラーを検出してたら何もしない。\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       //コールバックハンドラで受信\r
+       if(NyLPC_cModWebSocket_readCB(&(i_inst->super),readHandler,i_inst)<0){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+\r
+const union NyLPC_TJsonRpcParserResult* NyLPC_cModJsonRpc_getMessage(NyLPC_TcModJsonRpc_t* i_inst)\r
+{\r
+       return (NyLPC_cJsonRpcParser_getStatus(&i_inst->_rpc_parser)!=NyLPC_TcJsonRpcParser_ST_END)?NULL:(&i_inst->_result);\r
+}\r
+\r
+NyLPC_TBool NyLPC_cModJsonRpc_putRawMessageV(NyLPC_TcModJsonRpc_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args)\r
+{\r
+       return NyLPC_cModWebSocket_writeFormatV(&i_inst->super,i_fmt,i_args);\r
+}\r
+NyLPC_TBool NyLPC_cModJsonRpc_putRawMessage(NyLPC_TcModJsonRpc_t* i_inst,const NyLPC_TChar* i_fmt,...)\r
+{\r
+       NyLPC_TBool r;\r
+       va_list a;\r
+       va_start(a,i_fmt);\r
+       r=NyLPC_cModWebSocket_writeFormatV(&i_inst->super,i_fmt,a);\r
+       va_end(a);\r
+       return r;\r
+}\r
+\r
+\r
+\r
+/**\r
+ * @param i_params_fmt\r
+ * パラメータ部のフォーマット文字列です。NyLPC_cFormatWriterと同等の構文を使用できます。\r
+ * ここで指定した書式文字列は、"そのまま"パラメータ部に表示されます。文字列を返す場合は、次のように\"でエスケープしてください。\r
+ * '0,1,2,-1,\"result\",3'\r
+ */\r
+NyLPC_TBool NyLPC_cModJsonRpc_putResult(NyLPC_TcModJsonRpc_t* i_inst,NyLPC_TUInt32 i_id,NyLPC_TInt32 i_result,const NyLPC_TChar* i_params_fmt,...)\r
+{\r
+       NyLPC_TBool r;\r
+       va_list a;\r
+       NyLPC_TInt16 l;\r
+\r
+       //書き込み文字数の事前計算\r
+       va_start(a,i_params_fmt);\r
+       l=NyLPC_cModWebSocket_testFormat(&i_inst->super,"{\"result\":%d,\"params\":[",i_result);\r
+       l+=NyLPC_cModWebSocket_testFormatV(&i_inst->super,i_params_fmt,a);\r
+       l+=NyLPC_cModWebSocket_testFormat(&i_inst->super,"],\"id\":%d}",i_id);\r
+       va_end(a);\r
+\r
+       //バルク書き込み\r
+       va_start(a,i_params_fmt);\r
+       NyLPC_cModWebSocket_startBulkWrite(&i_inst->super,l);\r
+       r=NyLPC_cModWebSocket_writeBulkFormat(&i_inst->super,"{\"result\":%d,\"params\":[",i_result);\r
+       r=r||NyLPC_cModWebSocket_writeBulkFormatV(&i_inst->super,i_params_fmt,a);\r
+       r=r||NyLPC_cModWebSocket_writeBulkFormat(&i_inst->super,"],\"id\":%d}",i_id);\r
+       r=r||NyLPC_cModWebSocket_endBulkWrite(&i_inst->super);\r
+       va_end(a);\r
+       return r;\r
+}\r
diff --git a/lib/src/net/httpd/mod/NyLPC_cModJsonRpc.h b/lib/src/net/httpd/mod/NyLPC_cModJsonRpc.h
new file mode 100644 (file)
index 0000000..6794a37
--- /dev/null
@@ -0,0 +1,81 @@
+/*********************************************************************************\r
+ * PROJECT: MiMic\r
+ * --------------------------------------------------------------------------------\r
+ *\r
+ * This file is part of MiMic\r
+ * Copyright (C)2011 Ryo Iizuka\r
+ *\r
+ * MiMic is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU Lesser General Public License as published\r
+ * by the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
+ *\r
+ * For further information please contact.\r
+ *     http://nyatla.jp/\r
+ *     <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
+ *\r
+ *********************************************************************************/\r
+#ifndef NYLPC_CMODJSONRPC_H_\r
+#define NYLPC_CMODJSONRPC_H_\r
+#include "NyLPC_http.h"\r
+#include "../NyLPC_cHttpdConnection.h"\r
+#include "NyLPC_cModWebSocket.h"\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * WebSocketストリームからJSONRPC電文を取り込むモジュールです。\r
+ */\r
+typedef struct NyLPC_TcModJsonRpc NyLPC_TcModJsonRpc_t;\r
+\r
+\r
+/**\r
+ * クラス構造体\r
+ */\r
+struct NyLPC_TcModJsonRpc\r
+{\r
+       NyLPC_TcModWebSocket_t super;\r
+       NyLPC_TcJsonRpcParser_t _rpc_parser;\r
+       union NyLPC_TJsonRpcParserResult _result;\r
+};\r
+\r
+\r
+void NyLPC_cModJsonRpc_initialize(NyLPC_TcModJsonRpc_t* i_inst,const NyLPC_TChar* i_ref_root_path,const struct NyLPC_TJsonRpcClassDef** i_class_tbl);\r
+void NyLPC_cModJsonRpc_finalize(NyLPC_TcModJsonRpc_t* i_inst);\r
+#define NyLPC_cModJsonRpc_canHandle(i,c) NyLPC_cModWebSocket_canHandle(&((i)->super),(c))\r
+#define NyLPC_cModJsonRpc_close(i,t) NyLPC_cModWebSocket_close(&((i)->super),(t))\r
+\r
+\r
+NyLPC_TBool NyLPC_cModJsonRpc_execute(NyLPC_TcModJsonRpc_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection);\r
+\r
+/**\r
+ * Execute実行後に繰り返し実行できます。\r
+ * trueを返却した場合は、NyLPC_cModJsonRpc_getRpcCall関数で結果を取得できるか調べてください。\r
+ * @return\r
+ * JSONRPCの処理を継続して行えるかを返します。\r
+ * falseの場合、JSONRPCの構文解析は失敗し、Websocketは閉じられます。Websocketの受信ループを終了してください。\r
+ */\r
+NyLPC_TBool NyLPC_cModJsonRpc_processRpcMessage(NyLPC_TcModJsonRpc_t* i_inst);\r
+\r
+/**\r
+ * JSONRPCの構文解析結果を返します。\r
+ * @return\r
+ * JSONRPC電文が確定した場合、結果を格納した構造体を返します。構造体の有効期限は、次回にNyLPC_cModJsonRpc_processRpcMessageを実行するまでです。\r
+ * NULLを返した場合は、引き続きNyLPC_cModJsonRpc_processRpcMessageを実行する必要があります。\r
+ */\r
+const union NyLPC_TJsonRpcParserResult* NyLPC_cModJsonRpc_getRpcCall(NyLPC_TcModJsonRpc_t* i_inst);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+\r
+#endif /* NYLPC_CMODJSONRPC_H_ */\r
index 0817bd3..e759516 100644 (file)
@@ -467,6 +467,86 @@ Timeout:
        return;\r
 }\r
 \r
+\r
+/**\r
+ * 受信データをコールバック関数に通知するNyLPC_cModWebSocket_readです。\r
+ * @return\r
+ * n>0:データ受信\r
+ * 0  :タイムアウト。コネクションの状態は変化しない。\r
+ * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。\r
+ */\r
+NyLPC_TInt16 NyLPC_cModWebSocket_readCB(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcModWebSocket_onRreadCB i_cb,void* i_cb_param)\r
+{\r
+       const NyLPC_TUInt8* rx;\r
+       NyLPC_TInt32 rs,rd,i;\r
+       //ストリームの状態を更新する。\r
+       NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);\r
+\r
+       switch(i_inst->_payload_st)\r
+       {\r
+       case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:\r
+               break;//処理継続\r
+       case NyLPC_TcModWebSocket_ST_START_PAYLOAD:\r
+               //タイムアウト扱い\r
+               return 0;\r
+       default:\r
+               return -1;\r
+       }\r
+       //読み出し可能なデータをパース\r
+       rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);\r
+       if(rs<=0){\r
+               if(rs<0){\r
+                       //Error\r
+                       NyLPC_OnErrorGoto(Error);\r
+               }\r
+               //Timeout\r
+               goto Timeout;\r
+       }\r
+       rd=0;//読みだしたバイト数\r
+       //アンマスク\r
+       if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){\r
+               //マスク有の時\r
+               for(i=0;i<rs;i++){\r
+                       rd++;\r
+                       switch(i_cb(i_cb_param,rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4])){\r
+                       case 1:\r
+                               continue;\r
+                       case 0:\r
+                               break;\r
+                       default:\r
+                               NyLPC_OnErrorGoto(Error);\r
+                       }\r
+               }\r
+       }else{\r
+               //マスクなしの時\r
+               for(i=0;i<rs;i++){\r
+                       rd++;\r
+                       switch(i_cb(i_cb_param,rx[i])){\r
+                       case 1:\r
+                               continue;\r
+                       case 0:\r
+                               break;\r
+                       default:\r
+                               NyLPC_OnErrorGoto(Error);\r
+                       }\r
+               }\r
+       }\r
+       //読取位置を移動\r
+       NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rd);\r
+       i_inst->payload_ptr+=rd;\r
+       if(i_inst->payload_size==i_inst->payload_ptr){\r
+               i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;\r
+       }\r
+       return rd;\r
+       //処理されなければエラー\r
+Error:\r
+       NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);\r
+       i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;\r
+       return -1;\r
+Timeout:\r
+       return 0;\r
+}\r
+\r
 /**\r
  * @return\r
  * n>0:データ受信\r
@@ -578,10 +658,11 @@ Error:
        return NyLPC_TBool_FALSE;\r
 }\r
 \r
+#ifndef va_copy\r
+#    define va_copy(dest, src) ((dest) = (src))\r
+#endif\r
 \r
-\r
-\r
-NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)\r
+NyLPC_TBool NyLPC_cModWebSocket_writeFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)\r
 {\r
        NyLPC_TInt16 l;\r
        va_list a;\r
@@ -589,19 +670,16 @@ NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const
        NyLPC_cModWebSocket_update(i_inst,0);\r
 \r
        //書式文字列の長さを計算\r
-       va_start(a,i_fmt);\r
+       va_copy(a,args);\r
        l=NyLPC_cFormatWriter_length(i_fmt,a);\r
        va_end(a);\r
        if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,l)){\r
                //CLOSE\r
                NyLPC_OnErrorGoto(Error);\r
        }\r
-       va_start(a,i_fmt);\r
-       if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,a)){\r
-               va_end(a);\r
+       if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){\r
                NyLPC_OnErrorGoto(Error);\r
        }\r
-       va_end(a);\r
        NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));\r
        return NyLPC_TBool_TRUE;\r
 Error:\r
@@ -610,6 +688,16 @@ Error:
        return NyLPC_TBool_FALSE;\r
 }\r
 \r
+NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)\r
+{\r
+       NyLPC_TBool r;\r
+       va_list a;\r
+       va_start(a,i_fmt);\r
+       r=NyLPC_cModWebSocket_writeFormatV(i_inst,i_fmt,a);\r
+       va_end(a);\r
+       return r;\r
+}\r
+\r
 \r
 \r
 \r
@@ -647,3 +735,64 @@ void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_co
        //切断\r
        NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);\r
 }\r
+\r
+\r
+NyLPC_TInt16 NyLPC_cModWebSocket_testFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)\r
+{\r
+       return NyLPC_cFormatWriter_length(i_fmt,args);\r
+}\r
+NyLPC_TInt16 NyLPC_cModWebSocket_testFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)\r
+{\r
+       NyLPC_TInt16 r;\r
+       va_list a;\r
+       va_start(a,i_fmt);\r
+       r=NyLPC_cFormatWriter_length(i_fmt,a);\r
+       va_end(a);\r
+       return r;\r
+}\r
+\r
+\r
+NyLPC_TBool NyLPC_cModWebSocket_startBulkWrite(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)\r
+{\r
+       //ストリームの状態を更新する。\r
+       NyLPC_cModWebSocket_update(i_inst,0);\r
+       //ペイロードヘッダの出力\r
+       if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){\r
+               //CLOSE\r
+               NyLPC_OnErrorGoto(Error);\r
+       }\r
+       return NyLPC_TBool_TRUE;\r
+Error:\r
+       NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);\r
+       i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;\r
+       return NyLPC_TBool_FALSE;\r
+}\r
+/**\r
+ * バルク書き込みを終了します。\r
+ * この関数をコールする前に、startBulkWrite関数のi_lenで指定した大きさのデータを入力し終えている必要があります。\r
+ * 過不足があった場合、関数は失敗するか、WebSocketセッションが破壊されます。\r
+ */\r
+NyLPC_TBool NyLPC_cModWebSocket_endBulkWrite(NyLPC_TcModWebSocket_t* i_inst)\r
+{\r
+       if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       //送信サイズ確認?\r
+       NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));\r
+       return NyLPC_TBool_TRUE;\r
+}\r
+\r
+NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)\r
+{\r
+       if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){\r
+               return NyLPC_TBool_FALSE;\r
+       }\r
+       if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){\r
+               NyLPC_OnErrorGoto(Error);\r
+       }\r
+       return NyLPC_TBool_TRUE;\r
+Error:\r
+       NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);\r
+       i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;\r
+       return NyLPC_TBool_FALSE;\r
+}\r
index 776e4e0..18b37df 100644 (file)
@@ -85,6 +85,16 @@ struct NyLPC_TcModWebSocket
        NyLPC_TcHttpdConnection_t* _ref_connection;\r
 };\r
 \r
+\r
+/**\r
+ * NyLPC_cModWebSocket_readCB関数のコールバックハンドラです。\r
+ * @return\r
+ * -1    :エラーが発生したことを通知します。NyLPC_cModWebSocket_readCBは負数を返してクローズします。\r
+ *  0    :読出しの中断を通知します。NyLPC_cModWebSocket_readCBは読み取ったデータ数を記録して正常終了します。\r
+ *  1    :読出しの継続を通知します。NyLPC_cModWebSocket_readCBは継続してデータを通知します。\r
+ */\r
+typedef NyLPC_TInt32 (*NyLPC_TcModWebSocket_onRreadCB)(void* i_param,NyLPC_TChar i_c);\r
+\r
 /**\r
  * コンストラクタ。\r
  */\r
@@ -110,6 +120,17 @@ NyLPC_TBool NyLPC_cModWebSocket_execute(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcH
 NyLPC_TBool NyLPC_cModWebSocket_canRead(const NyLPC_TcModWebSocket_t* i_inst);\r
 \r
 \r
+/**\r
+ * 受信データをコールバック関数に通知するNyLPC_cModWebSocket_readです。\r
+ * @param i_cb\r
+ * NyLPC_TcModWebSocket_onRreadCBのi_paramに設定する数値です。\r
+ * @return\r
+ * n>0:データ受信\r
+ * 0  :タイムアウト。コネクションの状態は変化しない。\r
+ * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。\r
+ */\r
+NyLPC_TInt16 NyLPC_cModWebSocket_readCB(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcModWebSocket_onRreadCB i_cb,void* i_cb_param);\r
+\r
 \r
 /**\r
  * ストリームからデータを受信して、可能ならi_bufに最大i_buf_lenバイトのデータを受信します。\r
@@ -132,7 +153,32 @@ NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,const void*
  * 書式文字列を出力します。\r
  */\r
 NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...);\r
+NyLPC_TBool NyLPC_cModWebSocket_writeFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args);\r
+\r
+\r
+/**\r
+ * 書式文字列を出力した場合の文字数を返します。\r
+ * この関数は、startBulkWrite関数のi_lenパラメータに渡す値を計算するときに使います。\r
+ */\r
+NyLPC_TInt16 NyLPC_cModWebSocket_testFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args);\r
+NyLPC_TInt16 NyLPC_cModWebSocket_testFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...);\r
 \r
+/**\r
+ * バルク書き込みを開始します。\r
+ * バルク書き込みは、endBulkWrite関数をコールするまでにwriteBulk関数で入力されたデータを、1つのi_lenサイズのWebsocketパケットとして送信します。\r
+ * バルク書き込み中は、通常のwrite関数を使用することができません。\r
+ * @param i_len\r
+ * NyLPC_cModWebSocket_endBulkFormatでバルク書き込みを終了するまでに入力するデータサイズを指定します。\r
+ */\r
+NyLPC_TBool NyLPC_cModWebSocket_startBulkWrite(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len);\r
+/**\r
+ * バルク書き込みを終了します。\r
+ * この関数をコールする前に、startBulkWrite関数のi_lenで指定した大きさのデータを入力し終えている必要があります。\r
+ * 過不足があった場合、WebSocketセッションが破壊されます。\r
+ */\r
+NyLPC_TBool NyLPC_cModWebSocket_endBulkWrite(NyLPC_TcModWebSocket_t* i_inst);\r
+NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args);\r
+NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...);\r
 \r
 /**\r
  * CLOSEパケットを送信してコネクションを閉じます。\r
index c505155..804b4b6 100644 (file)
@@ -40,6 +40,8 @@ NyLPC_TBool NyLPC_cModWebSocket_writePayloadHeader(NyLPC_TcModWebSocket_t* i_ins
 \r
 void NyLPC_cModWebSocket_update(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt32 i_time_out);\r
 \r
+\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif /* __cplusplus */\r