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

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.0 KB
RevLine 
[270]1/*
2 * TOPPERS ECHONET Lite Communication Middleware
[279]3 *
[286]4 * Copyright (C) 2014-2017 Cores Co., Ltd. Japan
[279]5 *
[270]6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
[279]28 *
[270]29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
[279]34 *
[270]35 * @(#) $Id$
36 */
37
[279]38 /*
39 * サンプルプログラム(1)の本体
40 */
[270]41
[279]42#include <sys/types.h>
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <netinet/in.h>
46#include <netinet/tcp.h>
47#include <arpa/inet.h>
48#include <fcntl.h>
49#include <netdb.h>
50#include <unistd.h>
51#include <signal.h>
52#include <time.h>
53#include <sys/time.h>
[331]54#include <unistd.h>
[279]55#include <errno.h>
56
[270]57#include <string.h>
58#include <mruby.h>
59#include <mruby/compile.h>
60#include <mruby/proc.h>
61#include <mruby/array.h>
62#include <mruby/data.h>
63#include <mruby/class.h>
64#include <mruby/dump.h>
65#include <mruby/string.h>
[331]66#include <ntshell/usrcmd.h>
[270]67
[279]68#define ETHER_MAX_LEN 1518
69#define IF_FLAG_UP 1
70#define IF_FLAG_LINK_UP 2
71#define MAKE_IPV4_ADDR(a,b,c,d) htonl(((uint32_t)(a)<<24)|((uint32_t)(b)<<16)|((uint32_t)(c)<<8)|(d))
[270]72
[279]73struct udp_msg
74{
75 struct sockaddr_in dst;
76 int len;
77 uint8_t buffer[ETHER_MAX_LEN];
78};
[270]79
[279]80typedef struct
81{
82 cmd_table_t *table;
83 cmd_table_t *count;
84} cmd_table_info_t;
[270]85
[279]86extern int mrbc_main(int argc, char **argv);
87extern int mrdb_main(int argc, char **argv);
88extern int mruby_main(int argc, char **argv);
89extern int mirb_main(int argc, char **argv);
[331]90extern int curl_main(int argc, char **argv);
[279]91extern int tcc_main(int argc, char **argv);
92extern int vi_main(int argc, char **argv);
93extern int onitest_main(int argc, char **argv);
94extern int tcp_echo_main(int argc, char **argv);
95extern int echo_client_main(int argc, char **argv);
96extern int mrdb_break(void);
[270]97
[279]98static const cmd_table_t cmdlist[] = {
99 {"mrbc", "mruby compiler executable", mrbc_main},
100 {"mrdb","mruby debugger command", mrdb_main},
101 {"mruby","mruby command", mruby_main},
102 {"mirb", "Embeddable Interactive Ruby Shell", mirb_main},
[331]103 {"curl", "Command lines or scripts to transfer data", curl_main},
[279]104 {"tcc", "Tiny C compiler", tcc_main},
105 {"vi", "Text editor", vi_main},
106 {"onitest", "Onigumo Test", onitest_main},
107 {"tcp_echo", "TCP echo server/client", tcp_echo_main},
108 {"help", "This is a description text string for help command.", usrcmd_help},
[270]109};
[279]110cmd_table_info_t cmd_table_info = { &cmdlist, sizeof(cmdlist) / sizeof(cmdlist[0]) };
[270]111
[279]112int echonet = 1;
113struct timeval main_time;
114struct RClass *_module_target_board;
115int sock;
[270]116
[279]117int main(int argc, char **argv)
[270]118{
[279]119 if (argc == 0) {
120 return 0;
[270]121 }
[279]122 const cmd_table_t *p = cmd_table_info.table;
123 for (int i = 0; i < cmd_table_info.count; i++) {
124 if (strcmp((const char *)argv[0], p->cmd) == 0) {
125 return p->func(argc, argv);
[270]126 }
[279]127 p++;
[270]128 }
[279]129 printf("Unknown command found.\n");
130 return 0;
[270]131}
132
[279]133int run_mruby_code(int argc, char **argv, const uint8_t *code, const char *cmdline)
[270]134{
[279]135 mrb_state *mrb;
136 struct RProc* n;
137 struct mrb_irep *irep;
138 mrb_value ARGV;
139 mrbc_context *c;
140 mrb_value v;
141 mrb_sym zero_sym;
[270]142
[279]143 echonet = 0;
[270]144
[279]145 /* mrubyの初期化 */
146 mrb = mrb_open();
147 if (mrb == NULL)
148 return -1;
[270]149
[279]150 int ai = mrb_gc_arena_save(mrb);
151 ARGV = mrb_ary_new_capa(mrb, argc);
152 for (int i = 0; i < argc; i++) {
153 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i]));
[270]154 }
[279]155 mrb_define_global_const(mrb, "ARGV", ARGV);
[270]156
[279]157 c = mrbc_context_new(mrb);
158 c->dump_result = TRUE;
[270]159
[279]160 /* Set $0 */
161 zero_sym = mrb_intern_lit(mrb, "$0");
162 mrbc_filename(mrb, c, cmdline);
163 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
[270]164
[279]165 irep = mrb_read_irep(mrb, code);
166 n = mrb_proc_new(mrb, irep);
167 mrb_run(mrb, n, mrb_nil_value());
[270]168
[279]169 mrb_gc_arena_restore(mrb, ai);
170 mrbc_context_free(mrb, c);
171 if (mrb->exc) {
172 if (!mrb_undef_p(v)) {
173 mrb_print_error(mrb);
[270]174 }
[279]175 n = -1;
[270]176 }
177
[279]178 mrb_close(mrb);
179 return 0;
[270]180}
181
[279]182int tcp_echo_main(int argc, char **argv)
[270]183{
[279]184 extern const uint8_t echo_server_code[];
185 extern const uint8_t echo_client_code[];
[270]186
[279]187 if (argc >= 2) {
188 if (strcmp(argv[1], "-s") == 0) {
189 return run_mruby_code(argc - 2, &argv[2], echo_server_code, "echo_server");
[270]190 }
[279]191 else if (strcmp(argv[1], "-c") == 0) {
192 return run_mruby_code(argc - 2, &argv[2], echo_client_code, "echo_client");
[270]193 }
194 }
195
[279]196 printf("tcp_echo -s port\n");
197 printf("tcp_echo -c ipaddr port\n");
[270]198
[279]199 return 0;
[270]200}
201
[279]202int usrcmd_help(int argc, char **argv)
[270]203{
[279]204 const cmd_table_t *p = cmd_table_info.table;
205 for (int i = 0; i < cmd_table_info.count; i++) {
206 printf(p->cmd);
207 printf("\t:");
208 printf(p->desc);
209 printf("\n");
210 p++;
[270]211 }
[279]212 return 0;
[270]213}
214
[279]215void sigusr1_handler(int sig)
[270]216{
[279]217 printf("signal called\n");
[270]218}
219
[279]220void mrb_target_board_init()
[270]221{
[279]222 int ret;
223 struct sockaddr_in ep;
224 struct ip_mreq mreq;
[270]225
[279]226 signal(SIGUSR1, sigusr1_handler);
[270]227
[279]228 sock = socket(AF_INET, SOCK_DGRAM, 0);
[270]229
[279]230 memset(&ep, 0, sizeof(ep));
231 ep.sin_family = AF_INET;
232 ep.sin_port = htons(3610);
233 ep.sin_addr.s_addr = INADDR_ANY;
234 //ep.sin_addr.s_addr = MAKE_IPV4_ADDR(192,168,137,200);
[270]235
[279]236 ret = bind(sock, &ep, sizeof(ep));
237 if (ret != 0) {
238 printf("bind %d", ret);
239 return;
[270]240 }
241
[279]242 mreq.imr_interface.s_addr = INADDR_ANY;
243 mreq.imr_multiaddr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
[270]244
[279]245 ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
246 if (ret != 0) {
247 printf("setsockopt %d", ret);
[270]248 return;
249 }
250
[279]251 ret = gettimeofday(&main_time, NULL);
252 if (ret != 0) {
253 printf("gettimeofday");
[270]254 return;
255 }
256}
257
[279]258void mrb_target_board_final()
[270]259{
[279]260 close(sock);
[270]261}
262
[279]263void mrb_target_board_break()
[270]264{
[279]265 raise(SIGUSR1);
[270]266}
267
268/*
269 * アプリケーションタスクの登録
270 */
271static mrb_value mrb_target_board_wait_msg(mrb_state *mrb, mrb_value self)
272{
[279]273 int tmr;
274 struct timeval timer, *ptimer;
275 struct timeval now, elps;
276 int ret, ret2;
277 struct udp_msg _msg;
278 struct udp_msg *msg = &_msg;
[270]279 mrb_value arv[3];
[279]280 fd_set readfds, writefds, errorfds;
[270]281
[279]282 mrb_get_args(mrb, "i", &tmr);
[270]283
[279]284 if (tmr < 0)
285 ptimer = NULL;
286 else {
287 timer.tv_sec = tmr / 1000;
288 timer.tv_usec = (tmr % 1000) * 1000;
289 ptimer = &timer;
[270]290 }
291
[279]292 FD_ZERO(&readfds);
293 FD_ZERO(&writefds);
294 FD_ZERO(&errorfds);
295 FD_SET(sock, &readfds);
296 FD_SET(sock, &writefds);
297 FD_SET(sock, &errorfds);
298
[270]299 /* メッセージ待ち */
[279]300 memset(msg, 0, sizeof(*msg));
301 ret = select(sock + 1, &readfds, &writefds, &errorfds, ptimer);
302 if (ret < 0)
303 mrb_raise(mrb, E_RUNTIME_ERROR, "socket select error");
304 if (FD_ISSET(sock, &readfds)) {
305 int fromlen = sizeof(msg->dst);
306 msg->len = recvfrom(sock, msg->buffer, sizeof(msg->buffer), 0, &msg->dst, &fromlen);
307 if (msg->len < 0) {
308 printf("recvfrom %d", msg->len);
309 return mrb_nil_value();
310 }
[270]311 }
312
[279]313 ret2 = gettimeofday(&now, NULL);
314 if (ret2 != 0) {
315 printf("gettimeofday");
[270]316 return mrb_nil_value();
317 }
318
[279]319 timersub(&now, &main_time, &elps);
320 arv[0] = mrb_fixnum_value(elps.tv_sec);
321 main_time = now;
[270]322
323 /* タイムアウトの場合 */
[279]324 if (ret == 0) {
[270]325 return mrb_ary_new_from_values(mrb, 1, arv);
326 }
327
328 /* 内部イベントの場合 */
[279]329 if (msg->dst.sin_addr.s_addr == 0) {
[270]330 /* Ethernet Link up */
331 if (msg->buffer[0] & IF_FLAG_LINK_UP) {
332 arv[1] = mrb_fixnum_value(1);
333 }
334 /* EP Link up */
335 else if (msg->buffer[0] & IF_FLAG_UP) {
336 arv[1] = mrb_fixnum_value(2);
337 }
338
339 return mrb_ary_new_from_values(mrb, 2, arv);
340 }
341 /* Echonet電文受信の場合 */
342 else {
343 /* 通信端点 */
344 arv[1] = mrb_str_new(mrb, (char *)&msg->dst, sizeof(msg->dst));
345
346 /* 受信データ */
347 arv[2] = mrb_str_new(mrb, (char *)msg->buffer, msg->len);
348
349 return mrb_ary_new_from_values(mrb, 3, arv);
350 }
351}
352
353/*
354 * アプリケーションタスクの登録
355 */
356static mrb_value mrb_target_board_restart(mrb_state *mrb, mrb_value self)
357{
358 /* DHCP開始 */
359
360 return self;
361}
362
363/*
364 * 通信レイヤーへの送信
365 */
366static mrb_value mrb_target_board_snd_msg(mrb_state *mrb, mrb_value self)
367{
368 mrb_value rep;
369 mrb_value rdat;
[279]370 struct sockaddr_in *ep;
371 int ret;
[270]372
373 mrb_get_args(mrb, "SS", &rep, &rdat);
374
[279]375 if (RSTRING_LEN(rep) != sizeof(struct sockaddr_in)) {
[270]376 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
377 return mrb_nil_value();
378 }
379
[279]380 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]381
[279]382 ret = sendto(sock, RSTRING_PTR(rdat), RSTRING_LEN(rdat), 0, (struct sockaddr *)ep, sizeof(*ep));
[270]383 if (ret < 0) {
[279]384 mrb_raise(mrb, E_RUNTIME_ERROR, "sendto");
[270]385 return mrb_nil_value();
386 }
387
388 return mrb_nil_value();
389}
390
391/*
392 * ローカルアドレスか確認
393 */
394static mrb_value mrb_target_board_is_local_addr(mrb_state *mrb, mrb_value self)
395{
396 mrb_value rep;
[279]397 struct sockaddr_in *ep;
[270]398
399 mrb_get_args(mrb, "S", &rep);
400
[279]401 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
[270]402 mrb_raise(mrb, E_RUNTIME_ERROR, "is_local_addr");
403 return mrb_nil_value();
404 }
405
[279]406 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]407
[279]408 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(127, 0, 0, 1)) ? mrb_true_value() : mrb_false_value();
[270]409}
410
411/*
412 * マルチキャストアドレスか確認
413 */
414static mrb_value mrb_target_board_is_multicast_addr(mrb_state *mrb, mrb_value self)
415{
416 mrb_value rep;
[279]417 struct sockaddr_in *ep;
[270]418
419 mrb_get_args(mrb, "S", &rep);
420
[279]421 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
[270]422 mrb_raise(mrb, E_RUNTIME_ERROR, "is_multicast_addr");
423 return mrb_nil_value();
424 }
425
[279]426 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]427
[279]428 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(224, 0, 23, 0)) ? mrb_true_value() : mrb_false_value();
[270]429}
430
431/*
432 * 同一アドレスか確認
433 */
434static mrb_value mrb_target_board_equals_addr(mrb_state *mrb, mrb_value self)
435{
436 mrb_value rep1, rep2;
[279]437 struct sockaddr_in *ep1, *ep2;
[270]438
439 mrb_get_args(mrb, "SS", &rep1, &rep2);
440
[279]441 if ((RSTRING_LEN(rep1) != sizeof(struct sockaddr_in)) || (RSTRING_LEN(rep2) != sizeof(struct sockaddr_in))) {
[270]442 mrb_raise(mrb, E_RUNTIME_ERROR, "equals_addr");
443 return mrb_nil_value();
444 }
445
[279]446 ep1 = (struct sockaddr_in *)RSTRING_PTR(rep1);
447 ep2 = (struct sockaddr_in *)RSTRING_PTR(rep2);
[270]448
[279]449 return (ep1->sin_addr.s_addr == ep2->sin_addr.s_addr) ? mrb_true_value() : mrb_false_value();
[270]450}
451
452/*
453 * ローカルアドレスの取得
454 */
455static mrb_value mrb_target_board_get_local_addr(mrb_state *mrb, mrb_value self)
456{
[279]457 struct sockaddr_in ep;
[270]458 mrb_value rep;
459
[279]460 memset(&ep, 0, sizeof(ep));
461 ep.sin_family = AF_INET;
462 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(127, 0, 0, 1);
463 ep.sin_port = htons(3610);
[270]464
465 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
466
467 return rep;
468}
469
470/*
471 * マルチキャストアドレスの取得
472 */
473static mrb_value mrb_target_board_get_multicast_addr(mrb_state *mrb, mrb_value self)
474{
[279]475 struct sockaddr_in ep;
[270]476 mrb_value rep;
477
[279]478 memset(&ep, 0, sizeof(ep));
479 ep.sin_family = AF_INET;
480 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
481 ep.sin_port = htons(3610);
[270]482
483 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
484
485 return rep;
486}
487
488void mrb_mruby_others_gem_init(mrb_state* mrb)
489{
[279]490 if (!echonet)
491 return;
492
[270]493 _module_target_board = mrb_define_module(mrb, "TargetBoard");
494
495 mrb_define_class_method(mrb, _module_target_board, "wait_msg", mrb_target_board_wait_msg, MRB_ARGS_REQ(1));
496 mrb_define_class_method(mrb, _module_target_board, "restart", mrb_target_board_restart, MRB_ARGS_NONE());
497 mrb_define_class_method(mrb, _module_target_board, "snd_msg", mrb_target_board_snd_msg, MRB_ARGS_REQ(2));
498 mrb_define_class_method(mrb, _module_target_board, "is_local_addr", mrb_target_board_is_local_addr, MRB_ARGS_REQ(1));
499 mrb_define_class_method(mrb, _module_target_board, "is_multicast_addr", mrb_target_board_is_multicast_addr, MRB_ARGS_REQ(1));
500 mrb_define_class_method(mrb, _module_target_board, "equals_addr", mrb_target_board_equals_addr, MRB_ARGS_REQ(2));
501 mrb_define_class_method(mrb, _module_target_board, "get_local_addr", mrb_target_board_get_local_addr, MRB_ARGS_NONE());
502 mrb_define_class_method(mrb, _module_target_board, "get_multicast_addr", mrb_target_board_get_multicast_addr, MRB_ARGS_NONE());
[279]503
504 mrb_target_board_init();
[270]505}
506
507void mrb_mruby_others_gem_final(mrb_state* mrb)
508{
[279]509 if (!echonet)
510 return;
511
512 mrb_target_board_final();
[270]513}
[279]514
[331]515void _start_c(long *p);
[279]516int _data, _mdata, _edata;
517int _bss, _ebss;
518
[331]519void _PowerON_Reset(long *args)
[279]520{
521 memcpy(&_data, &_mdata, (size_t)&_edata - (size_t)&_data);
522 memset(&_bss, 0, (size_t)&_ebss - (size_t)&_bss);
523
[331]524 _start_c(args);
[279]525}
526
527#define FVECT_SECT __attribute__ ((section (".fvectors")))
528const void *HardwareVectors[] FVECT_SECT = {
529 _PowerON_Reset,
530 mrdb_break,
531};
532
533char stack_space[0x100000] __attribute__ ((section (".stack")));
Note: See TracBrowser for help on using the repository browser.