source: EcnlProtoTool/trunk/asp3_dcre/sample/sample1n.c@ 321

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

文字コードを設定

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