source: asp3_gr_sakura/trunk/tinet/asp_sample/sample1n.c@ 318

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

プロパティの文字コードにUTF-8を追加、キーワードを削除

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