1 /*********************************************************************************
\r
3 * --------------------------------------------------------------------------------
\r
5 * This file is part of MiMic
\r
6 * Copyright (C)2011 Ryo Iizuka
\r
8 * MiMic is free software: you can redistribute it and/or modify
\r
9 * it under the terms of the GNU Lesser General Public License as published
\r
10 * by the Free Software Foundation, either version 3 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU Lesser General Public License
\r
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
21 * For further information please contact.
\r
23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
25 *********************************************************************************/
\r
26 #include "NyLPC_cModMiMicSetting.h"
\r
27 #include "NyLPC_stdlib.h"
\r
28 #include "../NyLPC_cHttpdUtils.h"
\r
29 #include "NyLPC_http.h"
\r
30 #include "NyLPC_mimicVm.h"
\r
31 #include "NyLPC_flash.h"
\r
32 #include "../NyLPC_cHttpdConnection_protected.h"
\r
33 //#include <ctype.h>
\r
35 #define MOD_VERSION "ModMiMicSetting/1.4"
\r
36 #define SIZE_OF_SETUP_PARAM 8
\r
37 struct TModMiMicSettingRequest
\r
39 struct NyLPC_THttpBasicHeader super;
\r
40 NyLPC_TUInt8 _content_id;
\r
42 NyLPC_TUInt8 _qery_name_id;
\r
43 NyLPC_TUInt8 _astate;
\r
44 NyLPC_TInt16 _prefix_len;
\r
45 NyLPC_TcStr_t _tstr;
\r
46 NyLPC_TChar _tstr_buf[16];
\r
48 NyLPC_TcMiMicDbCompiler_t _binparser;
\r
51 * スタックサイズ削減のための構造体。tmpは受信処理に使用。
\r
52 * memimgはFlashへ書き込むときに使用。
\r
56 * 受信用構造体。host_name,param_buf[6]までのデータは、memimgのfast_boot以降のデータ構造と位置をあわせてください。
\r
57 * param_buf[7]以降については値変換必須
\r
58 * tmpにデータを作成後にmemimgへ整形して書きこむかんじ。
\r
61 NyLPC_TUInt16 param_len;
\r
62 NyLPC_TUInt16 host_len;
\r
63 NyLPC_TChar host_name[NyLPC_TcNetConfig_HOSTNAME_LEN];
\r
65 * 詳細はNyLPC_TcModMiMicSetting_tを参照
\r
67 NyLPC_TUInt32 param_buf[SIZE_OF_SETUP_PARAM];
\r
68 NyLPC_TUInt32 cval;//コマンド値
\r
73 struct NyLPC_TMiMicConfigulation memimg;
\r
77 * 不明な名前の場合は、ここに名前をコピー
\r
79 NyLPC_TChar path[32];
\r
84 #define ST_PARSE_PATH 1
\r
85 #define ST_PARSE_QUERY_NAME 2
\r
86 #define ST_PARSE_QUERY_VALUE 3 //Query読み出し中
\r
87 #define ST_PARSE_QUERY_VALUE_P 4
\r
88 #define ST_PARSE_QUERY_VALUE_C 5
\r
89 #define ST_PARSE_QUERY_VALUE_HOST 6
\r
91 * コンテンツID定義(コンテンツ名に対応)
\r
93 #define CONTENT_ID_UNKNOWN 1
\r
94 #define CONTENT_ID_SETUP 2
\r
95 #define CONTENT_ID_INDEX 3
\r
96 #define CONTENT_ID_STATUS 4
\r
97 #define CONTENT_ID_CSS 5
\r
98 #define CONTENT_ID_LOGO 6
\r
100 #define QNAME_ID_P 4
\r
101 #define QNAME_ID_C 5
\r
102 #define QNAME_ID_HOST 6
\r
103 #define QNAME_ID_UNKNOWN 0
\r
105 #define QVAL_C_GET 1
\r
106 #define QVAL_C_UPDATE 2
\r
107 #define QVAL_C_UNKNOWN 0
\r
110 static const struct NyLPC_TTextIdTbl url_tbl[]=
\r
112 {"setup.api",CONTENT_ID_SETUP},
\r
113 {NULL,CONTENT_ID_UNKNOWN}
\r
116 static const struct NyLPC_TTextIdTbl qname_id_table[]=
\r
120 {"host",QNAME_ID_HOST},
\r
121 {NULL,QNAME_ID_UNKNOWN}
\r
127 static NyLPC_TBool urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
\r
130 struct TModMiMicSettingRequest* out=(struct TModMiMicSettingRequest*)o_out;
\r
132 if(out->_prefix_len<0){
\r
133 out->_prefix_len++;
\r
134 return NyLPC_TBool_TRUE;//読み飛ばし
\r
136 if(out->_astate==ST_PARSE_PATH){
\r
137 if(i_c!='\0' && i_c!='?'){
\r
138 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
\r
139 NyLPC_OnErrorGoto(ERROR);
\r
141 return NyLPC_TBool_TRUE;
\r
143 out->_content_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),url_tbl);
\r
144 switch(out->_content_id)
\r
146 case CONTENT_ID_SETUP:
\r
147 out->content.setup.tmp.param_len=0;//クエリが無い場合の初期値
\r
148 out->content.setup.tmp.host_len =0;//クエリが無い場合の初期値
\r
149 out->content.setup.tmp.cval=QVAL_C_UNKNOWN;
\r
154 NyLPC_cStr_clear(&(out->_tstr));
\r
155 out->_astate=ST_PARSE_QUERY_NAME;//クエリ名解析へ
\r
156 return NyLPC_TBool_TRUE;
\r
158 switch(out->_content_id)
\r
160 case CONTENT_ID_SETUP:
\r
161 switch(out->_astate){
\r
162 case ST_PARSE_QUERY_NAME:
\r
163 if(i_c!='\0' && i_c!='&' && i_c!='='){
\r
164 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
\r
165 NyLPC_OnErrorGoto(ERROR);
\r
167 return NyLPC_TBool_TRUE;
\r
170 out->_qery_name_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),qname_id_table);
\r
171 NyLPC_cStr_clear(&(out->_tstr));
\r
173 switch(out->_qery_name_id){
\r
175 out->_astate=ST_PARSE_QUERY_VALUE_P;//MIMICBCのDBパラメータパーサを借用。
\r
176 out->content.setup.tmp.param_len=0;
\r
179 out->_astate=ST_PARSE_QUERY_VALUE_C;
\r
181 case QNAME_ID_HOST:
\r
182 out->_astate=ST_PARSE_QUERY_VALUE_HOST;//_host_nameに蓄積
\r
183 out->content.setup.tmp.host_len=0;
\r
186 out->_astate=ST_PARSE_QUERY_VALUE;
\r
189 return NyLPC_TBool_TRUE;
\r
190 case ST_PARSE_QUERY_VALUE:
\r
192 if(i_c!='\0' && i_c!='&'){
\r
193 return NyLPC_TBool_TRUE;
\r
196 out->_astate=ST_PARSE_QUERY_NAME;
\r
197 return NyLPC_TBool_TRUE;
\r
198 case ST_PARSE_QUERY_VALUE_HOST:
\r
200 if(i_c!='\0' && i_c!='&'){
\r
201 //許可する文字列は、[:AlNum:]||'_'
\r
202 if(!isalnum((int)i_c) && i_c!='_'){
\r
203 NyLPC_OnErrorGoto(ERROR);
\r
205 out->content.setup.tmp.host_name[out->content.setup.tmp.host_len++]=i_c;
\r
206 if(out->content.setup.tmp.host_len>=NyLPC_TcNetConfig_HOSTNAME_LEN){
\r
208 NyLPC_OnErrorGoto(ERROR);
\r
210 return NyLPC_TBool_TRUE;
\r
213 out->content.setup.tmp.host_name[out->content.setup.tmp.host_len]='\0';
\r
214 out->_astate=ST_PARSE_QUERY_NAME;
\r
215 return NyLPC_TBool_TRUE;
\r
216 case ST_PARSE_QUERY_VALUE_C:
\r
217 if(i_c!='\0' && i_c!='&'){
\r
218 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
\r
219 NyLPC_OnErrorGoto(ERROR);
\r
221 return NyLPC_TBool_TRUE;
\r
223 if(NyLPC_cStr_isEqual(&out->_tstr,"get")){
\r
224 out->content.setup.tmp.cval=QVAL_C_GET;
\r
225 }else if(NyLPC_cStr_isEqual(&out->_tstr,"update")){
\r
226 out->content.setup.tmp.cval=QVAL_C_UPDATE;
\r
228 NyLPC_OnErrorGoto(ERROR);
\r
230 out->_astate=ST_PARSE_QUERY_NAME;
\r
231 NyLPC_cStr_clear(&(out->_tstr));
\r
232 return NyLPC_TBool_TRUE;
\r
233 case ST_PARSE_QUERY_VALUE_P:
\r
234 if(i_c!='\0' && i_c!='&'){
\r
235 if(out->content.setup.tmp.param_len>=SIZE_OF_SETUP_PARAM)
\r
237 NyLPC_OnErrorGoto(ERROR);
\r
239 switch(NyLPC_cMiMicDbCompiler_compileFragment2(&(out->_binparser),i_c,out->content.setup.tmp.param_buf+out->content.setup.tmp.param_len))
\r
241 case NyLPC_TcMiMicDbCompiler_RET_CONTINUE:
\r
243 case NyLPC_TcMiMicDbCompiler_RET_OK:
\r
244 out->content.setup.tmp.param_len++;
\r
246 case NyLPC_TcMiMicDbCompiler_RET_ERROR:
\r
249 NyLPC_OnErrorGoto(ERROR);
\r
251 return NyLPC_TBool_TRUE;
\r
254 if(NyLPC_cMiMicDbCompiler_hasFragment(&(out->_binparser))){
\r
256 NyLPC_OnErrorGoto(ERROR);
\r
259 out->_astate=ST_PARSE_QUERY_NAME;
\r
260 NyLPC_cStr_clear(&(out->_tstr));
\r
261 return NyLPC_TBool_TRUE;
\r
265 NyLPC_OnErrorGoto(ERROR);
\r
267 NyLPC_OnErrorGoto(ERROR);
\r
269 return NyLPC_TBool_TRUE;
\r
271 return NyLPC_TBool_FALSE;
\r
276 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler=
\r
286 void NyLPC_cModMiMicSetting_initialize(NyLPC_TcModMiMicSetting_t* i_inst,const NyLPC_TChar* i_ref_root_path)
\r
288 NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_root_path,NULL,0);
\r
290 void NyLPC_cModMiMicSetting_finalize(NyLPC_TcModMiMicSetting_t* i_inst)
\r
292 NyLPC_cModRomFiles_finalize(&i_inst->super);
\r
295 * モジュールがコネクションをハンドリングできるかを返します。
\r
297 NyLPC_TBool NyLPC_cModMiMicSetting_canHandle(NyLPC_TcModMiMicSetting_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
\r
299 return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection);
\r
304 static void setup_proc(NyLPC_TcHttpdConnection_t* i_connection,struct TModMiMicSettingRequest* i_req);
\r
309 NyLPC_TBool NyLPC_cModMiMicSetting_execute(NyLPC_TcModMiMicSetting_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
\r
311 NyLPC_TUInt8 method_type;
\r
312 struct TModMiMicSettingRequest header;
\r
313 NyLPC_TcHttpBasicHeaderParser_t parser;
\r
315 //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却)
\r
316 NyLPC_cHttpdConnection_setReqStatusParsed(i_connection);
\r
319 header._prefix_len=-((NyLPC_TInt16)strlen(i_inst->super._ref_root_path)+2);
\r
320 header._astate=ST_PARSE_PATH;
\r
321 NyLPC_cStr_initialize(&header._tstr,header._tstr_buf,16);
\r
322 NyLPC_cMiMicDbCompiler_initialize(&header._binparser);
\r
324 NyLPC_cHttpBasicHeaderParser_initialize(&parser,&handler);
\r
326 NyLPC_cHttpBasicHeaderParser_parseInit(&parser,&(header.super));
\r
327 NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&parser,&header.super);
\r
329 if(!NyLPC_cHttpBasicHeaderParser_parseStream(&parser,NyLPC_cHttpdConnection_refStream(i_connection),&(header.super))){
\r
330 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
331 NyLPC_OnErrorGoto(Error2);
\r
333 if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&parser,&(header.super))){
\r
334 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
335 NyLPC_OnErrorGoto(Error2);
\r
338 method_type=NyLPC_cHttpdConnection_getMethod(i_connection);
\r
339 if(method_type!=NyLPC_THttpMethodType_GET && method_type!=NyLPC_THttpMethodType_HEAD)
\r
341 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,405);
\r
342 NyLPC_OnErrorGoto(Error2);
\r
344 //Request::ConnectionがClose設定,又はHTTP1.1では無い場合,CLOSE
\r
345 if(header.super.connection==NyLPC_THttpMessgeHeader_Connection_CLOSE || header.super.startline.req.version!=NyLPC_THttpVersion_11)
\r
347 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE);
\r
350 switch(header._content_id)
\r
352 case CONTENT_ID_SETUP:
\r
353 setup_proc(i_connection,&header);
\r
355 case CONTENT_ID_UNKNOWN:
\r
357 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
358 NyLPC_OnErrorGoto(Error2);
\r
360 NyLPC_cHttpBasicHeaderParser_finalize(&parser);
\r
361 NyLPC_cMiMicDbCompiler_finalize(&header._binparser);
\r
362 NyLPC_cStr_finalize(&(header._tstr));
\r
363 return NyLPC_TBool_TRUE;
\r
365 NyLPC_cHttpBasicHeaderParser_finalize(&parser);
\r
366 NyLPC_cMiMicDbCompiler_finalize(&header._binparser);
\r
367 NyLPC_cStr_finalize(&(header._tstr));
\r
369 return NyLPC_TBool_FALSE;
\r
373 static void setup_proc(NyLPC_TcHttpdConnection_t* i_connection,struct TModMiMicSettingRequest* i_req)
\r
376 const struct NyLPC_TMiMicConfigulation* config;
\r
377 const NyLPC_TcNetConfig_t* currebt_cfg;
\r
378 const struct NyLPC_TNetInterfaceInfo* netif_info;
\r
380 (NyLPC_cHttpdConnection_getMethod(i_connection)==NyLPC_THttpMethodType_GET)||
\r
381 (NyLPC_cHttpdConnection_getMethod(i_connection)==NyLPC_THttpMethodType_HEAD));
\r
383 switch(i_req->content.setup.tmp.cval){
\r
385 if(!NyLPC_cHttpdUtils_sendJsonHeader(i_connection)){
\r
386 NyLPC_OnErrorGoto(Error);
\r
388 if(NyLPC_cHttpdConnection_getMethod(i_connection)==NyLPC_THttpMethodType_GET){
\r
389 config=NyLPC_cMiMicConfiglation_loadFromFlash();
\r
391 if(!NyLPC_cHttpdConnection_sendResponseBodyF(i_connection,
\r
393 "\"application\":\""MOD_VERSION";%s;%s(%s)\","
\r
394 "\"landev\":\"%s\",",
\r
395 NyLPC_cMiMicEnv_getStrProperty(NyLPC_cMiMicEnv_VERSION),
\r
396 NyLPC_cMiMicEnv_getStrProperty(NyLPC_cMiMicEnv_SHORT_NAME),
\r
397 NyLPC_cMiMicEnv_getStrProperty(NyLPC_cMiMicEnv_MCU_NAME),
\r
398 NyLPC_cMiMicEnv_getStrProperty(NyLPC_cMiMicEnv_ETHERNET_PHY)
\r
401 NyLPC_OnErrorGoto(Error);
\r
403 if(!NyLPC_cHttpdConnection_sendResponseBodyF(i_connection,
\r
405 "\"mac00010203\":%u,"
\r
406 "\"mac0405xxxx\":%u,"
\r
418 config->mac_00_01_02_03,
\r
419 config->mac_04_05_xx_xx,
\r
421 config->ipv4_flags,
\r
422 config->ipv4_addr_net,
\r
423 config->ipv4_mask_net,
\r
424 config->ipv4_drut_net,
\r
428 NyLPC_OnErrorGoto(Error);
\r
430 //write current status
\r
431 netif_info=NyLPC_cNet_getInterfaceInfo();
\r
432 currebt_cfg=(const NyLPC_TcNetConfig_t*)(netif_info->current_config);
\r
433 if(!NyLPC_cHttpdConnection_sendResponseBodyF(i_connection,
\r
435 "\"mac00010203\":%u,"
\r
436 "\"mac0405xxxx\":%u,"
\r
448 (currebt_cfg->super.eth_mac.addr[0]<<24)|(currebt_cfg->super.eth_mac.addr[1]<<16)|(currebt_cfg->super.eth_mac.addr[2]<<8)|currebt_cfg->super.eth_mac.addr[3],
\r
449 (currebt_cfg->super.eth_mac.addr[4]<<24)|(currebt_cfg->super.eth_mac.addr[5]<<16),
\r
450 currebt_cfg->hostname,
\r
451 currebt_cfg->tcp_mode,
\r
452 NyLPC_ntohl(currebt_cfg->super.ip_addr.v),
\r
453 NyLPC_ntohl(currebt_cfg->super.netmask.v),
\r
454 NyLPC_ntohl(currebt_cfg->super.dr_addr.v),
\r
455 currebt_cfg->services.flags,
\r
456 currebt_cfg->services.http_port
\r
458 NyLPC_OnErrorGoto(Error);
\r
462 case QVAL_C_UPDATE:
\r
463 //check parameter length
\r
464 if(i_req->content.setup.tmp.param_len!=SIZE_OF_SETUP_PARAM || i_req->content.setup.tmp.host_len<1)
\r
466 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
469 i_req->content.setup.memimg.fast_boot=0xffffffff;
\r
470 // ここの部分は受信時にデータ位置を合わせてあるのでコピー不要。
\r
471 // cfg_image.mac_00_01_02_03=(i_req->content.setup.param_buf[0]);
\r
472 // cfg_image.mac_04_05_xx_xx=(i_req->content.setup.param_buf[1]&0xffff0000);
\r
473 // cfg_image.ipv4_flags =i_req->content.setup.param_buf[2];
\r
474 // cfg_image.ipv4_addr_net =i_req->content.setup.param_buf[3];
\r
475 // cfg_image.ipv4_mask_net =i_req->content.setup.param_buf[4];
\r
476 // cfg_image.ipv4_drut_net =i_req->content.setup.param_buf[5];
\r
477 // cfg_image.srv_flags =i_req->content.setup.param_buf[6];
\r
478 // strcpy(cfg_image.hostname,i_req->content.setup.host_name);
\r
479 i_req->content.setup.memimg.http_port =(NyLPC_TUInt16)(i_req->content.setup.tmp.param_buf[7]>>16);
\r
480 i_req->content.setup.memimg.padding32=0xffff;
\r
481 i_req->content.setup.memimg.padding64=0xffffffff;
\r
483 if(i_req->content.setup.memimg.http_port==0){
\r
484 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
487 NyLPC_cIsr_enterCritical();
\r
489 ret=NyLPC_cMiMicConfiglation_updateConfigulation(&i_req->content.setup.memimg);
\r
491 NyLPC_cIsr_exitCritical();
\r
493 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
\r
495 if(!NyLPC_cHttpdUtils_sendJsonHeader(i_connection)){
\r
496 NyLPC_OnErrorGoto(Error);
\r
498 if(NyLPC_cHttpdConnection_getMethod(i_connection)==NyLPC_THttpMethodType_GET){
\r
499 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection,
\r
500 "{\"application\":\""MOD_VERSION"\",\"result\":%u}",
\r
501 ret?0x00000000:0x80000000);
\r
509 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400);
\r
510 NyLPC_OnErrorGoto(Error);
\r