OSDN Git Service

backup目的。動作しない。
[mimic/MiMicSDK.git] / projects / example / sample.net.simplehttpd / src / sketch.c
1 /**\r
2  * httpdサーバのサンプルです。\r
3  * ROMにある定義済みファイルの入出力と、クロスドメインRESTが確認できます。\r
4  */\r
5 #include "boot/sketch.h"\r
6 #include "NyLPC_uipService.h"\r
7 #include "NyLPC_httpService.h"\r
8 #include "NyLPC_utils.h"\r
9 #include <stdio.h>\r
10 \r
11 #include "../api/NyLPC_cNet.h"\r
12 #include "../api/NyLPC_cHttpd.h"\r
13 \r
14 NyLPC_TcNet_t net;\r
15 struct MyHttpd{\r
16         NyLPC_TcHttpd_t super;\r
17 }httpd;\r
18 void handler(NyLPC_TcHttpdConnection_t* i_inst)\r
19 {\r
20         return;\r
21 }\r
22 void setup(void)\r
23 {\r
24         //uipサービス初期化。いろいろ利用可能に。\r
25         NyLPC_cNet_initialize(&net);\r
26         NyLPC_cHttpd_initialize(&httpd.super,80);\r
27         httpd.super.function._handler=handler;\r
28 }\r
29 \r
30 \r
31 void loop(void)\r
32 {\r
33         NyLPC_TcNetConfig_t c2;\r
34         NyLPC_cNetConfig_initialize(&c2);\r
35         NyLPC_cNet_start(&net,&c2);\r
36         NyLPC_cHttpd_loop(&httpd.super);\r
37         for(;;);\r
38 }\r
39 \r
40 \r
41 #ifdef COMMENT\r
42 \r
43 \r
44 //イーサネット用の初期化情報\r
45 const struct NyLPC_TEthAddr ethaddr=NyLPC_TEthAddr_pack(0x02,0x01,0x02,0x03,0x04,0x05);\r
46 const struct NyLPC_TIPv4Addr ipaddr=NyLPC_TIPv4Addr_pack(192,168,0,39);\r
47 const struct NyLPC_TIPv4Addr netmask=NyLPC_TIPv4Addr_pack(255,255,255,0);\r
48 const struct NyLPC_TIPv4Addr gateway=NyLPC_TIPv4Addr_pack(192,168,0,254);\r
49 \r
50 //TCP処理スレッドの定義\r
51 #define SIZE_OF_RX 256\r
52 #define NUM_OF_TH 7\r
53 struct TProc{\r
54         NyLPC_TcThread_t th;\r
55         NyLPC_TcTcpSocket_t socket;\r
56         char rbuf[SIZE_OF_RX];\r
57 }proc[NUM_OF_TH];\r
58 \r
59 //ROMFSの定義\r
60 extern struct NyLPC_TRomFileData file_cat_jpg;\r
61 extern struct NyLPC_TRomFileData file_index_html;\r
62 NyLPC_TcRomFileSet_t rfs;\r
63 const struct NyLPC_TRomFileData* rfsd[]={\r
64                 &file_index_html,\r
65                 &file_cat_jpg};\r
66 \r
67 //private 関数\r
68 \r
69 static NyLPC_TUInt16 parseReqHeader(NyLPC_TcHttpStream_t* i_st,struct NyLPC_THttpShortRequestHeader* o_reqh);\r
70 static NyLPC_TBool writeError(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh,NyLPC_TUInt16 i_status);\r
71 static NyLPC_TBool writeFile(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh,const struct NyLPC_TRomFileData* i_file);\r
72 static NyLPC_TBool writeJson(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh);\r
73 \r
74 \r
75 //スケッチ\r
76 \r
77 void setup(void)\r
78 {\r
79         int i;\r
80         //uipサービス初期化。いろいろ利用可能に。\r
81         NyLPC_cUipService_initialize();\r
82 //      for(i=0;i<NUM_OF_TH;i++){\r
83 //              NyLPC_cThread_initialize(&(proc[i].th),200,NyLPC_TcThread_PRIORITY_IDLE);\r
84 //              NyLPC_cTcpSocket_initialize(&(proc[i].socket),proc[i].rbuf,SIZE_OF_RX);\r
85 //      }\r
86 //      //ROMのファイルシステムを初期化\r
87 //      NyLPC_cRomFileSet_initialize(&rfs,rfsd,2);\r
88 \r
89 }\r
90 \r
91 //ステータス用。\r
92 static int num_of_reqest=0;\r
93 static int num_of_error=0;\r
94 static int num_of_connect=0;\r
95 static int num_of_tx=0;\r
96 \r
97 //Httpのセッション関数\r
98 static int server(void* p)\r
99 {\r
100         struct TProc* proc=(struct TProc*)p;\r
101         NyLPC_TUInt16 ret;\r
102         const struct NyLPC_TRomFileData* rf;\r
103         NyLPC_TcHttpStream_t st;\r
104         struct NyLPC_THttpShortRequestHeader reqheader;\r
105         if(!NyLPC_cTcpSocket_accept(&(proc->socket),3000)){\r
106                 return -1;\r
107         }\r
108         num_of_connect++;\r
109 \r
110         //TCPのオープン\r
111         if(NyLPC_cHttpStream_initialize(&st,&(proc->socket))){\r
112                 for(;;){\r
113                         ret=parseReqHeader(&st,&reqheader);\r
114                         num_of_reqest++;\r
115                         //コネクションが増えすぎたら持続性接続を停止するために上書き。\r
116                         if(num_of_connect>5){\r
117                                 reqheader.super.connection=NyLPC_THttpMessgeHeader_Connection_CLOSE;\r
118                         }\r
119                         if(ret!=200){\r
120                                 //エラーならエラーレスポンスを生成。持続性接続しない。\r
121                                 writeError(&st,&(reqheader.super),ret);\r
122                                 num_of_error++;\r
123                                 break;\r
124                         }\r
125                         //URLから判定。\r
126                         if(strncmp("/rf.api?",reqheader.url,8)==0){\r
127                                 //ファイル検索\r
128                                 rf=NyLPC_cRomFileSet_getFilaData(&rfs,reqheader.url+8);\r
129                                 if(rf==NULL){\r
130                                         num_of_error++;\r
131                                         if(!writeError(&st,&(reqheader.super),404)){\r
132                                                 break;\r
133                                         }\r
134                                 }else{\r
135                                         if(!writeFile(&st,&(reqheader.super),rf)){\r
136                                                 num_of_error++;\r
137                                                 break;\r
138                                         }\r
139                                 }\r
140                         }else if(strncmp("/status.json",reqheader.url,8)==0){\r
141                                 if(!writeJson(&st,&(reqheader.super))){\r
142                                         break;\r
143                                 }\r
144                                 //httpdの状態を返す。\r
145                         }else{\r
146                                 if(!writeFile(&st,&(reqheader.super),NyLPC_cRomFileSet_getFilaData(&rfs,"index.html"))){\r
147                                         num_of_error++;\r
148                                         break;\r
149                                 }\r
150                         }\r
151 \r
152                 }\r
153                 NyLPC_cHttpStream_finalize(&st);\r
154         }\r
155         //5秒以内に切断\r
156         NyLPC_cTcpSocket_close(&(proc->socket),5000);\r
157         num_of_connect--;\r
158         return 0;\r
159 }\r
160 \r
161 \r
162 void loop(void)\r
163 {\r
164         NyLPC_TcIPv4Config_t config;\r
165         NyLPC_TcTcpListener_t listener;\r
166         int i;\r
167 \r
168 \r
169         NyLPC_cIPv4Config_initialzeForEthernet(&config,&ethaddr,1480);\r
170         NyLPC_cIPv4Config_setDefaultRoute(&config,&gateway);\r
171         NyLPC_cIPv4Config_setIp(&config,&ipaddr,&netmask);\r
172 \r
173 \r
174 //      NyLPC_cTcpListener_initialize(&listener,80);\r
175         NyLPC_cUipService_start(&config);\r
176 /*      for(;;){\r
177                 //ターミネイト状態のタスクを検索\r
178                 for(i=0;i<NUM_OF_TH;i++){\r
179                         if(NyLPC_cThread_isTerminated(&(proc[i].th))){\r
180                                 //リスニング\r
181                                 if(!NyLPC_cTcpListener_listen(&listener,&(proc[i].socket),5000)){\r
182                                         continue;\r
183                                 }\r
184                                 //タスク起動\r
185                                 NyLPC_cThread_start(&(proc[i].th),server,&(proc[i]));\r
186                         }\r
187                 }\r
188         }*/\r
189         for(;;){}\r
190 }\r
191 \r
192 \r
193 \r
194 /**\r
195  * リクエストヘッダのパーサ\r
196  */\r
197 static NyLPC_TUInt16 parseReqHeader(NyLPC_TcHttpStream_t* i_st,struct NyLPC_THttpShortRequestHeader* o_reqh)\r
198 {\r
199         NyLPC_TUInt16 ret=200;\r
200         NyLPC_TcHttpShortRequestHeaderParser_t hp;\r
201         NyLPC_cHttpShortRequestHeaderParser_initialize(&hp);\r
202 \r
203         //ヘッダ解析\r
204         if(!NyLPC_cHttpShortRequestHeaderParser_parse(&hp,i_st,o_reqh)){\r
205                 ret=NyLPC_cHttpBasicHeaderParser_getStatusCode(&hp.super);\r
206         }\r
207         //ヘッダの内容確認\r
208         if(o_reqh->super.type!=NyLPC_THttpHeaderType_REQUEST){\r
209                 ret=400;\r
210         }\r
211         //GETだけネ\r
212         if(o_reqh->super.startline.req.method!=NyLPC_THttpMethodType_GET){\r
213                 ret=405;\r
214         }\r
215         NyLPC_cHttpBasicHeaderParser_finalize(&hp);\r
216         return ret;\r
217 }\r
218 /**\r
219  * エラーレスポンスのライタ。\r
220  * 戻り値はpersistentConnectionが有効かどうか。\r
221  */\r
222 static NyLPC_TBool writeError(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh,NyLPC_TUInt16 i_status)\r
223 {\r
224         static const char* HTML_FORMAT="<html><h1>STATUS %d</h1><hr/>"NyLPC_cHttpdConfig_SERVER"</html>";\r
225         NyLPC_TcHttpHeaderWriter_t hw;\r
226         NyLPC_TcHttpBodyWriter_t bw;\r
227         //ヘッダライタの生成\r
228         if(!NyLPC_cHttpHeaderWriter_initialize(&hw,i_st,i_rqh)){\r
229                 return NyLPC_TBool_FALSE;\r
230         }\r
231         //ヘッダ書込み\r
232         if(!NyLPC_THttpBasicHeader_isPersistent(i_rqh)){\r
233                 NyLPC_cHttpHeaderWriter_setClose(&hw);\r
234         }\r
235         //@bug HTTP/1.1未満のクライアントを考慮していない。\r
236         NyLPC_cHttpHeaderWriter_setChunked(&hw);\r
237         //ヘッダの基本情報出力\r
238         NyLPC_cHttpHeaderWriter_writeHeader(&hw,i_status);\r
239         //拡張メッセージヘッダの出力\r
240         NyLPC_cHttpHeaderWriter_writeMessage(&hw,"Content-type","text/html");\r
241 \r
242         //ヘッダ書込み終わり。(最後だけチェック)\r
243         if(!NyLPC_cHttpHeaderWriter_close(&hw)){\r
244                 NyLPC_cHttpHeaderWriter_finalize(&hw);\r
245                 return NyLPC_TBool_FALSE;\r
246         }\r
247         NyLPC_cHttpHeaderWriter_finalize(&hw);\r
248 \r
249         //Bodyの書込み\r
250         NyLPC_cHttpBodyWriter_initialize(&bw,i_st);\r
251         //チャンク転送設定\r
252         NyLPC_cHttpBodyWriter_setChunked(&bw);\r
253         NyLPC_cHttpBodyWriter_format(&bw,HTML_FORMAT,(NyLPC_TInt32)i_status);\r
254         //エラーチェック\r
255         if(!NyLPC_cHttpBodyWriter_close(&bw)){\r
256                 NyLPC_cHttpBodyWriter_finalize(&hw);\r
257                 return NyLPC_TBool_FALSE;\r
258         }\r
259         NyLPC_cHttpBodyWriter_finalize(&hw);\r
260         return NyLPC_THttpBasicHeader_isPersistent(i_rqh);\r
261 }\r
262 \r
263 /**\r
264  * エラーレスポンスのライタ。\r
265  * 戻り値はpersistentConnectionが有効かどうか。\r
266  */\r
267 static NyLPC_TBool writeJson(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh)\r
268 {\r
269         static const char* JSON_FORMAT="{nr:%d,ne:%d,ac:%d,er:\"%d/%d/%d\",tx:%d}";\r
270         NyLPC_TcHttpHeaderWriter_t hw;\r
271         NyLPC_TcHttpBodyWriter_t bw;\r
272         //ヘッダライタの生成\r
273         if(!NyLPC_cHttpHeaderWriter_initialize(&hw,i_st,i_rqh)){\r
274                 return NyLPC_TBool_FALSE;\r
275         }\r
276         //ヘッダ書込み\r
277         if(!NyLPC_THttpBasicHeader_isPersistent(i_rqh)){\r
278                 NyLPC_cHttpHeaderWriter_setClose(&hw);\r
279         }\r
280         //@bug HTTP/1.1未満のクライアントを考慮していない。\r
281         NyLPC_cHttpHeaderWriter_setChunked(&hw);\r
282         //ヘッダの基本情報出力\r
283         NyLPC_cHttpHeaderWriter_writeHeader(&hw,200);\r
284         //拡張メッセージヘッダの出力\r
285         NyLPC_cHttpHeaderWriter_writeMessage(&hw,"Content-type","application/json");\r
286         NyLPC_cHttpHeaderWriter_writeMessage(&hw,"Access-Control-Allow-Origin","*");\r
287 \r
288         //ヘッダ書込み終わり。(最後だけチェック)\r
289         if(!NyLPC_cHttpHeaderWriter_close(&hw)){\r
290                 NyLPC_cHttpHeaderWriter_finalize(&hw);\r
291                 return NyLPC_TBool_FALSE;\r
292         }\r
293         NyLPC_cHttpHeaderWriter_finalize(&hw);\r
294 \r
295         //Bodyの書込み\r
296         NyLPC_cHttpBodyWriter_initialize(&bw,i_st);\r
297         //チャンク転送設定\r
298         NyLPC_cHttpBodyWriter_setChunked(&bw);\r
299         NyLPC_cHttpBodyWriter_format(&bw,JSON_FORMAT,\r
300                 (NyLPC_TInt32)num_of_reqest,(NyLPC_TInt32)num_of_error,(NyLPC_TInt32)num_of_connect,\r
301                 NyLPC_assert_counter,NyLPC_abort_counter,NyLPC_debug_counter,dbg_getNumofUsedTx());\r
302         //エラーチェック\r
303         if(!NyLPC_cHttpBodyWriter_close(&bw)){\r
304                 NyLPC_cHttpBodyWriter_finalize(&hw);\r
305                 return NyLPC_TBool_FALSE;\r
306         }\r
307         NyLPC_cHttpBodyWriter_finalize(&hw);\r
308         return NyLPC_THttpBasicHeader_isPersistent(i_rqh);\r
309 }\r
310 /**\r
311  * ROMファイルのレスポンスライタ。\r
312  * 戻り値はpersistentConnectionが有効かどうか。\r
313  */\r
314 static NyLPC_TBool writeFile(NyLPC_TcHttpStream_t* i_st,const struct NyLPC_THttpBasicHeader* i_rqh,const struct NyLPC_TRomFileData* i_file)\r
315 {\r
316         NyLPC_TcHttpHeaderWriter_t hw;\r
317         NyLPC_TcHttpBodyWriter_t bw;\r
318         //ヘッダライタの生成\r
319         if(!NyLPC_cHttpHeaderWriter_initialize(&hw,i_st,i_rqh)){\r
320                 return NyLPC_TBool_FALSE;\r
321         }\r
322         //ヘッダ書込み\r
323         if(!NyLPC_THttpBasicHeader_isPersistent(i_rqh)){\r
324                 NyLPC_cHttpHeaderWriter_setClose(&hw);\r
325         }\r
326         NyLPC_cHttpHeaderWriter_setContentLength(&hw,i_file->size);\r
327         //ヘッダの基本情報出力\r
328         NyLPC_cHttpHeaderWriter_writeHeader(&hw,200);\r
329         //拡張メッセージヘッダの出力\r
330         NyLPC_cHttpHeaderWriter_writeMessage(&hw,"Content-type",i_file->content_type);\r
331 \r
332         //ヘッダ書込み終わり。(最後だけチェック)\r
333         if(!NyLPC_cHttpHeaderWriter_close(&hw)){\r
334                 NyLPC_cHttpHeaderWriter_finalize(&hw);\r
335                 return NyLPC_TBool_FALSE;\r
336         }\r
337         NyLPC_cHttpHeaderWriter_finalize(&hw);\r
338 \r
339         //Bodyの書込み\r
340         NyLPC_cHttpBodyWriter_initialize(&bw,i_st);\r
341         NyLPC_cHttpBodyWriter_write(&bw,i_file->data,i_file->size);\r
342         //エラーチェック\r
343         if(!NyLPC_cHttpBodyWriter_close(&bw)){\r
344                 NyLPC_cHttpBodyWriter_finalize(&hw);\r
345                 return NyLPC_TBool_FALSE;\r
346         }\r
347         NyLPC_cHttpBodyWriter_finalize(&hw);\r
348         return NyLPC_THttpBasicHeader_isPersistent(i_rqh);\r
349 }\r
350 #endif\r