source: EcnlProtoTool/trunk/prototool/src/main.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 31.0 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014-2017 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者
7は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再é…
10å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再é…
16å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
17å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
18 * 者
19マニュアルなど)に,上記の著作権表示,この利用条件および下記
20 * の無保証規定を掲載すること.
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再é…
23å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
24 * と.
25 * (a) 再é…
26å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
27マニュアルなど)に,上記の著
28 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
29 * (b) 再é…
30å¸ƒã®å½¢æ…
31‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
32 * 報告すること.
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者
35およびTOPPERSプロジェクトをå…
36è²¬ã™ã‚‹ã“と.
37 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
38 * 由に基づく請求からも,上記著作権者
39およびTOPPERSプロジェクトを
40 * å…
41è²¬ã™ã‚‹ã“と.
42 *
43 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
44お
45 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
46 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
47 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
48 * の責任を負わない.
49 *
50 * @(#) $Id: main.c 270 2017-02-09 04:03:47Z coas-nagasima $
51 */
52
53/*
54 * サンプルプログラム(1)の本体
55 */
56
57#include <kernel.h>
58#include <t_syslog.h>
59#include <t_stdlib.h>
60#include <sil.h>
61#include <stdlib.h>
62#include <string.h>
63#include "syssvc/serial.h"
64#include "syssvc/syslog.h"
65#include "kernel_cfg.h"
66#include "main.h"
67#include "rza1.h"
68#include <mruby.h>
69#include <mruby/compile.h>
70#include <mruby/proc.h>
71#include <mruby/array.h>
72#include <mruby/data.h>
73#include <mruby/class.h>
74#include <mruby/dump.h>
75#include <mruby/string.h>
76#include <tinet_config.h>
77#include <netinet/in.h>
78#include <netinet/in_itron.h>
79#include <tinet_nic_defs.h>
80#include <tinet_cfg.h>
81#include <netinet/in_var.h>
82#include <net/ethernet.h>
83#include <net/if6_var.h>
84#include <net/net.h>
85#include <net/if_var.h>
86#include <netinet/udp_var.h>
87#include <ethernet_api.h>
88#include "../webserver/httpd.h"
89#include "../webserver/httpd-fs.h"
90#include "../webserver/http-strings.h"
91#include "../webserver/base64.h"
92#include "../webserver/sha1.h"
93#include "mruby_arduino.h"
94#include "gpio_api.h"
95#include "arduino.h"
96#include "ff.h"
97
98#ifndef _MSC_VER
99void strcpy_s(char *dst, int size, const char *src);
100void strcat_s(char *dst, int size, const char *src);
101#endif
102
103uint8_t mac_addr[6] = {0x00, 0x30, 0x13, 0x06, 0x62, 0xC0};
104
105SYSTIM main_time;
106struct httpd_state *uploding;
107
108static void netif_link_callback(T_IFNET *ether);
109static void execute_ruby();
110
111/* TCP 送受信ウィンドバッファ */
112uint8_t tcp_swbuf1[TCP_SWBUF_SIZE];
113uint8_t tcp_rwbuf1[TCP_RWBUF_SIZE];
114uint8_t tcp_swbuf2[TCP_SWBUF_SIZE];
115uint8_t tcp_rwbuf2[TCP_RWBUF_SIZE];
116
117#define ISO_nl 0x0a
118#define ISO_space 0x20
119#define ISO_bang 0x21
120#define ISO_percent 0x25
121#define ISO_period 0x2e
122#define ISO_slash 0x2f
123#define ISO_colon 0x3a
124
125ID ecn_api_mailboxid;
126ID WEBSOCKET_MBXID;
127
128struct httpd_state httpd_state[2] = {
129 {MAIN1_TASK, TCP_CEPID1},
130 {MAIN2_TASK, TCP_CEPID2},
131};
132
133/*
134* ネットワーク層の選択
135*/
136
137#ifdef SUPPORT_INET6
138
139#define TCP_ACP_CEP(c,r,d,t) tcp6_acp_cep(c,r,d,t)
140#define IP2STR(s,a) ipv62str(s,a)
141
142#else /* of #ifdef SUPPORT_INET6 */
143
144#ifdef SUPPORT_INET4
145
146#define TCP_ACP_CEP(c,r,d,t) tcp_acp_cep(c,r,d,t)
147#define IP2STR(s,a) ip2str(s,a)
148
149#endif /* of #ifdef SUPPORT_INET4 */
150
151#endif /* of #ifdef SUPPORT_INET6 */
152
153struct httpd_state *get_httpd(ID cepid)
154{
155 for (int i = 0; i < 2; i++) {
156 if (httpd_state[i].cepid != cepid)
157 continue;
158
159 return &httpd_state[i];
160 }
161 return NULL;
162}
163
164struct websocket *websocket_getws(ID wbsid)
165{
166 for (int i = 0; i < 2; i++) {
167 if (httpd_state[i].websocket.wbsid != wbsid)
168 continue;
169
170 return &httpd_state[i].websocket;
171 }
172 return NULL;
173}
174
175void send_file(struct httpd_state *s)
176{
177 char *buf;
178 int len, slen;
179
180 while (s->file.len > 0) {
181 slen = tcp_get_buf(s->cepid, (void **)&buf, TMO_FEVR);
182 if (slen < 0) {
183 syslog(LOG_ERROR, "send_file#tcp_get_buf(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, slen);
184 s->state = STATE_CLOSING;
185 break;
186 }
187 if (slen == 0)
188 return;
189
190 len = s->file.len;
191 if (len > slen)
192 len = slen;
193
194 len = httpd_fs_read(&s->file, buf, len);
195 if (len <= 0) {
196 syslog(LOG_ERROR, "send_file#httpd_fs_read(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, len);
197 break;
198 }
199
200 s->file.len -= len;
201 s->file.pos += len;
202
203 if ((slen = tcp_snd_buf(s->cepid, len)) != E_OK) {
204 syslog(LOG_ERROR, "send_file#tcp_snd_buf(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, slen);
205 s->state = STATE_CLOSING;
206 break;
207 }
208 }
209
210 syslog(LOG_NOTICE, "close: %s.%d %s", s->addr, ((T_IPV4EP *)s->dst)->portno, s->filename);
211 httpd_fs_close(&s->file);
212 s->file.len = 0;
213 s->file.pos = 0;
214
215 s->out.state = OUT_STATE_SEND_END;
216}
217
218void send_data(struct httpd_state *s)
219{
220 char *buf;
221 int len, slen;
222
223 while (s->response_len > 0) {
224 slen = tcp_get_buf(s->cepid, (void **)&buf, TMO_FEVR);
225 if (slen < 0) {
226 syslog(LOG_ERROR, "send_data#tcp_get_buf(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, slen);
227 s->state = STATE_CLOSING;
228 break;
229 }
230 if (slen == 0)
231 return;
232
233 len = s->response_len;
234 if (len > slen)
235 len = slen;
236
237 memcpy(buf, &s->response_body[s->response_pos], len);
238
239 s->response_len -= len;
240 s->response_pos += len;
241
242 if ((slen = tcp_snd_buf(s->cepid, len)) != E_OK) {
243 syslog(LOG_ERROR, "send_data#tcp_snd_buf(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, slen);
244 s->state = STATE_CLOSING;
245 break;
246 }
247 }
248
249 s->response_body = NULL;
250 s->response_len = 0;
251 s->response_pos = 0;
252
253 s->out.state = OUT_STATE_SEND_END;
254}
255
256void send_headers(struct httpd_state *s, const char *statushdr)
257{
258 int len;
259 char *ptr;
260
261 len = strlen(statushdr);
262 tcp_snd_dat(s->cepid, (void *)statushdr, len, TMO_FEVR);
263
264 if ((s->filename[0] == '0') && (s->file.len > 0)) {
265 len = sizeof(http_content_encoding_gzip) - 1;
266 tcp_snd_dat(s->cepid, (void *)http_content_encoding_gzip, len, TMO_FEVR);
267 }
268
269 if (s->file.redirect) {
270 len = sizeof(http_location) - 1;
271 tcp_snd_dat(s->cepid, (void *)http_location, len, TMO_FEVR);
272 if (s->filename[0] == '1') {
273 len = 2;
274 tcp_snd_dat(s->cepid, "/~", len, TMO_FEVR);
275 }
276 len = strlen(s->filename);
277 tcp_snd_dat(s->cepid, s->filename, len, TMO_FEVR);
278 if (s->query != NULL) {
279 tcp_snd_dat(s->cepid, "?", 1, TMO_FEVR);
280 len = strlen(s->query);
281 tcp_snd_dat(s->cepid, s->query, len, TMO_FEVR);
282 }
283 len = 2;
284 tcp_snd_dat(s->cepid, "\r", len, TMO_FEVR);
285 }
286
287 ptr = strrchr(s->filename, ISO_period);
288 if (ptr == NULL) {
289 len = sizeof(http_content_type_binary) - 1;
290 tcp_snd_dat(s->cepid, (void *)http_content_type_binary, len, TMO_FEVR);
291 }
292 else if (strncmp(http_html, ptr, sizeof(http_html) - 1) == 0 ||
293 strncmp(http_htm, ptr, sizeof(http_htm) - 1) == 0) {
294 len = sizeof(http_content_type_html) - 1;
295 tcp_snd_dat(s->cepid, (void *)http_content_type_html, len, TMO_FEVR);
296 }
297 else if (strncmp(http_css, ptr, sizeof(http_css) - 1) == 0) {
298 len = sizeof(http_content_type_css) - 1;
299 tcp_snd_dat(s->cepid, (void *)http_content_type_css, len, TMO_FEVR);
300 }
301 else if (strncmp(http_js, ptr, sizeof(http_js) - 1) == 0) {
302 len = sizeof(http_content_type_js) - 1;
303 tcp_snd_dat(s->cepid, (void *)http_content_type_js, len, TMO_FEVR);
304 }
305 else if (strncmp(http_json, ptr, sizeof(http_json) - 1) == 0) {
306 len = sizeof(http_content_type_json) - 1;
307 tcp_snd_dat(s->cepid, (void *)http_content_type_json, len, TMO_FEVR);
308 }
309 else if (strncmp(http_png, ptr, sizeof(http_png) - 1) == 0) {
310 len = sizeof(http_content_type_png) - 1;
311 tcp_snd_dat(s->cepid, (void *)http_content_type_png, len, TMO_FEVR);
312 }
313 else if (strncmp(http_gif, ptr, sizeof(http_gif) - 1) == 0) {
314 len = sizeof(http_content_type_gif) - 1;
315 tcp_snd_dat(s->cepid, (void *)http_content_type_gif, len, TMO_FEVR);
316 }
317 else if (strncmp(http_jpg, ptr, sizeof(http_jpg) - 1) == 0) {
318 len = sizeof(http_content_type_jpg) - 1;
319 tcp_snd_dat(s->cepid, (void *)http_content_type_jpg, len, TMO_FEVR);
320 }
321 else if (strncmp(http_svg, ptr, sizeof(http_svg) - 1) == 0) {
322 len = sizeof(http_content_type_svg) - 1;
323 tcp_snd_dat(s->cepid, (void *)http_content_type_svg, len, TMO_FEVR);
324 }
325 else if (strncmp(http_text, ptr, sizeof(http_text) - 1) == 0) {
326 len = sizeof(http_content_type_text) - 1;
327 tcp_snd_dat(s->cepid, (void *)http_content_type_text, len, TMO_FEVR);
328 }
329 else if (strncmp(http_eot, ptr, sizeof(http_eot) - 1) == 0) {
330 len = sizeof(http_content_type_eot) - 1;
331 tcp_snd_dat(s->cepid, (void *)http_content_type_eot, len, TMO_FEVR);
332 }
333 else if (strncmp(http_ttf, ptr, sizeof(http_ttf) - 1) == 0) {
334 len = sizeof(http_content_type_ttf) - 1;
335 tcp_snd_dat(s->cepid, (void *)http_content_type_ttf, len, TMO_FEVR);
336 }
337 else if (strncmp(http_woff, ptr, sizeof(http_woff) - 1) == 0) {
338 len = sizeof(http_content_type_woff) - 1;
339 tcp_snd_dat(s->cepid, (void *)http_content_type_woff, len, TMO_FEVR);
340 }
341 else if (strncmp(http_woff2, ptr, sizeof(http_woff2) - 1) == 0) {
342 len = sizeof(http_content_type_woff2) - 1;
343 tcp_snd_dat(s->cepid, (void *)http_content_type_woff2, len, TMO_FEVR);
344 }
345 else if (strncmp(http_ico, ptr, sizeof(http_ico) - 1) == 0) {
346 len = sizeof(http_content_type_ico) - 1;
347 tcp_snd_dat(s->cepid, (void *)http_content_type_ico, len, TMO_FEVR);
348 }
349 else {
350 len = sizeof(http_content_type_plain) - 1;
351 tcp_snd_dat(s->cepid, (void *)http_content_type_plain, len, TMO_FEVR);
352 }
353
354 if (s->file.len > 0) {
355 len = sizeof(http_content_length) - 1;
356 tcp_snd_dat(s->cepid, (void *)http_content_length, len, TMO_FEVR);
357 sprintf(s->temp, "%d\r\n", s->file.len);
358 tcp_snd_dat(s->cepid, (void *)s->temp, strlen(s->temp), TMO_FEVR);
359 }
360
361 if (s->message.should_keep_alive && s->reset == 0) {
362 len = sizeof(http_connection_keep_alive) - 1;
363 tcp_snd_dat(s->cepid, (void *)http_connection_keep_alive, len, TMO_FEVR);
364 }
365 else {
366 len = sizeof(http_connection_close) - 1;
367 tcp_snd_dat(s->cepid, (void *)http_connection_close, len, TMO_FEVR);
368 }
369
370 tcp_snd_dat(s->cepid, (void *)http_crnl, 2, TMO_FEVR);
371
372 if (s->filename != NULL) {
373 s->out.state = OUT_STATE_SEND_FILE;
374 }
375 else {
376 s->out.state = OUT_STATE_SEND_DATA;
377 }
378}
379
380void handle_output(struct httpd_state *s)
381{
382 s->out.wait = false;
383
384 switch (s->out.state) {
385 case OUT_STATE_WAIT_REQUEST:
386 s->out.wait = true;
387 break;
388 case OUT_STATE_OPEN_GET_FILE:
389 syslog(LOG_NOTICE, "open: %s.%d %s", s->addr, ((T_IPV4EP *)s->dst)->portno, s->filename);
390 if (!httpd_fs_open(s->filename, sizeof(s->message.request_url), &s->file)) {
391 s->filename = NULL;
392 s->response_body = http_content_404;
393 s->response_pos = 0;
394 s->response_len = sizeof(http_content_403) - 1;
395 s->out.statushdr = http_header_404;
396 }
397 else {
398 s->out.statushdr = s->file.redirect ? http_header_301 : http_header_200;
399 }
400 s->out.state = OUT_STATE_SEND_HEADER;
401 break;
402 case OUT_STATE_WAIT_POST_BODY:
403 s->out.wait = true;
404 break;
405 case OUT_STATE_BODY_RECEIVED:
406 s->out.statushdr = http_header_200;
407 s->out.state = OUT_STATE_SEND_HEADER;
408 break;
409 case OUT_STATE_SEND_HEADER:
410 send_headers(s, s->out.statushdr);
411 break;
412 case OUT_STATE_SEND_FILE:
413 send_file(s);
414 break;
415 case OUT_STATE_SEND_DATA:
416 send_data(s);
417 break;
418 case OUT_STATE_SEND_END:
419 s->out.wait = true;
420 if (s->message.should_keep_alive && s->reset == 0) {
421 s->out.state = OUT_STATE_WAIT_REQUEST;
422 }
423 else {
424 s->state = STATE_CLOSING;
425 }
426 break;
427 }
428}
429
430void send_ws_headers(struct httpd_state *s, const char *statushdr)
431{
432 int len;
433
434 len = strlen(statushdr);
435 tcp_snd_dat(s->cepid, (void *)statushdr, len, TMO_FEVR);
436
437 len = sizeof(http_upgrade) - 1;
438 tcp_snd_dat(s->cepid, (void *)http_upgrade, len, TMO_FEVR);
439 len = strlen(s->message.upgrade);
440 tcp_snd_dat(s->cepid, s->message.upgrade, len, TMO_FEVR);
441 len = sizeof(http_crnl) - 1;
442 tcp_snd_dat(s->cepid, (void *)http_crnl, len, TMO_FEVR);
443
444 len = sizeof(http_connection) - 1;
445 tcp_snd_dat(s->cepid, (void *)http_connection, len, TMO_FEVR);
446 len = strlen(s->message.connection);
447 tcp_snd_dat(s->cepid, s->message.connection, len, TMO_FEVR);
448 len = sizeof(http_crnl) - 1;
449 tcp_snd_dat(s->cepid, (void *)http_crnl, len, TMO_FEVR);
450
451 len = sizeof(http_sec_websocket_accept) - 1;
452 tcp_snd_dat(s->cepid, (void *)http_sec_websocket_accept, len, TMO_FEVR);
453 len = strlen(s->message.response_key);
454 tcp_snd_dat(s->cepid, s->message.response_key, len, TMO_FEVR);
455 len = sizeof(http_crnl) - 1;
456 tcp_snd_dat(s->cepid, (void *)http_crnl, len, TMO_FEVR);
457
458 len = sizeof(http_sec_websocket_protocol) - 1;
459 tcp_snd_dat(s->cepid, (void *)http_sec_websocket_protocol, len, TMO_FEVR);
460 len = strlen(s->message.sec_websocket_protocol);
461 tcp_snd_dat(s->cepid, s->message.sec_websocket_protocol, len, TMO_FEVR);
462 len = sizeof(http_crnl) - 1;
463 tcp_snd_dat(s->cepid, (void *)http_crnl, len, TMO_FEVR);
464
465 len = sizeof(http_crnl) - 1;
466 tcp_snd_dat(s->cepid, (void *)http_crnl, len, TMO_FEVR);
467}
468
469void send_ws_data(struct httpd_state *s)
470{
471 char *buf;
472 int slen;
473
474 slen = tcp_get_buf(s->cepid, (void **)&buf, TMO_FEVR);
475 if (slen < 0) {
476 syslog(LOG_ERROR, "send_ws_data#tcp_get_buf(%s.%d) => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, slen);
477 return;
478 }
479
480 websocket_output(&s->websocket, buf, slen);
481}
482
483void handle_ws_output(struct httpd_state *s)
484{
485 char shaHash[20];
486 SHA_CTX sha1;
487 int len;
488
489 strlncat(s->message.response_key, sizeof(s->message.response_key),
490 s->message.sec_websocket_key, sizeof(s->message.sec_websocket_key));
491 len = strlncat(s->message.response_key, sizeof(s->message.response_key),
492 http_websocket_guid, sizeof(http_websocket_guid));
493 memset(shaHash, 0, sizeof(shaHash));
494 SHA1_Init(&sha1);
495 SHA1_Update(&sha1, (sha1_byte *)s->message.response_key, len);
496 SHA1_Final((sha1_byte *)shaHash, &sha1);
497 base64_encode((unsigned char *)s->message.response_key,
498 sizeof(s->message.response_key), (unsigned char *)shaHash, sizeof(shaHash));
499
500 send_ws_headers(s, http_header_101);
501
502 s->message.response_key[0] = '\0';
503
504 do {
505 while (!websocket_newdata(&s->websocket))
506 slp_tsk();
507
508 send_ws_data(s);
509 } while ((s->state == STATE_CONNECTED) && (!s->close_req));
510 s->state = STATE_DISCONNECTED;
511 websocket_destroy(&s->websocket);
512 s->close_req = 0;
513
514 s->state = STATE_CLOSING;
515}
516
517void handle_input(struct httpd_state *s)
518{
519 size_t done;
520 int len;
521
522 s->in.wait = false;
523
524 switch (s->in.state) {
525 case IN_STATE_START:
526 http_parser_init(&s->parser, HTTP_REQUEST);
527 s->in.state = IN_STATE_REQUEST;
528 break;
529 case IN_STATE_REQUEST:
530 case IN_STATE_RESPONSE:
531 case IN_STATE_UPLOAD:
532 if ((len = tcp_rcv_buf(s->cepid, (void **)&s->in.data, TMO_POL)) <= 0) {
533 if ((len == E_TMOUT) || (len == 0)) {
534 // 3秒は待
535つ
536 if (main_time - s->in.timer < 30000000) {
537 s->in.wait = true;
538 break;
539 }
540 }
541 syslog(LOG_ERROR, "handle_input#tcp_rcv_buf#%d(%s.%d) => %d", s->in.state, s->addr, ((T_IPV4EP *)s->dst)->portno, len);
542 uploding = NULL;
543 s->state = STATE_CLOSING;
544 return;
545 }
546 done = http_parser_execute(&s->parser, &websvr_settings, s->in.data, len);
547 tcp_rel_buf(s->cepid, done);
548 if (s->parser.http_errno != HPE_OK) {
549 syslog(LOG_ERROR, "http_parser error %s.%d => %d", s->addr, ((T_IPV4EP *)s->dst)->portno, s->parser.http_errno);
550 uploding = NULL;
551 s->state = STATE_CLOSING;
552 return;
553 }
554
555 s->parse_pos = done;
556 s->parse_len = len - done;
557 break;
558 case IN_STATE_UPLOAD_WAIT:
559 if (uploding != NULL) {
560 s->in.wait = true;
561 }
562 else {
563 uploding = s;
564 s->in.state = IN_STATE_UPLOAD;
565 }
566 break;
567 case IN_STATE_WEBSOCKET:
568 if (s->parse_len <= 0) {
569 if ((len = tcp_rcv_buf(s->cepid, (void **)&s->in.data, TMO_POL)) <= 0) {
570 if ((len == E_TMOUT) || (len == 0)) {
571 s->in.wait = true;
572 break;
573 }
574 syslog(LOG_ERROR, "handle_input#tcp_rcv_buf#%d(%s.%d) => %d", s->in.state, s->addr, ((T_IPV4EP *)s->dst)->portno, len);
575 s->state = STATE_CLOSING;
576 break;
577 }
578
579 s->parse_pos = 0;
580 s->parse_len = len;
581 }
582 else
583 len = s->parse_len;
584 done = websocket_input(&s->websocket, (void *)s->in.data, s->parse_len);
585 tcp_rel_buf(s->cepid, done);
586 if ((done != 0) || (s->websocket.rstate.opecode == connection_close)) {
587 s->close_req = 1;
588 s->state = STATE_CLOSING;
589 break;
590 }
591 s->parse_pos = done;
592 s->parse_len -= done;
593 break;
594 case IN_STATE_END:
595 s->in.wait = true;
596 break;
597 default:
598 s->state = STATE_CLOSING;
599 break;
600 }
601}
602
603/*
604 * ノンブロッキングコールのコールバック関数
605 */
606ER
607callback_nblk_tcp(ID cepid, FN fncd, void *p_parblk)
608{
609 struct httpd_state *s = get_httpd(cepid);
610
611 if (s == NULL)
612 syslog(LOG_NOTICE, "callback_nblk_tcp(%d, %d)", fncd, cepid);
613 else
614 syslog(LOG_NOTICE, "callback_nblk_tcp(%d, %s.%d)", fncd, s->addr, ((T_IPV4EP *)s->dst)->portno);
615
616 return E_PAR;
617}
618
619/*
620 * メインタスク
621 */
622void main_task(intptr_t exinf)
623{
624 ER ret, ret2;
625 struct httpd_state *s = &httpd_state[exinf];
626
627 if (exinf == 0) {
628 gpio_t led_blue, led_green, led_red, sw;
629 gpio_init_out(&led_blue, LED_BLUE);
630 gpio_init_out(&led_green, LED_GREEN);
631 gpio_init_out(&led_red, LED_RED);
632 gpio_init_in(&sw, USER_BUTTON0);
633
634 bool_t exec = gpio_read(&sw) == 1;
635
636 gpio_write(&led_blue, 1);
637 gpio_write(&led_green, exec ? 1 : 0);
638 gpio_write(&led_red, 0);
639
640 /* 初期化 */
641 if (mruby_arduino_init() == 0) {
642 gpio_write(&led_blue, 0);
643 }
644 else {
645 gpio_write(&led_blue, 0);
646 gpio_write(&led_red, 1);
647 }
648
649 gpio_write(&led_green, 0);
650
651 /* TINETが起動するまで待
652つ */
653 ether_set_link_callback(netif_link_callback);
654
655 act_tsk(MAIN2_TASK);
656
657 if (exec) {
658 strcpy_s(RubyFilename, sizeof(RubyFilename), "1:/upload/main.mrb");
659
660 execute_ruby();
661 }
662 }
663
664 for (;;) {
665 ret2 = get_tim(&main_time);
666 if (ret2 != E_OK) {
667 syslog(LOG_ERROR, "get_tim");
668 return;
669 }
670
671 switch (s->state) {
672 case STATE_DISCONNECTED:
673 memset(&s->dst, 0, sizeof(s->dst));
674 if ((ret = TCP_ACP_CEP(s->cepid, TCP_REPID, (T_IPV4EP *)s->dst, TMO_FEVR)) != E_OK) {
675 syslog(LOG_ERROR, "tcp_acp_cep(%d) => %d", s->cepid, ret);
676 tslp_tsk(100000); // TODO
677 s->state = STATE_CLOSING;
678 break;
679 }
680 IP2STR(s->addr, &((T_IPV4EP *)s->dst)->ipaddr);
681 syslog(LOG_NOTICE, "connected: %s.%d", s->addr, ((T_IPV4EP *)s->dst)->portno);
682 memset(&s->in, 0, sizeof(s->in));
683 memset(&s->out, 0, sizeof(s->out));
684 s->in.timer = main_time;
685 s->state = STATE_CONNECTED;
686 break;
687 case STATE_CONNECTED:
688 handle_input(s);
689 handle_output(s);
690 break;
691 case STATE_WEBSOCKET:
692 handle_input(s);
693 handle_ws_output(s);
694 break;
695 case STATE_CLOSING:
696 syslog(LOG_NOTICE, "close: %s.%d", s->addr, ((T_IPV4EP *)s->dst)->portno);
697 tcp_sht_cep(s->cepid);
698 tcp_cls_cep(s->cepid, TMO_FEVR);
699
700 if (s->reset) {
701 s->reset = 0;
702 s->state = STATE_RESET;
703 }
704 else{
705 s->state = STATE_DISCONNECTED;
706 }
707 break;
708 case STATE_RESET:
709 execute_ruby();
710 s->state = STATE_DISCONNECTED;
711 break;
712 }
713
714 if (s->in.wait && s->out.wait) {
715 tslp_tsk(100000);
716 }
717 }
718}
719
720struct udp_msg {
721 T_IPV4EP dst;
722 int len;
723 uint8_t buffer[ETHER_MAX_LEN];
724};
725
726SYSTIM mruby_time;
727struct RClass *_module_target_board;
728
729extern const uint8_t main_rb_code[];
730uint8_t RubyCode[16 * 1024];
731
732/* MACアドレスの設定時に呼ばれる */
733void mbed_mac_address(char *mac)
734{
735 memcpy(mac, mac_addr, 6);
736}
737
738/*
739 * mruby実行タスク
740 */
741void mruby_task(intptr_t exinf)
742{
743 ER ret;
744 struct RProc* n;
745 struct mrb_irep *irep;
746 mrb_state *mrb;
747
748 syslog(LOG_NOTICE, "mruby_task");
749
750 /* mrubyの初期化 */
751 mrb = mrb_open();
752 if (mrb == NULL)
753 abort();
754
755 ret = get_tim(&mruby_time);
756 if (ret != E_OK) {
757 syslog(LOG_ERROR, "get_tim => %d", ret);
758 return;
759 }
760
761 irep = mrb_read_irep(mrb, RubyCode);
762 n = mrb_proc_new(mrb, irep);
763 mrb_run(mrb, n, mrb_nil_value());
764
765 mrb_close(mrb);
766}
767
768static void execute_ruby()
769{
770 FIL fd;
771 FRESULT res;
772 ER ret;
773
774 syslog(LOG_NOTICE, "execute_ruby");
775
776 ret = ter_tsk(MRUBY_TASK);
777 if ((ret != E_OK) && (ret != E_OBJ)) {
778 syslog(LOG_ERROR, "ter_tsk => %d", ret);
779 }
780
781 tslp_tsk(100000);
782
783 reset_heap();
784
785 strcpy_s(ExeFilename, sizeof(ExeFilename), RubyFilename);
786 RubyFilename[0] = '\0';
787 ExeFilename[sizeof(ExeFilename) - 1] = '\0';
788
789 if (ExeFilename[0] == '\0') {
790 return;
791 }
792
793 syslog(LOG_NOTICE, "%s", ExeFilename);
794
795 wai_sem(SEM_FILESYSTEM);
796
797 if ((res = f_open(&fd, ExeFilename, FA_OPEN_EXISTING | FA_READ)) == FR_OK) {
798 if (fd.fsize < sizeof(RubyCode)) {
799 int len = fd.fsize;
800 for (int pos = 0; pos < fd.fsize; pos += len) {
801 if (len > 1024)
802 len = 1024;
803
804 UINT rlen;
805 if ((res = f_read(&fd, &RubyCode[pos], len, &rlen)) != FR_OK)
806 break;
807
808 // 他に使う人のために解放
809 sig_sem(SEM_FILESYSTEM);
810 wai_sem(SEM_FILESYSTEM);
811 }
812 }
813 f_close(&fd);
814 }
815
816 sig_sem(SEM_FILESYSTEM);
817
818 if (res == FR_OK) {
819 ret = act_tsk(MRUBY_TASK);
820 if (ret != E_OK) {
821 syslog(LOG_ERROR, "act_tsk => %d", ret);
822 }
823 }
824}
825
826ER callback_nblk_udp(ID cepid, FN fncd, void *p_parblk)
827{
828 static struct udp_msg msg_inst[2];
829 static int msg_no = 0;
830 struct udp_msg *msg = &msg_inst[msg_no];
831 ER error = E_OK;
832
833 switch (fncd) {
834 case TFN_UDP_CRE_CEP:
835 case TFN_UDP_RCV_DAT:
836 /* ECN_CAP_PUT("[UDP ECHO SRV] callback_nblk_udp() recv: %u", *(int *)p_parblk); */
837 memset(msg, 0, sizeof(struct udp_msg));
838 if ((msg->len = udp_rcv_dat(cepid, &msg->dst, msg->buffer, sizeof(msg->buffer), 0)) < 0) {
839 syslog(LOG_WARNING, "[UDP ECHO SRV] recv, error: %s", itron_strerror(msg->len));
840 return msg->len;
841 }
842 msg_no = (msg_no + 1) % 2;
843 return snd_dtq(MRUBY_DATAQUEUE, (intptr_t)msg);
844
845 case TFN_UDP_SND_DAT:
846 break;
847 default:
848 syslog(LOG_WARNING, "[UDP ECHO SRV] fncd:0x%04X(%s)", -fncd,
849 (fncd == TFN_UDP_CRE_CEP ? "TFN_UDP_CRE_CEP" :
850 (fncd == TFN_UDP_RCV_DAT ? "TFN_UDP_RCV_DAT" :
851 (fncd == TFN_UDP_SND_DAT ? "TFN_UDP_SND_DAT" : "undef"))));
852
853 error = E_PAR;
854 break;
855 }
856 return error;
857}
858
859static void netif_link_callback(T_IFNET *ether)
860{
861 static struct udp_msg msg_inst[2];
862 static int msg_no = 0;
863 struct udp_msg *msg = &msg_inst[msg_no];
864 T_RTSK rtsk;
865 ER ret;
866
867 ret = ref_tsk(MRUBY_TASK, &rtsk);
868 if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT))
869 return;
870
871 memset(msg, 0, sizeof(struct udp_msg));
872
873 msg->len = 1;
874 msg->buffer[0] = ether->flags;
875
876 msg_no = (msg_no + 1) % 2;
877 snd_dtq(MRUBY_DATAQUEUE, (intptr_t)msg);
878}
879
880/*
881 * アプリケーションタスクの登録
882 */
883static mrb_value mrb_target_board_wait_msg(mrb_state *mrb, mrb_value self)
884{
885 TMO timer;
886 SYSTIM now;
887 ER ret, ret2;
888 struct udp_msg *msg;
889 mrb_value arv[3];
890 static int first = 1;
891
892 mrb_get_args(mrb, "i", &timer);
893 if (timer != TMO_FEVR)
894 timer *= 1000;
895
896 if (first) {
897 first = 0;
898 syslog(LOG_NOTICE, "wait_msg");
899 }
900
901 /* メッセージ待
902ち */
903 ret = trcv_dtq(MRUBY_DATAQUEUE, (intptr_t *)&msg, timer);
904 if ((ret != E_OK) && (ret != E_TMOUT)) {
905 syslog(LOG_ERROR, "trcv_dtq => %d", ret);
906 return mrb_nil_value();
907 }
908
909 ret2 = get_tim(&now);
910 if (ret2 != E_OK) {
911 syslog(LOG_ERROR, "get_tim => %d", ret);
912 return mrb_nil_value();
913 }
914
915 arv[0] = mrb_fixnum_value((now - mruby_time) / 1000);
916 mruby_time = now;
917
918 /* タイムアウトの場合 */
919 if (ret == E_TMOUT) {
920 return mrb_ary_new_from_values(mrb, 1, arv);
921 }
922
923 /* 内
924部イベントの場合 */
925 if (msg->dst.ipaddr == 0) {
926 /* Ethernet Link up */
927 if (msg->buffer[0] & IF_FLAG_LINK_UP) {
928 arv[1] = mrb_fixnum_value(1);
929 }
930 /* EP Link up */
931 else if (msg->buffer[0] & IF_FLAG_UP) {
932 arv[1] = mrb_fixnum_value(2);
933 }
934 else {
935 arv[1] = mrb_fixnum_value(0);
936 }
937
938 return mrb_ary_new_from_values(mrb, 2, arv);
939 }
940 /* Echonet電文受信の場合 */
941 else {
942 /* 通信端点 */
943 arv[1] = mrb_str_new(mrb, (char *)&msg->dst, sizeof(msg->dst));
944
945 /* 受信データ */
946 arv[2] = mrb_str_new(mrb, (char *)msg->buffer, msg->len);
947
948 return mrb_ary_new_from_values(mrb, 3, arv);
949 }
950}
951
952/*
953 * アプリケーションタスクの登録
954 */
955static mrb_value mrb_target_board_restart(mrb_state *mrb, mrb_value self)
956{
957 /* DHCP開始 */
958
959 return self;
960}
961
962/*
963 * 通信レイヤーへの送信
964 */
965static mrb_value mrb_target_board_snd_msg(mrb_state *mrb, mrb_value self)
966{
967 mrb_value rep;
968 mrb_value rdat;
969 T_IPV4EP *ep;
970 ER_UINT ret;
971
972 mrb_get_args(mrb, "SS", &rep, &rdat);
973
974 if (RSTRING_LEN(rep) != sizeof(T_IPV4EP)) {
975 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
976 return mrb_nil_value();
977 }
978
979 ep = (T_IPV4EP *)RSTRING_PTR(rep);
980
981 ret = udp_snd_dat(MRUBY_ECNL_UDP_CEPID, ep, RSTRING_PTR(rdat), RSTRING_LEN(rdat), TMO_FEVR);
982 if (ret < 0) {
983 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
984 return mrb_nil_value();
985 }
986
987 return mrb_nil_value();
988}
989
990/*
991 * ローカルアドレスか確認
992 */
993static mrb_value mrb_target_board_is_local_addr(mrb_state *mrb, mrb_value self)
994{
995 mrb_value rep;
996 T_IPV4EP *ep;
997
998 mrb_get_args(mrb, "S", &rep);
999
1000 if (RSTRING_LEN(rep) < sizeof(T_IPV4EP)) {
1001 mrb_raise(mrb, E_RUNTIME_ERROR, "is_local_addr");
1002 return mrb_nil_value();
1003 }
1004
1005 ep = (T_IPV4EP *)RSTRING_PTR(rep);
1006
1007 return (ep->ipaddr == MAKE_IPV4_ADDR(127, 0, 0, 1)) ? mrb_true_value() : mrb_false_value();
1008}
1009
1010/*
1011 * マルチキャストアドレスか確認
1012 */
1013static mrb_value mrb_target_board_is_multicast_addr(mrb_state *mrb, mrb_value self)
1014{
1015 mrb_value rep;
1016 T_IPV4EP *ep;
1017
1018 mrb_get_args(mrb, "S", &rep);
1019
1020 if (RSTRING_LEN(rep) < sizeof(T_IPV4EP)) {
1021 mrb_raise(mrb, E_RUNTIME_ERROR, "is_multicast_addr");
1022 return mrb_nil_value();
1023 }
1024
1025 ep = (T_IPV4EP *)RSTRING_PTR(rep);
1026
1027 return (ep->ipaddr == MAKE_IPV4_ADDR(224, 0, 23, 0)) ? mrb_true_value() : mrb_false_value();
1028}
1029
1030/*
1031 * 同一アドレスか確認
1032 */
1033static mrb_value mrb_target_board_equals_addr(mrb_state *mrb, mrb_value self)
1034{
1035 mrb_value rep1, rep2;
1036 T_IPV4EP *ep1, *ep2;
1037
1038 mrb_get_args(mrb, "SS", &rep1, &rep2);
1039
1040 if ((RSTRING_LEN(rep1) != sizeof(T_IPV4EP)) || (RSTRING_LEN(rep2) != sizeof(T_IPV4EP))) {
1041 mrb_raise(mrb, E_RUNTIME_ERROR, "equals_addr");
1042 return mrb_nil_value();
1043 }
1044
1045 ep1 = (T_IPV4EP *)RSTRING_PTR(rep1);
1046 ep2 = (T_IPV4EP *)RSTRING_PTR(rep2);
1047
1048 return (ep1->ipaddr == ep2->ipaddr) ? mrb_true_value() : mrb_false_value();
1049}
1050
1051/*
1052 * ローカルアドレスの取得
1053 */
1054static mrb_value mrb_target_board_get_local_addr(mrb_state *mrb, mrb_value self)
1055{
1056 T_IPV4EP ep;
1057 mrb_value rep;
1058
1059 ep.ipaddr = MAKE_IPV4_ADDR(127, 0, 0, 1);
1060 ep.portno = 3610;
1061
1062 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
1063
1064 return rep;
1065}
1066
1067/*
1068 * マルチキャストアドレスの取得
1069 */
1070static mrb_value mrb_target_board_get_multicast_addr(mrb_state *mrb, mrb_value self)
1071{
1072 T_IPV4EP ep;
1073 mrb_value rep;
1074
1075 ep.ipaddr = MAKE_IPV4_ADDR(224, 0, 23, 0);
1076 ep.portno = 3610;
1077
1078 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
1079
1080 return rep;
1081}
1082
1083void mrb_mruby_others_gem_init(mrb_state* mrb)
1084{
1085 _module_target_board = mrb_define_module(mrb, "TargetBoard");
1086
1087 // mbed Pin Names
1088 mrb_define_const(mrb, _module_target_board, "LED1", mrb_fixnum_value(LED1));
1089 mrb_define_const(mrb, _module_target_board, "LED2", mrb_fixnum_value(LED2));
1090 mrb_define_const(mrb, _module_target_board, "LED3", mrb_fixnum_value(LED3));
1091 mrb_define_const(mrb, _module_target_board, "LED4", mrb_fixnum_value(LED4));
1092
1093 mrb_define_const(mrb, _module_target_board, "LED_RED", mrb_fixnum_value(LED_RED));
1094 mrb_define_const(mrb, _module_target_board, "LED_GREEN", mrb_fixnum_value(LED_GREEN));
1095 mrb_define_const(mrb, _module_target_board, "LED_BLUE", mrb_fixnum_value(LED_BLUE));
1096 mrb_define_const(mrb, _module_target_board, "LED_USER", mrb_fixnum_value(LED_USER));
1097
1098 mrb_define_const(mrb, _module_target_board, "USBTX", mrb_fixnum_value(USBTX));
1099 mrb_define_const(mrb, _module_target_board, "USBRX", mrb_fixnum_value(USBRX));
1100
1101 // Arduiono Pin Names
1102 mrb_define_const(mrb, _module_target_board, "D0", mrb_fixnum_value(D0));
1103 mrb_define_const(mrb, _module_target_board, "D1", mrb_fixnum_value(D1));
1104 mrb_define_const(mrb, _module_target_board, "D2", mrb_fixnum_value(D2));
1105 mrb_define_const(mrb, _module_target_board, "D3", mrb_fixnum_value(D3));
1106 mrb_define_const(mrb, _module_target_board, "D4", mrb_fixnum_value(D4));
1107 mrb_define_const(mrb, _module_target_board, "D5", mrb_fixnum_value(D5));
1108 mrb_define_const(mrb, _module_target_board, "D6", mrb_fixnum_value(D6));
1109 mrb_define_const(mrb, _module_target_board, "D7", mrb_fixnum_value(D7));
1110 mrb_define_const(mrb, _module_target_board, "D8", mrb_fixnum_value(D8));
1111 mrb_define_const(mrb, _module_target_board, "D9", mrb_fixnum_value(D9));
1112 mrb_define_const(mrb, _module_target_board, "D10", mrb_fixnum_value(D10));
1113 mrb_define_const(mrb, _module_target_board, "D11", mrb_fixnum_value(D11));
1114 mrb_define_const(mrb, _module_target_board, "D12", mrb_fixnum_value(D12));
1115 mrb_define_const(mrb, _module_target_board, "D13", mrb_fixnum_value(D13));
1116 mrb_define_const(mrb, _module_target_board, "D14", mrb_fixnum_value(D14));
1117 mrb_define_const(mrb, _module_target_board, "D15", mrb_fixnum_value(D15));
1118
1119 mrb_define_const(mrb, _module_target_board, "A0", mrb_fixnum_value(A0));
1120 mrb_define_const(mrb, _module_target_board, "A1", mrb_fixnum_value(A1));
1121 mrb_define_const(mrb, _module_target_board, "A2", mrb_fixnum_value(A2));
1122 mrb_define_const(mrb, _module_target_board, "A3", mrb_fixnum_value(A3));
1123 mrb_define_const(mrb, _module_target_board, "A4", mrb_fixnum_value(A4));
1124 mrb_define_const(mrb, _module_target_board, "A5", mrb_fixnum_value(A5));
1125
1126 mrb_define_const(mrb, _module_target_board, "I2C_SCL", mrb_fixnum_value(I2C_SCL));
1127 mrb_define_const(mrb, _module_target_board, "I2C_SDA", mrb_fixnum_value(I2C_SDA));
1128
1129 mrb_define_const(mrb, _module_target_board, "USER_BUTTON0", mrb_fixnum_value(USER_BUTTON0));
1130
1131 // Not connected
1132 mrb_define_const(mrb, _module_target_board, "NC", mrb_fixnum_value(NC));
1133
1134 mrb_define_class_method(mrb, _module_target_board, "wait_msg", mrb_target_board_wait_msg, MRB_ARGS_REQ(1));
1135 mrb_define_class_method(mrb, _module_target_board, "restart", mrb_target_board_restart, MRB_ARGS_NONE());
1136 mrb_define_class_method(mrb, _module_target_board, "snd_msg", mrb_target_board_snd_msg, MRB_ARGS_REQ(2));
1137 mrb_define_class_method(mrb, _module_target_board, "is_local_addr", mrb_target_board_is_local_addr, MRB_ARGS_REQ(1));
1138 mrb_define_class_method(mrb, _module_target_board, "is_multicast_addr", mrb_target_board_is_multicast_addr, MRB_ARGS_REQ(1));
1139 mrb_define_class_method(mrb, _module_target_board, "equals_addr", mrb_target_board_equals_addr, MRB_ARGS_REQ(2));
1140 mrb_define_class_method(mrb, _module_target_board, "get_local_addr", mrb_target_board_get_local_addr, MRB_ARGS_NONE());
1141 mrb_define_class_method(mrb, _module_target_board, "get_multicast_addr", mrb_target_board_get_multicast_addr, MRB_ARGS_NONE());
1142}
1143
1144void mrb_mruby_others_gem_final(mrb_state* mrb)
1145{
1146}
Note: See TracBrowser for help on using the repository browser.