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

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

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.3 KB
RevLine 
[270]1/*
[439]2 * TOPPERS PROJECT Home Network Working Group Software
[279]3 *
[439]4 * Copyright (C) 2017-2019 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);
[428]93extern int openssl_main(int argc, char *argv[]);
[279]94extern int onitest_main(int argc, char **argv);
95extern int tcp_echo_main(int argc, char **argv);
96extern int echo_client_main(int argc, char **argv);
97extern int mrdb_break(void);
[270]98
[279]99static const cmd_table_t cmdlist[] = {
100 {"mrbc", "mruby compiler executable", mrbc_main},
101 {"mrdb","mruby debugger command", mrdb_main},
102 {"mruby","mruby command", mruby_main},
103 {"mirb", "Embeddable Interactive Ruby Shell", mirb_main},
[331]104 {"curl", "Command lines or scripts to transfer data", curl_main},
[279]105 {"tcc", "Tiny C compiler", tcc_main},
106 {"vi", "Text editor", vi_main},
[428]107 {"openssl", "Cryptography and SSL/TLS Toolkit", openssl_main},
[279]108 {"onitest", "Onigumo Test", onitest_main},
109 {"tcp_echo", "TCP echo server/client", tcp_echo_main},
110 {"help", "This is a description text string for help command.", usrcmd_help},
[270]111};
[279]112cmd_table_info_t cmd_table_info = { &cmdlist, sizeof(cmdlist) / sizeof(cmdlist[0]) };
[270]113
[279]114int echonet = 1;
115struct timeval main_time;
116struct RClass *_module_target_board;
117int sock;
[270]118
[279]119int main(int argc, char **argv)
[270]120{
[279]121 if (argc == 0) {
122 return 0;
[270]123 }
[279]124 const cmd_table_t *p = cmd_table_info.table;
125 for (int i = 0; i < cmd_table_info.count; i++) {
126 if (strcmp((const char *)argv[0], p->cmd) == 0) {
127 return p->func(argc, argv);
[270]128 }
[279]129 p++;
[270]130 }
[279]131 printf("Unknown command found.\n");
132 return 0;
[270]133}
134
[279]135int run_mruby_code(int argc, char **argv, const uint8_t *code, const char *cmdline)
[270]136{
[279]137 mrb_state *mrb;
138 struct RProc* n;
139 struct mrb_irep *irep;
140 mrb_value ARGV;
141 mrbc_context *c;
142 mrb_value v;
143 mrb_sym zero_sym;
[270]144
[279]145 echonet = 0;
[270]146
[279]147 /* mrubyの初期化 */
148 mrb = mrb_open();
149 if (mrb == NULL)
150 return -1;
[270]151
[279]152 int ai = mrb_gc_arena_save(mrb);
153 ARGV = mrb_ary_new_capa(mrb, argc);
154 for (int i = 0; i < argc; i++) {
155 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i]));
[270]156 }
[279]157 mrb_define_global_const(mrb, "ARGV", ARGV);
[270]158
[279]159 c = mrbc_context_new(mrb);
160 c->dump_result = TRUE;
[270]161
[279]162 /* Set $0 */
163 zero_sym = mrb_intern_lit(mrb, "$0");
164 mrbc_filename(mrb, c, cmdline);
165 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
[270]166
[279]167 irep = mrb_read_irep(mrb, code);
168 n = mrb_proc_new(mrb, irep);
169 mrb_run(mrb, n, mrb_nil_value());
[270]170
[279]171 mrb_gc_arena_restore(mrb, ai);
172 mrbc_context_free(mrb, c);
173 if (mrb->exc) {
174 if (!mrb_undef_p(v)) {
175 mrb_print_error(mrb);
[270]176 }
[279]177 n = -1;
[270]178 }
179
[279]180 mrb_close(mrb);
181 return 0;
[270]182}
183
[279]184int tcp_echo_main(int argc, char **argv)
[270]185{
[279]186 extern const uint8_t echo_server_code[];
187 extern const uint8_t echo_client_code[];
[270]188
[279]189 if (argc >= 2) {
190 if (strcmp(argv[1], "-s") == 0) {
191 return run_mruby_code(argc - 2, &argv[2], echo_server_code, "echo_server");
[270]192 }
[279]193 else if (strcmp(argv[1], "-c") == 0) {
194 return run_mruby_code(argc - 2, &argv[2], echo_client_code, "echo_client");
[270]195 }
196 }
197
[279]198 printf("tcp_echo -s port\n");
199 printf("tcp_echo -c ipaddr port\n");
[270]200
[279]201 return 0;
[270]202}
203
[279]204int usrcmd_help(int argc, char **argv)
[270]205{
[279]206 const cmd_table_t *p = cmd_table_info.table;
207 for (int i = 0; i < cmd_table_info.count; i++) {
208 printf(p->cmd);
209 printf("\t:");
210 printf(p->desc);
211 printf("\n");
212 p++;
[270]213 }
[279]214 return 0;
[270]215}
216
[279]217void sigusr1_handler(int sig)
[270]218{
[279]219 printf("signal called\n");
[270]220}
221
[279]222void mrb_target_board_init()
[270]223{
[279]224 int ret;
225 struct sockaddr_in ep;
226 struct ip_mreq mreq;
[270]227
[279]228 signal(SIGUSR1, sigusr1_handler);
[270]229
[279]230 sock = socket(AF_INET, SOCK_DGRAM, 0);
[270]231
[279]232 memset(&ep, 0, sizeof(ep));
233 ep.sin_family = AF_INET;
234 ep.sin_port = htons(3610);
235 ep.sin_addr.s_addr = INADDR_ANY;
236 //ep.sin_addr.s_addr = MAKE_IPV4_ADDR(192,168,137,200);
[270]237
[279]238 ret = bind(sock, &ep, sizeof(ep));
239 if (ret != 0) {
240 printf("bind %d", ret);
241 return;
[270]242 }
243
[279]244 mreq.imr_interface.s_addr = INADDR_ANY;
245 mreq.imr_multiaddr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
[270]246
[279]247 ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
248 if (ret != 0) {
249 printf("setsockopt %d", ret);
[270]250 return;
251 }
252
[279]253 ret = gettimeofday(&main_time, NULL);
254 if (ret != 0) {
255 printf("gettimeofday");
[270]256 return;
257 }
258}
259
[279]260void mrb_target_board_final()
[270]261{
[279]262 close(sock);
[270]263}
264
[279]265void mrb_target_board_break()
[270]266{
[279]267 raise(SIGUSR1);
[270]268}
269
270/*
271 * アプリケーションタスクの登録
272 */
273static mrb_value mrb_target_board_wait_msg(mrb_state *mrb, mrb_value self)
274{
[279]275 int tmr;
276 struct timeval timer, *ptimer;
277 struct timeval now, elps;
278 int ret, ret2;
279 struct udp_msg _msg;
280 struct udp_msg *msg = &_msg;
[270]281 mrb_value arv[3];
[279]282 fd_set readfds, writefds, errorfds;
[270]283
[279]284 mrb_get_args(mrb, "i", &tmr);
[270]285
[279]286 if (tmr < 0)
287 ptimer = NULL;
288 else {
289 timer.tv_sec = tmr / 1000;
290 timer.tv_usec = (tmr % 1000) * 1000;
291 ptimer = &timer;
[270]292 }
293
[279]294 FD_ZERO(&readfds);
295 FD_ZERO(&writefds);
296 FD_ZERO(&errorfds);
297 FD_SET(sock, &readfds);
298 FD_SET(sock, &writefds);
299 FD_SET(sock, &errorfds);
300
[270]301 /* メッセージ待ち */
[279]302 memset(msg, 0, sizeof(*msg));
303 ret = select(sock + 1, &readfds, &writefds, &errorfds, ptimer);
304 if (ret < 0)
305 mrb_raise(mrb, E_RUNTIME_ERROR, "socket select error");
306 if (FD_ISSET(sock, &readfds)) {
307 int fromlen = sizeof(msg->dst);
308 msg->len = recvfrom(sock, msg->buffer, sizeof(msg->buffer), 0, &msg->dst, &fromlen);
309 if (msg->len < 0) {
310 printf("recvfrom %d", msg->len);
311 return mrb_nil_value();
312 }
[270]313 }
314
[279]315 ret2 = gettimeofday(&now, NULL);
316 if (ret2 != 0) {
317 printf("gettimeofday");
[270]318 return mrb_nil_value();
319 }
320
[279]321 timersub(&now, &main_time, &elps);
322 arv[0] = mrb_fixnum_value(elps.tv_sec);
323 main_time = now;
[270]324
325 /* タイムアウトの場合 */
[279]326 if (ret == 0) {
[270]327 return mrb_ary_new_from_values(mrb, 1, arv);
328 }
329
330 /* 内部イベントの場合 */
[279]331 if (msg->dst.sin_addr.s_addr == 0) {
[270]332 /* Ethernet Link up */
333 if (msg->buffer[0] & IF_FLAG_LINK_UP) {
334 arv[1] = mrb_fixnum_value(1);
335 }
336 /* EP Link up */
337 else if (msg->buffer[0] & IF_FLAG_UP) {
338 arv[1] = mrb_fixnum_value(2);
339 }
340
341 return mrb_ary_new_from_values(mrb, 2, arv);
342 }
343 /* Echonet電文受信の場合 */
344 else {
345 /* 通信端点 */
346 arv[1] = mrb_str_new(mrb, (char *)&msg->dst, sizeof(msg->dst));
347
348 /* 受信データ */
349 arv[2] = mrb_str_new(mrb, (char *)msg->buffer, msg->len);
350
351 return mrb_ary_new_from_values(mrb, 3, arv);
352 }
353}
354
355/*
356 * アプリケーションタスクの登録
357 */
358static mrb_value mrb_target_board_restart(mrb_state *mrb, mrb_value self)
359{
360 /* DHCP開始 */
361
362 return self;
363}
364
365/*
366 * 通信レイヤーへの送信
367 */
368static mrb_value mrb_target_board_snd_msg(mrb_state *mrb, mrb_value self)
369{
370 mrb_value rep;
371 mrb_value rdat;
[279]372 struct sockaddr_in *ep;
373 int ret;
[270]374
375 mrb_get_args(mrb, "SS", &rep, &rdat);
376
[279]377 if (RSTRING_LEN(rep) != sizeof(struct sockaddr_in)) {
[270]378 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
379 return mrb_nil_value();
380 }
381
[279]382 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]383
[279]384 ret = sendto(sock, RSTRING_PTR(rdat), RSTRING_LEN(rdat), 0, (struct sockaddr *)ep, sizeof(*ep));
[270]385 if (ret < 0) {
[279]386 mrb_raise(mrb, E_RUNTIME_ERROR, "sendto");
[270]387 return mrb_nil_value();
388 }
389
390 return mrb_nil_value();
391}
392
393/*
394 * ローカルアドレスか確認
395 */
396static mrb_value mrb_target_board_is_local_addr(mrb_state *mrb, mrb_value self)
397{
398 mrb_value rep;
[279]399 struct sockaddr_in *ep;
[270]400
401 mrb_get_args(mrb, "S", &rep);
402
[279]403 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
[270]404 mrb_raise(mrb, E_RUNTIME_ERROR, "is_local_addr");
405 return mrb_nil_value();
406 }
407
[279]408 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]409
[279]410 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(127, 0, 0, 1)) ? mrb_true_value() : mrb_false_value();
[270]411}
412
413/*
414 * マルチキャストアドレスか確認
415 */
416static mrb_value mrb_target_board_is_multicast_addr(mrb_state *mrb, mrb_value self)
417{
418 mrb_value rep;
[279]419 struct sockaddr_in *ep;
[270]420
421 mrb_get_args(mrb, "S", &rep);
422
[279]423 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
[270]424 mrb_raise(mrb, E_RUNTIME_ERROR, "is_multicast_addr");
425 return mrb_nil_value();
426 }
427
[279]428 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
[270]429
[279]430 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(224, 0, 23, 0)) ? mrb_true_value() : mrb_false_value();
[270]431}
432
433/*
434 * 同一アドレスか確認
435 */
436static mrb_value mrb_target_board_equals_addr(mrb_state *mrb, mrb_value self)
437{
438 mrb_value rep1, rep2;
[279]439 struct sockaddr_in *ep1, *ep2;
[270]440
441 mrb_get_args(mrb, "SS", &rep1, &rep2);
442
[279]443 if ((RSTRING_LEN(rep1) != sizeof(struct sockaddr_in)) || (RSTRING_LEN(rep2) != sizeof(struct sockaddr_in))) {
[270]444 mrb_raise(mrb, E_RUNTIME_ERROR, "equals_addr");
445 return mrb_nil_value();
446 }
447
[279]448 ep1 = (struct sockaddr_in *)RSTRING_PTR(rep1);
449 ep2 = (struct sockaddr_in *)RSTRING_PTR(rep2);
[270]450
[279]451 return (ep1->sin_addr.s_addr == ep2->sin_addr.s_addr) ? mrb_true_value() : mrb_false_value();
[270]452}
453
454/*
455 * ローカルアドレスの取得
456 */
457static mrb_value mrb_target_board_get_local_addr(mrb_state *mrb, mrb_value self)
458{
[279]459 struct sockaddr_in ep;
[270]460 mrb_value rep;
461
[279]462 memset(&ep, 0, sizeof(ep));
463 ep.sin_family = AF_INET;
464 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(127, 0, 0, 1);
465 ep.sin_port = htons(3610);
[270]466
467 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
468
469 return rep;
470}
471
472/*
473 * マルチキャストアドレスの取得
474 */
475static mrb_value mrb_target_board_get_multicast_addr(mrb_state *mrb, mrb_value self)
476{
[279]477 struct sockaddr_in ep;
[270]478 mrb_value rep;
479
[279]480 memset(&ep, 0, sizeof(ep));
481 ep.sin_family = AF_INET;
482 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
483 ep.sin_port = htons(3610);
[270]484
485 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
486
487 return rep;
488}
489
490void mrb_mruby_others_gem_init(mrb_state* mrb)
491{
[279]492 if (!echonet)
493 return;
494
[270]495 _module_target_board = mrb_define_module(mrb, "TargetBoard");
496
497 mrb_define_class_method(mrb, _module_target_board, "wait_msg", mrb_target_board_wait_msg, MRB_ARGS_REQ(1));
498 mrb_define_class_method(mrb, _module_target_board, "restart", mrb_target_board_restart, MRB_ARGS_NONE());
499 mrb_define_class_method(mrb, _module_target_board, "snd_msg", mrb_target_board_snd_msg, MRB_ARGS_REQ(2));
500 mrb_define_class_method(mrb, _module_target_board, "is_local_addr", mrb_target_board_is_local_addr, MRB_ARGS_REQ(1));
501 mrb_define_class_method(mrb, _module_target_board, "is_multicast_addr", mrb_target_board_is_multicast_addr, MRB_ARGS_REQ(1));
502 mrb_define_class_method(mrb, _module_target_board, "equals_addr", mrb_target_board_equals_addr, MRB_ARGS_REQ(2));
503 mrb_define_class_method(mrb, _module_target_board, "get_local_addr", mrb_target_board_get_local_addr, MRB_ARGS_NONE());
504 mrb_define_class_method(mrb, _module_target_board, "get_multicast_addr", mrb_target_board_get_multicast_addr, MRB_ARGS_NONE());
[279]505
506 mrb_target_board_init();
[270]507}
508
509void mrb_mruby_others_gem_final(mrb_state* mrb)
510{
[279]511 if (!echonet)
512 return;
513
514 mrb_target_board_final();
[270]515}
[279]516
[439]517extern char __start_rodata, __end_rodata;
518
519mrb_bool mrb_ro_data_p(const char *p)
520{
521 return (&__start_rodata <= p && p < &__end_rodata);
522}
523
[331]524void _start_c(long *p);
[427]525extern int __start_idata, __start_data, __end_data;
526extern int __start_bss, __end_bss;
[279]527
[331]528void _PowerON_Reset(long *args)
[279]529{
[427]530 memcpy(&__start_data, &__start_idata, (size_t)&__end_data - (size_t)&__start_data);
531 memset(&__start_bss, 0, (size_t)&__end_bss - (size_t)&__start_bss);
[279]532
[331]533 _start_c(args);
[279]534}
535
[427]536#define FVECT_SECT __attribute__ ((section (".vector")))
[279]537const void *HardwareVectors[] FVECT_SECT = {
538 _PowerON_Reset,
539 mrdb_break,
540};
Note: See TracBrowser for help on using the repository browser.