source: EcnlProtoTool/trunk/asp3_dcre/sample/sample1n.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: 15.7 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者
8は,以下の (1)~(4) の条件か,Free Software Foundation
9 * によってå…
10¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
14 * 利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22 * 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24 * の無保証規定を掲載すること.
25 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26 * 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®æ¡ä»¶ã‚’満たすこと.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
33 * 害からも,上記著作権者
34およびTOPPERSプロジェクトをå…
35è²¬ã™ã‚‹ã“と.
36 *
37 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
38お
39 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
42 *
43 * @(#) $Id: sample1n.c 270 2017-02-09 04:03:47Z coas-nagasima $
44 */
45
46/*
47 * ネットワーク化サンプルプログラム(1)の本体
48 */
49
50#include <stdarg.h>
51
52#include <kernel.h>
53#include <t_syslog.h>
54#include "syssvc/serial.h"
55#include "kernel_cfg.h"
56#include "tinet_cfg.h"
57
58#include <netinet/in.h>
59#include <netinet/in_itron.h>
60
61#include "sample1n.h"
62
63/*
64 * マクロ定義
65 */
66
67/* リネームの解除 */
68
69#undef syslog
70#undef serial_rea_dat
71#undef serial_ctl_por
72
73#define EOF (-1)
74
75/* TELNET オプション */
76
77#define TELNET_OPT_SE (240)
78#define TELNET_OPT_NOP (241)
79#define TELNET_OPT_DM (242)
80#define TELNET_OPT_BRK (243)
81#define TELNET_OPT_IP (244)
82#define TELNET_OPT_AO (245)
83#define TELNET_OPT_AYT (246)
84#define TELNET_OPT_EC (247)
85#define TELNET_OPT_EL (248)
86#define TELNET_OPT_GA (249)
87#define TELNET_OPT_SB (250)
88#define TELNET_OPT_WILL (251)
89#define TELNET_OPT_WONT (252)
90#define TELNET_OPT_DO (253)
91#define TELNET_OPT_DONT (254)
92#define TELNET_OPT_IAC (255)
93
94/*
95 * 変数
96 */
97
98/* TCP 送受信ウィンドバッファ */
99
100uint8_t tcp_swbuf[TCP_SWBUF_SIZE];
101uint8_t tcp_rwbuf[TCP_RWBUF_SIZE];
102
103bool_t connected = false; /* コネクションの状æ…
104‹ */
105bool_t wait_accept = false; /* 接続要求待
106ち中 */
107
108#ifdef SUPPORT_INET4
109
110T_IPV4EP dst;
111
112#endif /* of #ifdef SUPPORT_INET4 */
113
114#ifdef SUPPORT_INET6
115
116T_IPV6EP dst;
117
118#endif /* of #ifdef SUPPORT_INET6 */
119
120uint8_t *snd_buff = NULL;
121uint8_t *rcv_buff = NULL;
122uint_t snd_off = 0;
123uint_t rcv_off = 0;
124ER_UINT snd_len = 0;
125ER_UINT rcv_len = 0;
126uint_t net_ioctl = IOCTL_NULL;
127uint8_t addr[sizeof("0123:4567:89ab:cdef:0123:4567:89ab:cdef")];
128
129/*
130 * ネットワーク層の選択
131 */
132
133#ifdef SUPPORT_INET4
134
135#define TCP_ACP_CEP(c,r,d,t) tcp_acp_cep(c,r,d,t)
136#define IP2STR(s,a) ip2str(s,a)
137
138#endif /* of #ifdef SUPPORT_INET4 */
139
140#ifdef SUPPORT_INET6
141
142#define TCP_ACP_CEP(c,r,d,t) tcp6_acp_cep(c,r,d,t)
143#define IP2STR(s,a) ipv62str(s,a)
144
145#endif /* of #ifdef SUPPORT_INET6 */
146
147/*
148 * ノンブロッキングコールのコールバック関数
149 */
150
151ER
152callback_nblk_tcp (ID cepid, FN fncd, void *p_parblk)
153{
154 ER error = E_OK;
155
156 switch (fncd) {
157
158 case TFN_TCP_ACP_CEP:
159 IP2STR(addr, &dst.ipaddr);
160 syslog(LOG_NOTICE, "connected: %s.%d", addr, dst.portno);
161 if (*(ER*)p_parblk == E_OK)
162 connected = true;
163 snd_len = snd_off = rcv_len = rcv_off = 0;
164 wait_accept = false;
165 break;
166
167 case TFN_TCP_CLS_CEP:
168 case TFN_TCP_RCV_BUF:
169 case TFN_TCP_GET_BUF:
170 case TFN_TCP_RCV_DAT:
171 case TFN_TCP_SND_DAT:
172 case TFN_TCP_CON_CEP:
173 case TFN_TCP_SND_OOB:
174 default:
175 error = E_PAR;
176 break;
177 }
178 return error;
179 }
180
181/*
182 * コネクションを切断
183 */
184
185ER
186disconnecting (void)
187{
188 ER error = E_OK;
189
190 if (connected) {
191 syscall(wai_sem(SEM_NET_SEND));
192 if (snd_off > 0)
193 tcp_snd_buf(TCP_CEPID, snd_off);
194 tcp_sht_cep(TCP_CEPID);
195 tcp_cls_cep(TCP_CEPID, TMO_FEVR);
196 connected = false;
197 syscall(sig_sem(SEM_NET_SEND));
198 IP2STR(addr, &dst.ipaddr);
199 syslog(LOG_NOTICE, "disconnected: %s.%d", addr, dst.portno);
200 }
201 return error;
202 }
203
204/*
205 * 送信バッファのフラッシュ
206 */
207
208void
209flush_snd_buff (ID cepid)
210{
211 if (connected) {
212 syscall(wai_sem(SEM_NET_SEND));
213 if (snd_off > 0) {
214 tcp_snd_buf(cepid, snd_off);
215 snd_len = snd_off = 0;
216 }
217 syscall(sig_sem(SEM_NET_SEND));
218 }
219 return;
220 }
221
222/*
223 * 文字送信
224 */
225
226void
227put_char (ID cepid, char ch)
228{
229 if (connected) {
230 if (ch == '\n' && (net_ioctl & IOCTL_CRLF) != 0)
231 put_char(cepid, '\r');
232 syscall(wai_sem(SEM_NET_SEND));
233 if (snd_off >= snd_len) {
234 if (tcp_snd_buf(cepid, snd_off) != E_OK) {
235 syscall(sig_sem(SEM_NET_SEND));
236 return;
237 }
238 snd_off = 0;
239 if ((snd_len = tcp_get_buf(cepid, (void**)&snd_buff, TMO_FEVR)) <= 0) {
240 syscall(sig_sem(SEM_NET_SEND));
241 return;
242 }
243 }
244 snd_buff[snd_off ++] = ch;
245 syscall(sig_sem(SEM_NET_SEND));
246 }
247 }
248
249/*
250 * 文字受信(変換なし)
251 */
252
253int_t
254get_char_raw (ID cepid)
255{
256 if (connected) {
257 if (rcv_off >= rcv_len) {
258 rcv_off = 0;
259 if (tcp_rel_buf(TCP_CEPID, rcv_len) != E_OK) {
260 disconnecting();
261 return EOF;
262 }
263 if ((rcv_len = tcp_rcv_buf(TCP_CEPID, (void**)&rcv_buff, TMO_FEVR)) == 0) {
264 disconnecting();
265 return EOF;
266 }
267 else if (rcv_len < 0) {
268 disconnecting();
269 return EOF;
270 }
271 }
272 return rcv_buff[rcv_off ++];
273 }
274 else
275 return EOF;
276 }
277
278/*
279 * 文字受信(TELNET オプションをスキップ)
280 */
281
282int_t
283get_char (ID cepid)
284{
285 int_t ch, req;
286
287 while ((ch = get_char_raw(cepid)) == TELNET_OPT_IAC || ch == '\0') {
288 if (ch != '\0') {
289 switch (ch = get_char_raw(cepid)) {
290 case TELNET_OPT_WILL:
291 case TELNET_OPT_WONT:
292 case TELNET_OPT_DO:
293 case TELNET_OPT_DONT:
294 req = get_char_raw(cepid);
295 break;
296 case TELNET_OPT_SB:
297 while ((ch = get_char_raw(cepid)) != EOF && ch != TELNET_OPT_IAC) {
298 if ((ch = get_char_raw(cepid)) == EOF || ch == TELNET_OPT_SE)
299 break;
300 }
301 break;
302 default:
303 break;
304 }
305 }
306 }
307 return ch;
308 }
309
310/*
311 * シリアルポートからの読出し
312 */
313
314ER_UINT
315net_serial_rea_dat (ID portid, char *buf, uint_t len)
316{
317 T_SERIAL_RPOR rpor;
318 uint_t off;
319 int_t ch;
320
321 if (!wait_accept && !connected) {
322 wait_accept = true;
323 if (TCP_ACP_CEP(TCP_CEPID, TCP_REPID, &dst, TMO_NBLK) != E_WBLK)
324 return 0;
325 }
326
327 while (true) {
328 if (connected) {
329 off = 0;
330 while (off < len && (ch = get_char(TCP_CEPID)) != EOF) {
331 *(buf + off ++) = ch;
332 if ((net_ioctl & IOCTL_ECHO) != 0) {
333 put_char(TCP_CEPID, ch);
334 flush_snd_buff(TCP_CEPID);
335 }
336 }
337 return off;
338 }
339 else if (serial_ref_por(portid, &rpor) == E_OK && rpor.reacnt > 0) {
340 return serial_rea_dat(portid, buf, len);
341 }
342 dly_tsk(500);
343 }
344 return off;
345 }
346
347/*
348 * シリアルポートの制御
349 */
350
351ER
352net_serial_ctl_por (ID portid, uint_t ioctl)
353{
354 net_ioctl = ioctl;
355 return serial_ctl_por(portid, ioctl);
356 }
357
358/*
359 * もっとも長い整数型 (LONGEST) と符号なし整数型 (ULONGEST)
360 */
361
362#ifdef LONGLONG_TYPE
363
364typedef LONGLONG_TYPE LONGEST;
365typedef unsigned LONGLONG_TYPE ULONGEST;
366
367#else /* of #ifdef LONGLONG_TYPE */
368
369#ifdef LONG_TYPE
370
371typedef LONG_TYPE LONGEST;
372typedef unsigned LONG_TYPE ULONGEST;
373
374#else /* of #ifdef LONG_TYPE */
375
376typedef int_t LONGEST;
377typedef uint_t ULONGEST;
378
379#endif /* of #ifdef LONG_TYPE */
380
381#endif /* of #ifdef LONGLONG_TYPE */
382
383/*
384 * ログのシミュレーション
385 */
386
387/* 数値変換のための変換表 */
388
389static const char radhex[] = "0123456789abcdef";
390static const char radHEX[] = "0123456789ABCDEF";
391
392/*
393 * put_num -- printf の数値変換
394 */
395
396int_t
397put_num(ID cepid, ULONGEST val, int_t radix, const char *radchar, int_t width, bool_t minus, char padchar)
398{
399 char digits[24];
400 int_t ix, pad, pchars;
401 bool_t left;
402
403 if (width < 0) {
404 width = -width;
405 left = true;
406 }
407 else
408 left = false;
409
410 ix = 0;
411 do {
412 digits[ix ++] = radchar[val % radix];
413 val /= radix;
414 } while (val != 0);
415
416 if (minus)
417 digits[ix ++] = '-';
418
419 if (width > ix)
420 pchars = width;
421 else
422 pchars = ix;
423
424 pad = ix;
425 if (!left) /* 右詰め */
426 for ( ; pad < width; pad ++)
427 put_char(cepid, padchar);
428
429 while (ix -- > 0)
430 put_char(cepid, digits[ix]);
431
432 if (left) /* 左詰め */
433 for ( ; pad < width; pad ++)
434 put_char(cepid, padchar);
435
436 return pchars;
437 }
438
439#ifdef SUPPORT_INET4
440
441/*
442 * put_ipv4addr -- IPv4 アドレス出力
443 */
444
445static int_t
446put_ipv4addr (ID cepid, ULONGEST *addr, int_t width)
447{
448 int_t len = 3; /* 3 は '.' の文字数 */
449
450#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
451
452 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
453 put_char(cepid, '.');
454 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
455 put_char(cepid, '.');
456 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
457 put_char(cepid, '.');
458 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
459
460#else /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
461
462 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
463 put_char(cepid, '.');
464 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
465 put_char(cepid, '.');
466 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
467 put_char(cepid, '.');
468 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
469
470#endif /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
471
472 for ( ; len < width; len ++)
473 put_char(cepid, ' ');
474
475 return len;
476 }
477
478#define PUT_IPADDR(p,a,w) put_ipv4addr(p,a,w)
479
480#endif /* of #ifdef SUPPORT_INET4 */
481
482#ifdef SUPPORT_INET6
483
484/*
485 * ipv6addr -- IPv6 アドレス出力
486 */
487
488static int_t
489put_ipv6addr (ID cepid, const T_IN6_ADDR *addr, int_t width)
490{
491 int_t len = 0, ix;
492 bool_t omit = false, zero = false;
493
494 if (addr == NULL) {
495 put_char(cepid, '0');
496 put_char(cepid, ':');
497 put_char(cepid, ':');
498 put_char(cepid, '0');
499 len = 4;
500 }
501 else {
502 for (ix = 0; ix < sizeof(T_IN6_ADDR) / 2; ix ++) {
503 if (omit) {
504 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
505 if (ix < 7) {
506 put_char(cepid, ':');
507 len ++;
508 }
509 }
510 else if (ix > 0 && ix < 7 && addr->s6_addr16[ix] == 0)
511 zero = true;
512 else {
513 if (zero) {
514 omit = true;
515 put_char(cepid, ':');
516 len ++;
517 }
518 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
519 if (ix < 7) {
520 put_char(cepid, ':');
521 len ++;
522 }
523 }
524 }
525
526 for ( ; len < width; len ++)
527 put_char(cepid, ' ');
528 }
529 return len;
530 }
531
532#define PUT_IPADDR(p,a,w) put_ipv6addr(p,a,w)
533
534#endif /* of #ifdef SUPPORT_INET6 */
535
536/*
537 * put_macaddr -- MAC アドレス出力
538 */
539
540static int_t
541put_macaddr (ID cepid, char *mac, int_t width)
542{
543 int_t oct, len;
544
545 for (oct = 5; oct -- > 0; ) {
546 put_num(cepid, *mac ++, 16, radhex, 2, false, '0');
547 put_char(cepid, ':');
548 }
549 put_num(cepid, *mac, 16, radhex, 2, false, '0');
550
551 for (len = 17; len < width; len ++)
552 put_char(cepid, ' ');
553
554 return len;
555 }
556
557/*
558 * 引数を取り出すためのマクロ
559 */
560
561#ifdef LONGLONG_TYPE
562
563#ifdef LONG_TYPE
564
565#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
566 (lf ? va_arg(ap, LONG_TYPE) \
567 : va_arg(ap, int_t)))
568
569#else /* of #ifdef LONG_TYPE */
570
571#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
572 : va_arg(ap, int_t))
573
574#endif /* of #ifdef LONG_TYPE */
575
576#else /* of #ifdef LONGLONG_TYPE */
577
578#ifdef LONG_TYPE
579
580#define GET_ARG(ap,lf) (lf ? va_arg(ap, LONG_TYPE) \
581 : va_arg(ap, int_t))
582
583#else /* of #ifdef LONG_TYPE */
584
585#define GET_ARG(ap,lf) (va_arg(ap, int_t))
586
587#endif /* of #ifdef LONG_TYPE */
588
589#endif /* of #ifdef LONGLONG_TYPE */
590
591/*
592 * ログ出力
593 */
594
595void
596net_syslog (uint_t prio, const char *format, ...)
597{
598 LONGEST val;
599 SYSLOG log;
600 va_list ap;
601 char padchar, *str;
602 int_t ch, width, longflag, left, i, c;
603
604 if (connected) {
605 syscall(wai_sem(SEM_TCP_SYSLOG));
606 va_start(ap, format);
607 while ((ch = *format ++) != '\0') {
608 if (ch != '%') { /* 書式指定以外 */
609 put_char(TCP_CEPID, (char)ch);
610 continue;
611 }
612
613 width = longflag = 0;
614 padchar = ' ';
615
616 if (ch == '-') { /* 左詰め */
617 format ++;
618 left = -1;
619 }
620 else
621 left = 1;
622
623 if ((ch = *format ++) == '0') { /* 上位桁の 0 */
624 padchar = '0';
625 ch = *format ++;
626 }
627
628 while ('0' <= ch && ch <= '9') { /* 出力幅
629 */
630 width = width * 10 + ch - '0';
631 ch = *format ++;
632 }
633
634 while (ch == 'l') { /* long (long) の指定 */
635 longflag ++;
636 ch = *format ++;
637 }
638
639 switch (ch) {
640 case 'd':
641 val = GET_ARG(ap, longflag);
642 if (val >= 0)
643 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
644 else
645 put_num(TCP_CEPID, -val, 10, radhex, width * left, true, padchar);
646 break;
647
648 case 'u':
649 val = GET_ARG(ap, longflag);
650 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
651 break;
652
653 case 'x':
654 val = GET_ARG(ap, longflag);
655 put_num(TCP_CEPID, val, 16, radhex, width * left, false, padchar);
656 break;
657
658 case 'X':
659 val = GET_ARG(ap, longflag);
660 put_num(TCP_CEPID, val, 16, radHEX, width * left, false, padchar);
661 break;
662
663 case 'c':
664 ch = va_arg(ap, int_t);
665 put_char(TCP_CEPID, (char)ch);
666 break;
667
668 case 's':
669 str = va_arg(ap, char*);
670 while ((ch = *str ++) != '\0') {
671 put_char(TCP_CEPID, (char)ch);
672 width --;
673 }
674 while (width -- > 0)
675 put_char(TCP_CEPID, ' ');
676 break;
677
678 case 'I':
679
680#ifdef SUPPORT_INET4
681
682 val = GET_ARG(ap, longflag);
683 put_ipv4addr(TCP_CEPID, (ULONGEST *)val, width);
684
685#endif /* of #ifdef SUPPORT_INET4 */
686
687#ifdef SUPPORT_INET6
688
689 str = va_arg(ap, char*);
690 put_ipv6addr(TCP_CEPID, (T_IN6_ADDR *)str, width);
691
692#endif /* of #ifdef SUPPORT_INET6 */
693
694 break;
695
696 case 'M':
697 str = va_arg(ap, char*);
698 put_macaddr(TCP_CEPID, str, width);
699 break;
700
701 case '%':
702 put_char(TCP_CEPID, '%');
703 break;
704
705 case '0':
706 format --;
707 break;
708
709 default:
710 break;
711 }
712
713 }
714 va_end(ap);
715 put_char(TCP_CEPID, '\n');
716 flush_snd_buff(TCP_CEPID);
717 syscall(sig_sem(SEM_TCP_SYSLOG));
718 return E_OK;
719 }
720 else {
721 log.logtype = LOG_TYPE_COMMENT;
722 log.logpar[0] = (intptr_t)format;
723 i = 1;
724 va_start(ap, format);
725
726 while ((c = *format++) != '\0' && i < TNUM_LOGPAR) {
727 if (c != '%') {
728 continue;
729 }
730
731 c = *format++;
732 while ('0' <= c && c <= '9') {
733 c = *format++;
734 }
735 switch (c) {
736 case 'd':
737 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
738 break;
739 case 'u':
740 case 'x':
741 case 'X':
742 log.logpar[i++] = (intptr_t)va_arg(ap, uint_t);
743 break;
744 case 'p':
745 log.logpar[i++] = (intptr_t)va_arg(ap, void *);
746 break;
747 case 'c':
748 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
749 break;
750 case 's':
751 log.logpar[i++] = (intptr_t)va_arg(ap, const char *);
752 break;
753 case '\0':
754 format--;
755 break;
756 default:
757 break;
758 }
759 }
760 va_end(ap);
761 syslog_wri_log(prio, &log);
762 return;
763 }
764 }
Note: See TracBrowser for help on using the repository browser.