source: rubycfg_asp/trunk/csp/sample1n/sample1n.c@ 313

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

ソースを追加

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