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

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

プログラムテーブルのセクションを追加しntshellで読みだしてHELPを表示するよう変更

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 12.4 KB
Line 
1/*
2 * TOPPERS PROJECT Home Network Working Group Software
3 *
4 * Copyright (C) 2017-2019 Cores Co., Ltd. Japan
5 *
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 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38 /*
39 * サンプルプログラム(1)の本体
40 */
41
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>
54#include <unistd.h>
55#include <errno.h>
56
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>
66#include <ntshell/usrcmd.h>
67
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))
72
73struct udp_msg
74{
75 struct sockaddr_in dst;
76 int len;
77 uint8_t buffer[ETHER_MAX_LEN];
78};
79
80extern const cmd_table_info_t cmd_table_info;
81
82int echonet = 1;
83struct timeval main_time;
84struct RClass *_module_target_board;
85int sock;
86
87int main(int argc, char **argv)
88{
89 if (argc == 0) {
90 return 0;
91 }
92 const cmd_table_t *p = cmd_table_info.table;
93 for (int i = 0; i < cmd_table_info.count; i++) {
94 if (strcmp((const char *)argv[0], p->cmd) == 0) {
95 return p->func(argc, argv);
96 }
97 p++;
98 }
99 printf("Unknown command found.\n");
100 return 0;
101}
102
103int run_mruby_code(int argc, char **argv, const uint8_t *code, const char *cmdline)
104{
105 mrb_state *mrb;
106 struct RProc* n;
107 struct mrb_irep *irep;
108 mrb_value ARGV;
109 mrbc_context *c;
110 mrb_value v;
111 mrb_sym zero_sym;
112
113 echonet = 0;
114
115 /* mrubyの初期化 */
116 mrb = mrb_open();
117 if (mrb == NULL)
118 return -1;
119
120 int ai = mrb_gc_arena_save(mrb);
121 ARGV = mrb_ary_new_capa(mrb, argc);
122 for (int i = 0; i < argc; i++) {
123 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i]));
124 }
125 mrb_define_global_const(mrb, "ARGV", ARGV);
126
127 c = mrbc_context_new(mrb);
128 c->dump_result = TRUE;
129
130 /* Set $0 */
131 zero_sym = mrb_intern_lit(mrb, "$0");
132 mrbc_filename(mrb, c, cmdline);
133 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
134
135 irep = mrb_read_irep(mrb, code);
136 n = mrb_proc_new(mrb, irep);
137 mrb_run(mrb, n, mrb_nil_value());
138
139 mrb_gc_arena_restore(mrb, ai);
140 mrbc_context_free(mrb, c);
141 if (mrb->exc) {
142 if (!mrb_undef_p(v)) {
143 mrb_print_error(mrb);
144 }
145 n = -1;
146 }
147
148 mrb_close(mrb);
149 return 0;
150}
151
152int tcp_echo_main(int argc, char **argv)
153{
154 extern const uint8_t echo_server_code[];
155 extern const uint8_t echo_client_code[];
156
157 if (argc >= 2) {
158 if (strcmp(argv[1], "-s") == 0) {
159 return run_mruby_code(argc - 2, &argv[2], echo_server_code, "echo_server");
160 }
161 else if (strcmp(argv[1], "-c") == 0) {
162 return run_mruby_code(argc - 2, &argv[2], echo_client_code, "echo_client");
163 }
164 }
165
166 printf("tcp_echo -s port\n");
167 printf("tcp_echo -c ipaddr port\n");
168
169 return 0;
170}
171
172void sigusr1_handler(int sig)
173{
174 printf("signal called\n");
175}
176
177void mrb_target_board_init()
178{
179 int ret;
180 struct sockaddr_in ep;
181 struct ip_mreq mreq;
182
183 signal(SIGUSR1, sigusr1_handler);
184
185 sock = socket(AF_INET, SOCK_DGRAM, 0);
186
187 memset(&ep, 0, sizeof(ep));
188 ep.sin_family = AF_INET;
189 ep.sin_port = htons(3610);
190 ep.sin_addr.s_addr = INADDR_ANY;
191 //ep.sin_addr.s_addr = MAKE_IPV4_ADDR(192,168,137,200);
192
193 ret = bind(sock, &ep, sizeof(ep));
194 if (ret != 0) {
195 printf("bind %d", ret);
196 return;
197 }
198
199 mreq.imr_interface.s_addr = INADDR_ANY;
200 mreq.imr_multiaddr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
201
202 ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
203 if (ret != 0) {
204 printf("setsockopt %d", ret);
205 return;
206 }
207
208 ret = gettimeofday(&main_time, NULL);
209 if (ret != 0) {
210 printf("gettimeofday");
211 return;
212 }
213}
214
215void mrb_target_board_final()
216{
217 close(sock);
218}
219
220void mrb_target_board_break()
221{
222 raise(SIGUSR1);
223}
224
225/*
226 * アプリケーションタスクの登録
227 */
228static mrb_value mrb_target_board_wait_msg(mrb_state *mrb, mrb_value self)
229{
230 int tmr;
231 struct timeval timer, *ptimer;
232 struct timeval now, elps;
233 int ret, ret2;
234 struct udp_msg _msg;
235 struct udp_msg *msg = &_msg;
236 mrb_value arv[3];
237 fd_set readfds, writefds, errorfds;
238
239 mrb_get_args(mrb, "i", &tmr);
240
241 if (tmr < 0)
242 ptimer = NULL;
243 else {
244 timer.tv_sec = tmr / 1000;
245 timer.tv_usec = (tmr % 1000) * 1000;
246 ptimer = &timer;
247 }
248
249 FD_ZERO(&readfds);
250 FD_ZERO(&writefds);
251 FD_ZERO(&errorfds);
252 FD_SET(sock, &readfds);
253 FD_SET(sock, &writefds);
254 FD_SET(sock, &errorfds);
255
256 /* メッセージ待ち */
257 memset(msg, 0, sizeof(*msg));
258 ret = select(sock + 1, &readfds, &writefds, &errorfds, ptimer);
259 if (ret < 0)
260 mrb_raise(mrb, E_RUNTIME_ERROR, "socket select error");
261 if (FD_ISSET(sock, &readfds)) {
262 int fromlen = sizeof(msg->dst);
263 msg->len = recvfrom(sock, msg->buffer, sizeof(msg->buffer), 0, &msg->dst, &fromlen);
264 if (msg->len < 0) {
265 printf("recvfrom %d", msg->len);
266 return mrb_nil_value();
267 }
268 }
269
270 ret2 = gettimeofday(&now, NULL);
271 if (ret2 != 0) {
272 printf("gettimeofday");
273 return mrb_nil_value();
274 }
275
276 timersub(&now, &main_time, &elps);
277 arv[0] = mrb_fixnum_value(elps.tv_sec);
278 main_time = now;
279
280 /* タイムアウトの場合 */
281 if (ret == 0) {
282 return mrb_ary_new_from_values(mrb, 1, arv);
283 }
284
285 /* 内部イベントの場合 */
286 if (msg->dst.sin_addr.s_addr == 0) {
287 /* Ethernet Link up */
288 if (msg->buffer[0] & IF_FLAG_LINK_UP) {
289 arv[1] = mrb_fixnum_value(1);
290 }
291 /* EP Link up */
292 else if (msg->buffer[0] & IF_FLAG_UP) {
293 arv[1] = mrb_fixnum_value(2);
294 }
295
296 return mrb_ary_new_from_values(mrb, 2, arv);
297 }
298 /* Echonet電文受信の場合 */
299 else {
300 /* 通信端点 */
301 arv[1] = mrb_str_new(mrb, (char *)&msg->dst, sizeof(msg->dst));
302
303 /* 受信データ */
304 arv[2] = mrb_str_new(mrb, (char *)msg->buffer, msg->len);
305
306 return mrb_ary_new_from_values(mrb, 3, arv);
307 }
308}
309
310/*
311 * アプリケーションタスクの登録
312 */
313static mrb_value mrb_target_board_restart(mrb_state *mrb, mrb_value self)
314{
315 /* DHCP開始 */
316
317 return self;
318}
319
320/*
321 * 通信レイヤーへの送信
322 */
323static mrb_value mrb_target_board_snd_msg(mrb_state *mrb, mrb_value self)
324{
325 mrb_value rep;
326 mrb_value rdat;
327 struct sockaddr_in *ep;
328 int ret;
329
330 mrb_get_args(mrb, "SS", &rep, &rdat);
331
332 if (RSTRING_LEN(rep) != sizeof(struct sockaddr_in)) {
333 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
334 return mrb_nil_value();
335 }
336
337 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
338
339 ret = sendto(sock, RSTRING_PTR(rdat), RSTRING_LEN(rdat), 0, (struct sockaddr *)ep, sizeof(*ep));
340 if (ret < 0) {
341 mrb_raise(mrb, E_RUNTIME_ERROR, "sendto");
342 return mrb_nil_value();
343 }
344
345 return mrb_nil_value();
346}
347
348/*
349 * ローカルアドレスか確認
350 */
351static mrb_value mrb_target_board_is_local_addr(mrb_state *mrb, mrb_value self)
352{
353 mrb_value rep;
354 struct sockaddr_in *ep;
355
356 mrb_get_args(mrb, "S", &rep);
357
358 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
359 mrb_raise(mrb, E_RUNTIME_ERROR, "is_local_addr");
360 return mrb_nil_value();
361 }
362
363 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
364
365 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(127, 0, 0, 1)) ? mrb_true_value() : mrb_false_value();
366}
367
368/*
369 * マルチキャストアドレスか確認
370 */
371static mrb_value mrb_target_board_is_multicast_addr(mrb_state *mrb, mrb_value self)
372{
373 mrb_value rep;
374 struct sockaddr_in *ep;
375
376 mrb_get_args(mrb, "S", &rep);
377
378 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
379 mrb_raise(mrb, E_RUNTIME_ERROR, "is_multicast_addr");
380 return mrb_nil_value();
381 }
382
383 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
384
385 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(224, 0, 23, 0)) ? mrb_true_value() : mrb_false_value();
386}
387
388/*
389 * 同一アドレスか確認
390 */
391static mrb_value mrb_target_board_equals_addr(mrb_state *mrb, mrb_value self)
392{
393 mrb_value rep1, rep2;
394 struct sockaddr_in *ep1, *ep2;
395
396 mrb_get_args(mrb, "SS", &rep1, &rep2);
397
398 if ((RSTRING_LEN(rep1) != sizeof(struct sockaddr_in)) || (RSTRING_LEN(rep2) != sizeof(struct sockaddr_in))) {
399 mrb_raise(mrb, E_RUNTIME_ERROR, "equals_addr");
400 return mrb_nil_value();
401 }
402
403 ep1 = (struct sockaddr_in *)RSTRING_PTR(rep1);
404 ep2 = (struct sockaddr_in *)RSTRING_PTR(rep2);
405
406 return (ep1->sin_addr.s_addr == ep2->sin_addr.s_addr) ? mrb_true_value() : mrb_false_value();
407}
408
409/*
410 * ローカルアドレスの取得
411 */
412static mrb_value mrb_target_board_get_local_addr(mrb_state *mrb, mrb_value self)
413{
414 struct sockaddr_in ep;
415 mrb_value rep;
416
417 memset(&ep, 0, sizeof(ep));
418 ep.sin_family = AF_INET;
419 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(127, 0, 0, 1);
420 ep.sin_port = htons(3610);
421
422 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
423
424 return rep;
425}
426
427/*
428 * マルチキャストアドレスの取得
429 */
430static mrb_value mrb_target_board_get_multicast_addr(mrb_state *mrb, mrb_value self)
431{
432 struct sockaddr_in ep;
433 mrb_value rep;
434
435 memset(&ep, 0, sizeof(ep));
436 ep.sin_family = AF_INET;
437 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
438 ep.sin_port = htons(3610);
439
440 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
441
442 return rep;
443}
444
445void mrb_mruby_others_gem_init(mrb_state* mrb)
446{
447 if (!echonet)
448 return;
449
450 _module_target_board = mrb_define_module(mrb, "TargetBoard");
451
452 mrb_define_class_method(mrb, _module_target_board, "wait_msg", mrb_target_board_wait_msg, MRB_ARGS_REQ(1));
453 mrb_define_class_method(mrb, _module_target_board, "restart", mrb_target_board_restart, MRB_ARGS_NONE());
454 mrb_define_class_method(mrb, _module_target_board, "snd_msg", mrb_target_board_snd_msg, MRB_ARGS_REQ(2));
455 mrb_define_class_method(mrb, _module_target_board, "is_local_addr", mrb_target_board_is_local_addr, MRB_ARGS_REQ(1));
456 mrb_define_class_method(mrb, _module_target_board, "is_multicast_addr", mrb_target_board_is_multicast_addr, MRB_ARGS_REQ(1));
457 mrb_define_class_method(mrb, _module_target_board, "equals_addr", mrb_target_board_equals_addr, MRB_ARGS_REQ(2));
458 mrb_define_class_method(mrb, _module_target_board, "get_local_addr", mrb_target_board_get_local_addr, MRB_ARGS_NONE());
459 mrb_define_class_method(mrb, _module_target_board, "get_multicast_addr", mrb_target_board_get_multicast_addr, MRB_ARGS_NONE());
460
461 mrb_target_board_init();
462}
463
464void mrb_mruby_others_gem_final(mrb_state* mrb)
465{
466 if (!echonet)
467 return;
468
469 mrb_target_board_final();
470}
471
472extern char __start_rodata, __end_rodata;
473
474mrb_bool mrb_ro_data_p(const char *p)
475{
476 return (&__start_rodata <= p && p < &__end_rodata);
477}
Note: See TracBrowser for help on using the repository browser.