source: asp3_gr_sakura/trunk/sample/sample1n.c@ 317

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

GR-SAKURA向けASP3を追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 16.2 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2012 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 317 2017-08-03 13:14:26Z coas-nagasima $
44 */
45
46/*
47 * ネットワーク化サンプルプログラム(1)の本体
48 */
49
50#include <stdarg.h>
51
52#include <kernel.h>
53#include "syssvc/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_INET6
109
110T_IPV6EP dst;
111
112#else /* of #ifdef SUPPORT_INET6 */
113
114#ifdef SUPPORT_INET4
115
116T_IPV4EP dst;
117
118#endif /* of #ifdef SUPPORT_INET4 */
119
120#endif /* of #ifdef SUPPORT_INET6 */
121
122uint8_t *snd_buff = NULL;
123uint8_t *rcv_buff = NULL;
124uint_t snd_off = 0;
125uint_t rcv_off = 0;
126ER_UINT snd_len = 0;
127ER_UINT rcv_len = 0;
128uint_t net_ioctl = IOCTL_NULL;
129uint8_t addr[sizeof("0123:4567:89ab:cdef:0123:4567:89ab:cdef")];
130
131/*
132 * ネットワーク層の選択
133 */
134
135#ifdef SUPPORT_INET6
136
137#define TCP_ACP_CEP(c,r,d,t) tcp6_acp_cep(c,r,d,t)
138#define IP2STR(s,a) ipv62str(s,a)
139
140#else /* of #ifdef SUPPORT_INET6 */
141
142#ifdef SUPPORT_INET4
143
144#define TCP_ACP_CEP(c,r,d,t) tcp_acp_cep(c,r,d,t)
145#define IP2STR(s,a) ip2str(s,a)
146
147#endif /* of #ifdef SUPPORT_INET4 */
148
149#endif /* of #ifdef SUPPORT_INET6 */
150
151/*
152 * ノンブロッキングコールのコールバック関数
153 */
154
155ER
156callback_nblk_tcp (ID cepid, FN fncd, void *p_parblk)
157{
158 ER error = E_OK;
159
160 switch (fncd) {
161
162 case TFN_TCP_ACP_CEP:
163 IP2STR((char *)addr, &dst.ipaddr);
164 syslog(LOG_NOTICE, "connected: %s.%d", addr, dst.portno);
165 if (*(ER*)p_parblk == E_OK)
166 connected = true;
167 snd_len = snd_off = rcv_len = rcv_off = 0;
168 wait_accept = false;
169 break;
170
171 case TFN_TCP_CLS_CEP:
172 case TFN_TCP_RCV_BUF:
173 case TFN_TCP_GET_BUF:
174 case TFN_TCP_RCV_DAT:
175 case TFN_TCP_SND_DAT:
176 case TFN_TCP_CON_CEP:
177 case TFN_TCP_SND_OOB:
178 default:
179 error = E_PAR;
180 break;
181 }
182 return error;
183 }
184
185/*
186 * コネクションを切断
187 */
188
189ER
190disconnecting (void)
191{
192 ER error = E_OK;
193
194 if (connected) {
195 syscall(wai_sem(SEM_NET_SEND));
196 if (snd_off > 0)
197 tcp_snd_buf(TCP_CEPID, snd_off);
198 tcp_sht_cep(TCP_CEPID);
199 tcp_cls_cep(TCP_CEPID, TMO_FEVR);
200 connected = false;
201 syscall(sig_sem(SEM_NET_SEND));
202 IP2STR((char *)addr, &dst.ipaddr);
203 syslog(LOG_NOTICE, "disconnected: %s.%d", addr, dst.portno);
204 }
205 return error;
206 }
207
208/*
209 * 送信バッファのフラッシュ
210 */
211
212void
213flush_snd_buff (ID cepid)
214{
215 if (connected) {
216 syscall(wai_sem(SEM_NET_SEND));
217 if (snd_off > 0) {
218 tcp_snd_buf(cepid, snd_off);
219 snd_len = snd_off = 0;
220 }
221 syscall(sig_sem(SEM_NET_SEND));
222 }
223 return;
224 }
225
226/*
227 * 文字送信
228 */
229
230void
231put_char (ID cepid, char ch)
232{
233 if (connected) {
234 if (ch == '\n' && (net_ioctl & IOCTL_CRLF) != 0)
235 put_char(cepid, '\r');
236 syscall(wai_sem(SEM_NET_SEND));
237 if (snd_off >= snd_len) {
238 if (tcp_snd_buf(cepid, snd_off) != E_OK) {
239 syscall(sig_sem(SEM_NET_SEND));
240 return;
241 }
242 snd_off = 0;
243 if ((snd_len = tcp_get_buf(cepid, (void**)&snd_buff, TMO_FEVR)) <= 0) {
244 syscall(sig_sem(SEM_NET_SEND));
245 return;
246 }
247 }
248 snd_buff[snd_off ++] = ch;
249 syscall(sig_sem(SEM_NET_SEND));
250 }
251 }
252
253/*
254 * 文字受信(変換なし)
255 */
256
257int_t
258get_char_raw (ID cepid)
259{
260 if (connected) {
261 if (rcv_off >= rcv_len) {
262 rcv_off = 0;
263 if (tcp_rel_buf(TCP_CEPID, rcv_len) != E_OK) {
264 disconnecting();
265 return EOF;
266 }
267 if ((rcv_len = tcp_rcv_buf(TCP_CEPID, (void**)&rcv_buff, TMO_FEVR)) == 0) {
268 disconnecting();
269 return EOF;
270 }
271 else if (rcv_len < 0) {
272 disconnecting();
273 return EOF;
274 }
275 }
276 return rcv_buff[rcv_off ++];
277 }
278 else
279 return EOF;
280 }
281
282/*
283 * 文字受信(TELNET オプションをスキップ)
284 */
285
286int_t
287get_char (ID cepid)
288{
289 int_t ch, req;
290
291 while ((ch = get_char_raw(cepid)) == TELNET_OPT_IAC || ch == '\0') {
292 if (ch != '\0') {
293 switch (ch = get_char_raw(cepid)) {
294 case TELNET_OPT_WILL:
295 case TELNET_OPT_WONT:
296 case TELNET_OPT_DO:
297 case TELNET_OPT_DONT:
298 req = get_char_raw(cepid);
299 break;
300 case TELNET_OPT_SB:
301 while ((ch = get_char_raw(cepid)) != EOF && ch != TELNET_OPT_IAC) {
302 if ((ch = get_char_raw(cepid)) == EOF || ch == TELNET_OPT_SE)
303 break;
304 }
305 break;
306 default:
307 break;
308 }
309 }
310 }
311 return ch;
312 }
313
314/*
315 * シリアルポートからの読出し
316 */
317
318ER_UINT
319net_serial_rea_dat (ID portid, char *buf, uint_t len)
320{
321 T_SERIAL_RPOR rpor;
322 uint_t off;
323 int_t ch;
324
325 if (!wait_accept && !connected) {
326 wait_accept = true;
327 if (TCP_ACP_CEP(TCP_CEPID, TCP_REPID, &dst, TMO_NBLK) != E_WBLK)
328 return 0;
329 }
330
331 while (true) {
332 if (connected) {
333 off = 0;
334 while (off < len && (ch = get_char(TCP_CEPID)) != EOF) {
335 *(buf + off ++) = ch;
336 if ((net_ioctl & IOCTL_ECHO) != 0) {
337 put_char(TCP_CEPID, ch);
338 flush_snd_buff(TCP_CEPID);
339 }
340 }
341 return off;
342 }
343 else if (serial_ref_por(portid, &rpor) == E_OK && rpor.reacnt > 0) {
344 return serial_rea_dat(portid, buf, len);
345 }
346 dly_tsk(500000);
347 }
348 return off;
349 }
350
351/*
352 * シリアルポートの制御
353 */
354
355ER
356net_serial_ctl_por (ID portid, uint_t ioctl)
357{
358 net_ioctl = ioctl;
359 return serial_ctl_por(portid, ioctl);
360 }
361
362/*
363 * もっとも長い整数型 (LONGEST) と符号なし整数型 (ULONGEST)
364 */
365
366#ifdef LONGLONG_TYPE
367
368typedef LONGLONG_TYPE LONGEST;
369typedef unsigned LONGLONG_TYPE ULONGEST;
370
371#else /* of #ifdef LONGLONG_TYPE */
372
373#ifdef LONG_TYPE
374
375typedef LONG_TYPE LONGEST;
376typedef unsigned LONG_TYPE ULONGEST;
377
378#else /* of #ifdef LONG_TYPE */
379
380typedef int_t LONGEST;
381typedef uint_t ULONGEST;
382
383#endif /* of #ifdef LONG_TYPE */
384
385#endif /* of #ifdef LONGLONG_TYPE */
386
387/*
388 * ログのシミュレーション
389 */
390
391/* 数値変換のための変換表 */
392
393static const char radhex[] = "0123456789abcdef";
394static const char radHEX[] = "0123456789ABCDEF";
395
396/*
397 * put_num -- printf の数値変換
398 */
399
400int_t
401put_num(ID cepid, ULONGEST val, int_t radix, const char *radchar, int_t width, bool_t minus, char padchar)
402{
403 char digits[24];
404 int_t ix, pad, pchars;
405 bool_t left;
406
407 if (width < 0) {
408 width = -width;
409 left = true;
410 }
411 else
412 left = false;
413
414 ix = 0;
415 do {
416 digits[ix ++] = radchar[val % radix];
417 val /= radix;
418 } while (val != 0);
419
420 if (minus)
421 digits[ix ++] = '-';
422
423 if (width > ix)
424 pchars = width;
425 else
426 pchars = ix;
427
428 pad = ix;
429 if (!left) /* 右詰め */
430 for ( ; pad < width; pad ++)
431 put_char(cepid, padchar);
432
433 while (ix -- > 0)
434 put_char(cepid, digits[ix]);
435
436 if (left) /* 左詰め */
437 for ( ; pad < width; pad ++)
438 put_char(cepid, padchar);
439
440 return pchars;
441 }
442
443/*
444 * ipv6addr -- IPv6 アドレス出力
445 */
446
447int_t
448put_ipv6addr (ID cepid, const T_IN6_ADDR *addr, int_t width)
449{
450 int_t len = 0, ix;
451 bool_t omit = false, zero = false;
452
453 if (addr == NULL) {
454 put_char(cepid, '0');
455 put_char(cepid, ':');
456 put_char(cepid, ':');
457 put_char(cepid, '0');
458 len = 4;
459 }
460 else {
461 for (ix = 0; ix < sizeof(T_IN6_ADDR) / 2; ix ++) {
462 if (omit) {
463 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
464 if (ix < 7) {
465 put_char(cepid, ':');
466 len ++;
467 }
468 }
469 else if (ix > 0 && ix < 7 && addr->s6_addr16[ix] == 0)
470 zero = true;
471 else {
472 if (zero) {
473 omit = true;
474 put_char(cepid, ':');
475 len ++;
476 }
477 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
478 if (ix < 7) {
479 put_char(cepid, ':');
480 len ++;
481 }
482 }
483 }
484
485 for ( ; len < width; len ++)
486 put_char(cepid, ' ');
487 }
488 return len;
489 }
490
491/*
492 * put_ipv4addr -- IPv4 アドレス出力
493 */
494
495int_t
496put_ipv4addr (ID cepid, ULONGEST *addr, int_t width)
497{
498 int_t len = 3; /* 3 は '.' の文字数 */
499
500#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
501
502 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
503 put_char(cepid, '.');
504 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
505 put_char(cepid, '.');
506 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
507 put_char(cepid, '.');
508 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
509
510#else /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
511
512 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
513 put_char(cepid, '.');
514 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
515 put_char(cepid, '.');
516 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
517 put_char(cepid, '.');
518 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
519
520#endif /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
521
522 for ( ; len < width; len ++)
523 put_char(cepid, ' ');
524
525 return len;
526 }
527
528/*
529 * put_macaddr -- MAC アドレス出力
530 */
531
532static int_t
533put_macaddr (ID cepid, char *mac, int_t width)
534{
535 int_t oct, len;
536
537 for (oct = 5; oct -- > 0; ) {
538 put_num(cepid, *mac ++, 16, radhex, 2, false, '0');
539 put_char(cepid, ':');
540 }
541 put_num(cepid, *mac, 16, radhex, 2, false, '0');
542
543 for (len = 17; len < width; len ++)
544 put_char(cepid, ' ');
545
546 return len;
547 }
548
549/*
550 * 引数を取り出すためのマクロ
551 */
552
553#ifdef LONGLONG_TYPE
554
555#ifdef LONG_TYPE
556
557#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
558 (lf ? va_arg(ap, LONG_TYPE) \
559 : va_arg(ap, int_t)))
560
561#else /* of #ifdef LONG_TYPE */
562
563#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
564 : va_arg(ap, int_t))
565
566#endif /* of #ifdef LONG_TYPE */
567
568#else /* of #ifdef LONGLONG_TYPE */
569
570#ifdef LONG_TYPE
571
572#define GET_ARG(ap,lf) (lf ? va_arg(ap, LONG_TYPE) \
573 : va_arg(ap, int_t))
574
575#else /* of #ifdef LONG_TYPE */
576
577#define GET_ARG(ap,lf) (va_arg(ap, int_t))
578
579#endif /* of #ifdef LONG_TYPE */
580
581#endif /* of #ifdef LONGLONG_TYPE */
582
583/*
584 * ログ出力
585 */
586
587void
588net_syslog (uint_t prio, const char *format, ...)
589{
590 LONGEST val;
591 SYSLOG log;
592 va_list ap;
593 char padchar, *str;
594 int_t ch, width, longflag, shortflag, left, i, c;
595
596 if (connected) {
597 syscall(wai_sem(SEM_TCP_SYSLOG));
598 va_start(ap, format);
599 while ((ch = *format ++) != '\0') {
600 if (ch != '%') { /* 書式指定以外 */
601 put_char(TCP_CEPID, (char)ch);
602 continue;
603 }
604
605 width = longflag = shortflag = 0;
606 padchar = ' ';
607
608 if (ch == '-') { /* 左詰め */
609 format ++;
610 left = -1;
611 }
612 else
613 left = 1;
614
615 if ((ch = *format ++) == '0') { /* 上位桁の 0 */
616 padchar = '0';
617 ch = *format ++;
618 }
619
620 while ('0' <= ch && ch <= '9') { /* 出力幅
621 */
622 width = width * 10 + ch - '0';
623 ch = *format ++;
624 }
625
626 while (ch == 'l') { /* long (long) の指定 */
627 longflag ++;
628 ch = *format ++;
629 }
630
631 while (ch == 'h') { /* short の指定 */
632 shortflag ++;
633 ch = *format ++;
634 }
635
636 switch (ch) {
637 case 'd':
638 val = GET_ARG(ap, longflag);
639 if (val >= 0)
640 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
641 else
642 put_num(TCP_CEPID, -val, 10, radhex, width * left, true, padchar);
643 break;
644
645 case 'u':
646 val = GET_ARG(ap, longflag);
647 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
648 break;
649
650 case 'x':
651 val = GET_ARG(ap, longflag);
652 put_num(TCP_CEPID, val, 16, radhex, width * left, false, padchar);
653 break;
654
655 case 'X':
656 val = GET_ARG(ap, longflag);
657 put_num(TCP_CEPID, val, 16, radHEX, width * left, false, padchar);
658 break;
659
660 case 'c':
661 ch = va_arg(ap, int_t);
662 put_char(TCP_CEPID, (char)ch);
663 break;
664
665 case 's':
666 str = va_arg(ap, char*);
667 while ((ch = *str ++) != '\0') {
668 put_char(TCP_CEPID, (char)ch);
669 width --;
670 }
671 while (width -- > 0)
672 put_char(TCP_CEPID, ' ');
673 break;
674
675 case 'I':
676
677 if (longflag) {
678 str = va_arg(ap, char*);
679 put_ipv6addr(TCP_CEPID, (T_IN6_ADDR *)str, width);
680 }
681 else if (shortflag) {
682 val = GET_ARG(ap, longflag);
683 put_ipv4addr(TCP_CEPID, (ULONGEST *)val, width);
684 }
685 else {
686
687#ifdef SUPPORT_INET6
688
689 str = va_arg(ap, char*);
690 put_ipv6addr(TCP_CEPID, (T_IN6_ADDR *)str, width);
691
692#else /* of #ifdef SUPPORT_INET6 */
693
694#ifdef SUPPORT_INET4
695
696 val = GET_ARG(ap, longflag);
697 put_ipv4addr(TCP_CEPID, (ULONGEST *)val, width);
698
699#endif /* of #ifdef SUPPORT_INET4 */
700
701#endif /* of #ifdef SUPPORT_INET6 */
702
703 }
704
705 break;
706
707 case 'M':
708 str = va_arg(ap, char*);
709 put_macaddr(TCP_CEPID, str, width);
710 break;
711
712 case '%':
713 put_char(TCP_CEPID, '%');
714 break;
715
716 case '0':
717 format --;
718 break;
719
720 default:
721 break;
722 }
723
724 }
725 va_end(ap);
726 put_char(TCP_CEPID, '\n');
727 flush_snd_buff(TCP_CEPID);
728 syscall(sig_sem(SEM_TCP_SYSLOG));
729 return;
730 }
731 else {
732 log.logtype = LOG_TYPE_COMMENT;
733 log.logpar[0] = (intptr_t)format;
734 i = 1;
735 va_start(ap, format);
736
737 while ((c = *format++) != '\0' && i < TNUM_LOGPAR) {
738 if (c != '%') {
739 continue;
740 }
741
742 longflag = 0;
743 c = *format++;
744 while ('0' <= c && c <= '9') {
745 c = *format++;
746 }
747
748 while (c == 'l') {
749 longflag = 1;
750 c = *format++;
751 }
752
753 switch (c) {
754 case 'd':
755 if(longflag == 1) {
756 log.logpar[i++] = (intptr_t)va_arg(ap, long_t);
757 }
758 else {
759 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
760 }
761 break;
762 case 'u':
763 case 'x':
764 case 'X':
765 log.logpar[i++] = (intptr_t)va_arg(ap, uint_t);
766 break;
767 case 'p':
768 log.logpar[i++] = (intptr_t)va_arg(ap, void *);
769 break;
770 case 'c':
771 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
772 break;
773 case 's':
774 log.logpar[i++] = (intptr_t)va_arg(ap, const char *);
775 break;
776 case '\0':
777 format--;
778 break;
779 default:
780 break;
781 }
782 }
783 va_end(ap);
784 syslog_wri_log(prio, &log);
785 return;
786 }
787 }
Note: See TracBrowser for help on using the repository browser.