source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet/tcp_usrreq.c@ 389

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

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 41.1 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 * Copyright (c) 1982, 1986, 1988, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
67 * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.40.2.3 1999/08/29 16:29:57 peter Exp $
68 */
69
70#include <string.h>
71
72#ifdef TARGET_KERNEL_ASP
73
74#include <kernel.h>
75#include <sil.h>
76#include "kernel_cfg.h"
77#include "tinet_cfg.h"
78
79#endif /* of #ifdef TARGET_KERNEL_ASP */
80
81#ifdef TARGET_KERNEL_JSP
82
83#include <s_services.h>
84#include <t_services.h>
85#include "kernel_id.h"
86#include "tinet_id.h"
87
88#endif /* of #ifdef TARGET_KERNEL_JSP */
89
90#include <tinet_defs.h>
91#include <tinet_config.h>
92
93#include <net/if.h>
94#include <net/if_ppp.h>
95#include <net/if_loop.h>
96#include <net/ethernet.h>
97#include <net/net.h>
98#include <net/net_endian.h>
99#include <net/net_var.h>
100#include <net/net_buf.h>
101#include <net/net_timer.h>
102#include <net/net_count.h>
103
104#include <netinet/in.h>
105#include <netinet/in_var.h>
106#include <netinet/in_itron.h>
107#include <netinet/ip.h>
108#include <netinet/ip_var.h>
109#include <netinet/tcp.h>
110#include <netinet/tcp_var.h>
111#include <netinet/tcp_fsm.h>
112#include <netinet/tcp_seq.h>
113#include <netinet/tcp_timer.h>
114
115#include <net/if_var.h>
116
117#ifdef SUPPORT_TCP
118
119/*
120 * TINET をライブラリ化しない場合は、全ての機能を
121 * オブジェクトファイルに出力するため、マクロを有効にする。
122 */
123
124#ifndef TCP_CFG_LIBRARY
125
126#define __tcp_cre_rep
127#define __tcp_del_rep
128#define __tcp_cre_cep
129#define __tcp_del_cep
130#define __tcp_acp_cep
131#define __tcp_con_cep
132#define __tcp_sht_cep
133#define __tcp_cls_cep
134#define __tcp_snd_dat
135#define __tcp_rcv_dat
136#define __tcp_snd_oob
137#define __tcp_rcv_oob
138#define __tcp_get_buf
139#define __tcp_snd_buf
140#define __tcp_rcv_buf
141#define __tcp_rel_buf
142#define __tcp_can_cep
143#define __tcp_set_opt
144#define __tcp_get_opt
145
146#endif /* of #ifndef TCP_CFG_LIBRARY */
147
148/*
149 * IPv6 と IPv4 で引数が異なる関数のコンパイル
150 */
151
152#if defined(SUPPORT_INET6)
153
154#define T_IPEP T_IPV6EP
155#define TCP_ACP_CEP tcp6_acp_cep
156#define TCP_CON_CEP tcp6_con_cep
157#define TCP_FIND_CEP_REP tcp6_find_cep_rep
158
159#if defined(SUPPORT_INET4)
160
161#undef T_TCP_REP
162#define T_TCP_REP T_TCP6_REP
163
164#endif /* of #if defined(SUPPORT_INET4) */
165
166#define TCP_CRE_REP tcp6_cre_rep
167#define TCP_DEL_REP_BODY tcp6_del_rep_body
168#define GET_TCP_REP GET_TCP6_REP
169#define VALID_TCP_REPID VALID_TCP6_REPID
170#define T_TCPN_CREP T_TCP6_CREP
171#define API_PROTO API_PROTO_IPV6
172
173#include <netinet/tcpn_usrreq.c>
174
175#undef T_IPEP
176#undef TCP_ACP_CEP
177#undef TCP_CON_CEP
178#undef TCP_FIND_CEP_REP
179
180#undef TCP_CRE_REP
181#undef TCP_DEL_REP_BODY
182#undef GET_TCP_REP
183#undef VALID_TCP_REPID
184#undef T_TCPN_CREP
185#undef API_PROTO
186
187#endif /* of #if defined(SUPPORT_INET6) */
188
189#if defined(SUPPORT_INET4)
190
191#define T_IPEP T_IPV4EP
192#define TCP_ACP_CEP tcp_acp_cep
193#define TCP_CON_CEP tcp_con_cep
194#define TCP_FIND_CEP_REP tcp4_find_cep_rep
195
196#if defined(SUPPORT_INET6)
197
198#undef T_TCP_REP
199#define T_TCP_REP T_TCP4_REP
200
201#endif /* of #if defined(SUPPORT_INET6) */
202
203#define TCP_CRE_REP tcp_cre_rep
204#define TCP_DEL_REP_BODY tcp4_del_rep_body
205#define GET_TCP_REP GET_TCP4_REP
206#define VALID_TCP_REPID VALID_TCP4_REPID
207#define T_TCPN_CREP T_TCP_CREP
208#define API_PROTO API_PROTO_IPV4
209
210#include <netinet/tcpn_usrreq.c>
211
212#endif /* of #if defined(SUPPORT_INET4) */
213
214#ifdef __tcp_cls_cep
215
216/*
217 * tcp_user_closed -- ユーザからのコネクションの開放
218 */
219
220T_TCP_CEP *
221tcp_user_closed (T_TCP_CEP *cep)
222{
223 switch (cep->fsm_state) {
224
225 case TCP_FSM_CLOSED: /* クローズ */
226 case TCP_FSM_LISTEN: /* 受動オープン */
227 cep->fsm_state = TCP_FSM_CLOSED;
228 cep = tcp_close(cep);
229 break;
230
231 case TCP_FSM_SYN_SENT: /* 能動オープン、SYN 送信済み */
232 case TCP_FSM_SYN_RECVD: /* SYN を受信し、SYN 送信済み */
233 cep->flags |= TCP_CEP_FLG_NEED_FIN;
234 break;
235
236 case TCP_FSM_ESTABLISHED: /* コネクション開設完了 */
237 cep->fsm_state = TCP_FSM_FIN_WAIT_1;
238 break;
239
240 case TCP_FSM_CLOSE_WAIT: /* 相手から FIN 受信、APP の終了待ち */
241 cep->fsm_state = TCP_FSM_LAST_ACK;
242 break;
243 }
244
245 if (cep != NULL && cep->fsm_state == TCP_FSM_FIN_WAIT_2)
246 cep->timer[TCP_TIM_2MSL] = TCP_TVAL_KEEP_COUNT * TCP_TVAL_KEEP_INTERVAL;
247 return cep;
248 }
249
250/*
251 * tcp_cls_cep -- 通信端点のクローズ【標準機能】
252 */
253
254ER
255tcp_cls_cep (ID cepid, TMO tmout)
256{
257 T_TCP_CEP *cep;
258 ER error = E_OK;
259 FLGPTN flag;
260
261#ifndef TCP_CFG_NON_BLOCKING
262
263 /* tmout が TMO_NBLK ならエラー */
264 if (tmout == TMO_NBLK)
265 return E_PAR;
266
267#endif /* of #ifndef TCP_CFG_NON_BLOCKING */
268
269 /*
270 * CEP をロックし、API 機能コードとタスク識別子を記録する。
271 * すでに記録されていれば、ペンディング中なのでエラー
272 */
273 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_CLS_CEP)) != E_OK)
274 return error;
275
276#ifdef TCP_CFG_NON_BLOCKING
277
278 /* タイムアウトをチェックする。*/
279 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
280
281 if (!IS_PTR_DEFINED(cep->callback))
282 error = E_OBJ;
283 else if (cep->fsm_state == TCP_FSM_CLOSED) { /* すでにクローズされているとき */
284
285#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
286
287 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_CLS_CEP, E_OK);
288 error = E_WBLK;
289
290#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
291
292 ER error = E_OK;
293
294 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_CLS_CEP, (void*)&error);
295 error = E_WBLK;
296
297#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
298
299 }
300 else {
301 /* NBLK のAPI 機能コードを設定する。*/
302 cep->rcv_nblk_tfn = TFN_TCP_CLS_CEP;
303
304 if ((cep = tcp_user_closed(cep)) != NULL) { /* コネクションを切断する。*/
305 /* 切断セグメント出力をポストする。*/
306 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
307 sig_sem(SEM_TCP_POST_OUTPUT);
308 }
309
310 /* cep が NULL で戻ってきた場合は、
311 * 既にコネクションが切断されていることを意味している。
312 * また、この場合コールバック関数が呼び出されている。
313 */
314 return E_WBLK;
315 }
316 }
317 else { /* 非ノンブロッキングコール */
318
319#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
320
321 if ((cep = tcp_user_closed(cep)) == NULL) { /* コネクションを切断する。*/
322
323 /* cep が NULL で戻ってきた場合は、
324 * 既にコネクションが切断されていることを意味している。
325 */
326 return error;
327 }
328 else {
329 /* 切断セグメント出力をポストする。*/
330 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
331 sig_sem(SEM_TCP_POST_OUTPUT);
332
333 /* イベントフラグが CLOSED になるまで待つ。*/
334 error = twai_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED, TWF_ORW, &flag, tmout);
335 if (error == E_OK && cep->error != E_OK)
336 error = cep->error;
337
338 if (error != E_OK) {
339 if (error == E_RLWAI) {
340 /* tcp_cls_cep がキャンセルされたときは、RST を送信する。*/
341 tcp_respond(NULL, cep, cep->rcv_nxt, cep->snd_una - 1,
342 cep->rbufsz - cep->rwbuf_count, TCP_FLG_RST);
343 }
344
345 /* タイマーを停止する。*/
346 tcp_cancel_timers(cep);
347
348 /*
349 * 通信端点をロックし、
350 * 受信再構成キューのネットワークバッファを解放する。
351 */
352 syscall(wai_sem(cep->semid_lock));
353 tcp_free_reassq(cep);
354 syscall(sig_sem(cep->semid_lock));
355
356 /* 状態を未使用にする。*/
357 cep->fsm_state = TCP_FSM_CLOSED;
358
359 /*
360 * 以下に関係しないフラグをクリアーする。
361 * ・送受信ウィンドバッファの省コピー機能
362 * ・動的な通信端点の生成・削除機能
363 */
364 cep->flags &= TCP_CEP_FLG_NOT_CLEAR;
365
366 /*
367 * 通信端点をロックし、
368 * 送受信ウィンドバッファキューのネットワークバッファを解放する。
369 */
370 cep->rwbuf_count = 0;
371 syscall(wai_sem(cep->semid_lock));
372 TCP_FREE_RWBUFQ(cep);
373 TCP_FREE_SWBUFQ(cep);
374 syscall(sig_sem(cep->semid_lock));
375
376 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
377 }
378 }
379
380#ifdef TCP_CFG_NON_BLOCKING
381
382 }
383
384#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
385
386 cep->rcv_tskid = TA_NULL;
387 cep->rcv_tfn = TFN_TCP_UNDEF;
388 return error;
389 }
390
391#endif /* of #ifdef __tcp_cls_cep */
392
393#ifdef __tcp_sht_cep
394
395/*
396 * tcp_sht_cep -- データ送信の終了【標準機能】
397 */
398
399ER
400tcp_sht_cep (ID cepid)
401{
402 T_TCP_CEP *cep;
403 ER error = E_OK;
404
405 /*
406 * CEP をロックし、API 機能コードとタスク識別子を記録する。
407 * すでに記録されていれば、ペンディング中なのでエラー
408 */
409 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SHT_CEP)) != E_OK)
410 return error;
411
412 /* TCP 通信端点のコネクションが確立状態でなければエラー */
413 if (!TCP_FSM_HAVE_ESTABLISHED(cep->fsm_state)) {
414 if ((error = cep->error) == E_OK)
415 error = E_OBJ;
416 }
417
418 else if ((cep = tcp_user_closed(cep)) != NULL) { /* コネクションを切断する。*/
419
420 /* 切断セグメント出力をポストする。*/
421 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
422 sig_sem(SEM_TCP_POST_OUTPUT);
423 }
424
425 cep->snd_tskid = TA_NULL;
426 cep->snd_tfn = TFN_TCP_UNDEF;
427 return error;
428 }
429
430#endif /* of #ifdef __tcp_sht_cep */
431
432#ifdef __tcp_snd_dat
433
434/*
435 * tcp_snd_dat -- パケットの送信【標準機能】
436 */
437
438ER_UINT
439tcp_snd_dat (ID cepid, void *data, int_t len, TMO tmout)
440{
441 T_TCP_CEP *cep;
442 ER_UINT error;
443
444#ifdef TCP_CFG_NON_BLOCKING
445
446 /* data が NULL か、len < 0 ならエラー */
447 if (data == NULL || len < 0)
448 return E_PAR;
449
450#else /* of #ifdef TCP_CFG_NON_BLOCKING */
451
452 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
453 if (data == NULL || len < 0 || tmout == TMO_NBLK)
454 return E_PAR;
455
456#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
457
458 /*
459 * CEP をロックし、API 機能コードとタスク識別子を記録する。
460 * すでに記録されていれば、ペンディング中なのでエラー
461 */
462 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_DAT)) != E_OK)
463 return error;
464
465 /* 送信できるか、通信端点の状態を見る。*/
466 if ((error = tcp_can_send_more(cep, TFN_TCP_SND_DAT, tmout)) != E_OK)
467 goto err_ret;
468
469#ifdef TCP_CFG_NON_BLOCKING
470
471 /* タイムアウトをチェックする。*/
472 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
473
474 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
475 if (!TCP_IS_SWBUF_FULL(cep)) {
476
477 /* 送信ウィンドバッファにデータを書き込む。*/
478 error = TCP_WRITE_SWBUF(cep, data, (uint_t)len);
479
480 /* 出力をポストする。*/
481 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
482 sig_sem(SEM_TCP_POST_OUTPUT);
483
484 /* コールバック関数を呼び出す。*/
485#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
486 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_DAT, (void*)error);
487#else
488 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_DAT, (void*)&error);
489#endif
490 error = E_WBLK;
491 goto err_ret;
492 }
493 else {
494 cep->snd_data = data;
495 cep->snd_len = len;
496 cep->snd_nblk_tfn = TFN_TCP_SND_DAT;
497 TCP_ALLOC_SWBUF(cep);
498
499 return E_WBLK;
500 }
501 }
502 else { /* 非ノンブロッキングコール */
503
504#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
505
506 /* 送信ウィンドバッファが空くのを待つ。*/
507 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
508 goto err_ret;
509
510 /* 送信ウィンドバッファにデータを書き込む。*/
511 if ((error = TCP_WRITE_SWBUF(cep, data, (uint_t)len)) > 0) {
512
513 /* データを送信する。送信ウィンドバッファがフルのときは強制的に送信する。*/
514 if (TCP_IS_SWBUF_FULL(cep))
515 cep->flags |= TCP_CEP_FLG_FORCE | TCP_CEP_FLG_FORCE_CLEAR;
516
517 /* 出力をポストする。*/
518 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
519 sig_sem(SEM_TCP_POST_OUTPUT);
520 }
521
522#ifdef TCP_CFG_NON_BLOCKING
523
524 }
525
526#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
527
528err_ret:
529 cep->snd_tskid = TA_NULL;
530 cep->snd_tfn = TFN_TCP_UNDEF;
531 return error;
532 }
533
534#endif /* of #ifdef __tcp_snd_dat */
535
536#ifdef __tcp_get_buf
537
538/*
539 * tcp_get_buf -- 送信用バッファの獲得【標準機能】
540 */
541
542ER_UINT
543tcp_get_buf (ID cepid, void **p_buf, TMO tmout)
544{
545 T_TCP_CEP *cep;
546 ER_UINT error;
547
548#ifdef TCP_CFG_NON_BLOCKING
549
550 /* p_buf が NULL ならエラー */
551 if (p_buf == NULL)
552 return E_PAR;
553
554#else /* of #ifdef TCP_CFG_NON_BLOCKING */
555
556 /* p_buf が NULL か、tmout が TMO_NBLK ならエラー */
557 if (p_buf == NULL || tmout == TMO_NBLK)
558 return E_PAR;
559
560#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
561
562 /*
563 * CEP をロックし、API 機能コードとタスク識別子を記録する。
564 * すでに記録されていれば、ペンディング中なのでエラー
565 */
566 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_GET_BUF)) != E_OK)
567 return error;
568
569 /* 送信できるか、通信端点の状態を見る。*/
570 if ((error = tcp_can_send_more(cep, TFN_TCP_GET_BUF, tmout)) != E_OK)
571 goto err_ret;
572
573#ifdef TCP_CFG_NON_BLOCKING
574
575 /* タイムアウトをチェックする。*/
576 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
577
578 if (!TCP_IS_SWBUF_FULL(cep)) {
579
580 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
581 error = TCP_GET_SWBUF_ADDR(cep, p_buf);
582
583 /* コールバック関数を呼び出す。*/
584#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
585 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_GET_BUF, (void*)error);
586#else
587 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_GET_BUF, (void*)&error);
588#endif
589 error = E_WBLK;
590 goto err_ret;
591 }
592 else {
593 cep->snd_p_buf = p_buf;
594 cep->snd_nblk_tfn = TFN_TCP_GET_BUF;
595 TCP_ALLOC_SWBUF(cep);
596 return E_WBLK;
597 }
598 }
599
600 else { /* 非ノンブロッキングコール */
601
602#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
603
604 /* 送信ウィンドバッファが空くのを待つ。*/
605 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
606 goto err_ret;
607
608 /* 送信ウィンドバッファの空アドレスを獲得する。*/
609 error = TCP_GET_SWBUF_ADDR(cep, p_buf);
610
611#ifdef TCP_CFG_NON_BLOCKING
612
613 }
614
615#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
616
617err_ret:
618 cep->snd_tskid = TA_NULL;
619 cep->snd_tfn = TFN_TCP_UNDEF;
620 return error;
621 }
622
623#endif /* of #ifdef __tcp_get_buf */
624
625#ifdef __tcp_snd_buf
626
627/*
628 * tcp_snd_buf -- バッファ内のデータの送信【標準機能】
629 */
630
631ER
632tcp_snd_buf (ID cepid, int_t len)
633{
634 T_TCP_CEP *cep;
635 ER error;
636
637 /* 送信する長さ len をチェックする。*/
638 if (len < 0)
639 return E_PAR;
640
641 /* 送信する長さlen が 0 であれば、何もしないで戻る。*/
642 if (len == 0)
643 return E_OK;
644
645 /*
646 * CEP をロックし、API 機能コードとタスク識別子を記録する。
647 * すでに記録されていれば、ペンディング中なのでエラー
648 */
649 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_BUF)) != E_OK)
650 return error;
651
652 /* 送信する長さ len をチェックする。*/
653 if (len > cep->get_buf_len) {
654 error = E_OBJ;
655 goto err_ret;
656 }
657
658 /* 送信できるか、CEP の FSM 状態を見る。*/
659 if (!TCP_FSM_CAN_SEND_MORE(cep->fsm_state)) {
660 if ((error = cep->error) == E_OK)
661 error = E_OBJ;
662 goto err_ret;
663 }
664
665 /* 送信ウィンドバッファのデータを送信可能にする。*/
666 TCP_SEND_SWBUF(cep, (uint_t)len);
667
668 /* 出力をポストする。*/
669 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
670 sig_sem(SEM_TCP_POST_OUTPUT);
671
672err_ret:
673 cep->snd_tskid = TA_NULL;
674 cep->snd_tfn = TFN_TCP_UNDEF;
675 return error;
676 }
677
678#endif /* of #ifdef __tcp_snd_buf */
679
680#ifdef __tcp_rcv_dat
681
682/*
683 * tcp_rcv_dat -- パケットの受信【標準機能】
684 */
685
686ER_UINT
687tcp_rcv_dat (ID cepid, void *data, int_t len, TMO tmout)
688{
689 T_TCP_CEP *cep;
690 ER_UINT error;
691
692#ifdef TCP_CFG_NON_BLOCKING
693
694 /* data が NULL か、len < 0 ならエラー */
695 if (data == NULL || len < 0)
696 return E_PAR;
697
698#else /* of #ifdef TCP_CFG_NON_BLOCKING */
699
700 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
701 if (data == NULL || len < 0 || tmout == TMO_NBLK)
702 return E_PAR;
703
704#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
705
706 /*
707 * CEP をロックし、API 機能コードとタスク識別子を記録する。
708 * すでに記録されていれば、ペンディング中なのでエラー
709 */
710 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_RCV_DAT)) != E_OK)
711 return error;
712
713 /* 受信できるか、通信端点の状態を見る。*/
714 if (tcp_can_recv_more(&error, cep, TFN_TCP_RCV_DAT, tmout) != E_OK)
715 goto err_ret;
716
717#ifdef TCP_CFG_NON_BLOCKING
718
719 /* タイムアウトをチェックする。*/
720 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
721
722 /* 受信ウィンドバッファにデータがあればコールバック関数を呼び出す。*/
723 if (cep->rwbuf_count > 0) {
724
725 /* 受信ウィンドバッファからデータを取り出す。*/
726 len = TCP_READ_RWBUF(cep, data, (uint_t)len);
727
728 /* コールバック関数を呼び出す。*/
729#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
730 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_DAT, (void*)(uint32_t)len);
731#else
732 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_DAT, (void*)&len);
733#endif
734 error = E_WBLK;
735 goto err_ret;
736 }
737 else {
738 cep->rcv_data = data;
739 cep->rcv_len = len;
740 cep->rcv_nblk_tfn = TFN_TCP_RCV_DAT;
741 return E_WBLK;
742 }
743 }
744 else { /* 非ノンブロッキングコール */
745
746#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
747
748 /* 受信ウィンドバッファにデータがなければ、入力があるまで待つ。*/
749 if ((error = tcp_wait_rwbuf(cep, tmout)) != E_OK)
750 goto err_ret;
751
752 /* 受信ウィンドバッファからデータを取り出す。*/
753 error = TCP_READ_RWBUF(cep, data, (uint_t)len);
754
755 /* 相手にウィンドウサイズが変わったことを知らせるため出力をポストする。*/
756 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
757 sig_sem(SEM_TCP_POST_OUTPUT);
758
759#ifdef TCP_CFG_NON_BLOCKING
760
761 }
762
763#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
764
765err_ret:
766 cep->rcv_tskid = TA_NULL;
767 cep->rcv_tfn = TFN_TCP_UNDEF;
768 return error;
769 }
770
771#endif /* of #ifdef __tcp_rcv_dat */
772
773#ifdef __tcp_rcv_buf
774
775/*
776 * tcp_rcv_buf -- 受信したデータの入ったバッファの獲得【標準機能】
777 */
778
779ER_UINT
780tcp_rcv_buf (ID cepid, void **p_buf, TMO tmout)
781{
782 T_TCP_CEP *cep;
783 ER_UINT error;
784
785#ifdef TCP_CFG_NON_BLOCKING
786
787 /* p_buf が NULL ならエラー */
788 if (p_buf == NULL)
789 return E_PAR;
790
791#else /* of #ifdef TCP_CFG_NON_BLOCKING */
792
793 /* p_buf が NULL か、tmout が TMO_NBLK ならエラー */
794 if (p_buf == NULL || tmout == TMO_NBLK)
795 return E_PAR;
796
797#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
798
799 /*
800 * CEP をロックし、API 機能コードとタスク識別子を記録する。
801 * すでに記録されていれば、ペンディング中なのでエラー
802 */
803 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_RCV_BUF)) != E_OK)
804 return error;
805
806 /* 受信できるか、通信端点の状態を見る。*/
807 if (tcp_can_recv_more(&error, cep, TFN_TCP_RCV_DAT, tmout) != E_OK)
808 goto err_ret;
809
810#ifdef TCP_CFG_NON_BLOCKING
811
812 /* タイムアウトをチェックする。*/
813 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
814
815 /* 受信ウィンドバッファにデータがあればコールバック関数を呼び出す。*/
816 if (cep->rwbuf_count > 0) {
817
818 /* 受信ウィンドバッファの空アドレスを獲得する。*/
819 error = TCP_GET_RWBUF_ADDR(cep, p_buf);
820
821 /* コールバック関数を呼び出す。*/
822#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
823 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_BUF, (void*)error);
824#else
825 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_BUF, (void*)&error);
826#endif
827 error = E_WBLK;
828 goto err_ret;
829 }
830 else {
831 cep->rcv_p_buf = p_buf;
832 cep->rcv_nblk_tfn = TFN_TCP_RCV_BUF;
833 return E_WBLK;
834 }
835 }
836 else { /* 非ノンブロッキングコール */
837
838#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
839
840 /* 受信ウィンドバッファにデータがなければ、入力があるまで待つ。*/
841 if ((error = tcp_wait_rwbuf(cep, tmout)) != E_OK) {
842 cep->rwbuf_count = 0;
843 goto err_ret;
844 }
845
846 /* 受信ウィンドバッファのアドレスを獲得する。*/
847 error = TCP_GET_RWBUF_ADDR(cep, p_buf);
848
849#ifdef TCP_CFG_NON_BLOCKING
850
851 }
852
853#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
854
855err_ret:
856 cep->rcv_tskid = TA_NULL;
857 cep->rcv_tfn = TFN_TCP_UNDEF;
858 return error;
859 }
860
861#endif /* of #ifdef __tcp_rcv_buf */
862
863#ifdef __tcp_rel_buf
864
865/*
866 * tcp_rel_buf -- 受信用バッファの解放【標準機能】
867 */
868
869ER
870tcp_rel_buf (ID cepid, int_t len)
871{
872 T_TCP_CEP *cep;
873 ER error;
874
875 /* 解放する長さ len をチェックする。*/
876 if (len < 0)
877 return E_PAR;
878
879 /*
880 * CEP をロックし、API 機能コードとタスク識別子を記録する。
881 * すでに記録されていれば、ペンディング中なのでエラー
882 */
883 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_REL_BUF)) != E_OK)
884 return error;
885
886 /* 解放する長さ len をチェックする。*/
887 if (len > cep->rcv_buf_len) {
888 error = E_OBJ;
889 goto err_ret;
890 }
891
892 /* 通信端点をロックする。*/
893 syscall(wai_sem(cep->semid_lock));
894
895 /* 受信ウィンドバッファから受信したオクテットを削除する。*/
896 TCP_DROP_RWBUF(cep, (uint_t)len);
897
898 /* tcp_rcv_buf の割当て長をリセットする。*/
899 cep->rcv_buf_len -= len;
900
901 /* 通信端点のロックを解除する。*/
902 syscall(sig_sem(cep->semid_lock));
903
904 /* 相手にウィンドウサイズが変わったことを知らせるため出力をポストする。*/
905 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
906 sig_sem(SEM_TCP_POST_OUTPUT);
907
908err_ret:
909 cep->rcv_tskid = TA_NULL;
910 cep->rcv_tfn = TFN_TCP_UNDEF;
911 return error;
912 }
913
914#endif /* of #ifdef __tcp_rel_buf */
915
916#ifdef __tcp_can_cep
917
918/*
919 * tcp_can_snd -- ペンディングしている送信のキャンセル
920 */
921
922static ER
923tcp_can_snd (T_TCP_CEP *cep, FN fncd)
924{
925 ER error = E_OK;
926
927 /* 通信端点をロックする。*/
928 syscall(wai_sem(cep->semid_lock));
929
930 /*
931 * snd_tskid が TA_NULL なら、
932 * ペンディングしていないのでエラー
933 */
934 if (cep->snd_tskid == TA_NULL)
935 error = EV_NOPND;
936
937 /* ペンディング中の API 機能コードと一致しなければエラー */
938 else if (fncd != TFN_TCP_ALL && fncd != cep->snd_tfn)
939 error = E_OBJ;
940
941 /* 処理をキャンセルする。*/
942 else {
943
944 /* 受信再構成キューのネットワークバッファを解放する。*/
945 tcp_free_reassq(cep);
946
947 /* 受信ウィンドバッファキューのネットワークバッファを解放する。*/
948 cep->rwbuf_count = 0;
949 TCP_FREE_RWBUFQ(cep);
950
951 /* 送信ウィンドバッファキューのネットワークバッファを解放する。*/
952 TCP_FREE_SWBUFQ(cep);
953
954#ifdef TCP_CFG_NON_BLOCKING
955
956 if (cep->snd_nblk_tfn != TFN_TCP_UNDEF) { /* ノンブロッキングコール */
957
958 switch (cep->snd_nblk_tfn) {
959
960 case TFN_TCP_CON_CEP:
961 /*
962 * 通信端点から受付口を解放し、
963 * イベントフラグをクローズに設定する。
964 */
965 cep->rep = NULL;
966
967#if defined(_IP6_CFG) && defined(_IP4_CFG)
968 cep->rep4 = NULL;
969#endif
970
971 cep->fsm_state = TCP_FSM_CLOSED;
972 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
973 break;
974
975 case TFN_TCP_SND_DAT:
976 case TFN_TCP_GET_BUF:
977 case TFN_TCP_SND_OOB:
978 break;
979 }
980
981 if (IS_PTR_DEFINED(cep->callback)) {
982
983#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
984
985 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)E_RLWAI);
986
987#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
988
989 ER error = E_RLWAI;
990
991 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)&error);
992
993#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
994
995 }
996 else
997 error = E_OBJ;
998 cep->snd_nblk_tfn = TFN_TCP_UNDEF;
999 }
1000 else
1001
1002#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1003
1004 error = rel_wai(cep->snd_tskid);
1005
1006 cep->snd_tskid = TA_NULL;
1007 cep->snd_tfn = TFN_TCP_UNDEF;
1008 }
1009
1010 /* 通信端点のロックを解除する。*/
1011 syscall(sig_sem(cep->semid_lock));
1012
1013 return error;
1014 }
1015
1016/*
1017 * tcp_can_rcv -- ペンディングしている受信のキャンセル
1018 */
1019
1020static ER
1021tcp_can_rcv (T_TCP_CEP *cep, FN fncd)
1022{
1023 ER error = E_OK;
1024
1025 /* 通信端点をロックする。*/
1026 syscall(wai_sem(cep->semid_lock));
1027
1028 /*
1029 * rcv_tskid が TA_NULL なら、
1030 * ペンディングしていないのでエラー
1031 */
1032 if (cep->rcv_tskid == TA_NULL)
1033 error = EV_NOPND;
1034
1035 /* ペンディング中の API 機能コードと一致しなければエラー */
1036 else if (fncd != TFN_TCP_ALL && fncd != cep->rcv_tfn)
1037 error = E_OBJ;
1038
1039 /* 処理をキャンセルする。*/
1040 else {
1041
1042 /* 受信再構成キューのネットワークバッファを解放する。*/
1043 tcp_free_reassq(cep);
1044
1045 /* 受信ウィンドバッファキューのネットワークバッファを解放する。*/
1046 cep->rwbuf_count = 0;
1047 TCP_FREE_RWBUFQ(cep);
1048
1049 /* 送信ウィンドバッファキューのネットワークバッファを解放する。*/
1050 TCP_FREE_SWBUFQ(cep);
1051
1052#ifdef TCP_CFG_NON_BLOCKING
1053
1054 if (cep->rcv_nblk_tfn != TFN_TCP_UNDEF) { /* ノンブロッキングコール */
1055
1056 switch (cep->rcv_nblk_tfn) {
1057
1058 case TFN_TCP_ACP_CEP:
1059 /*
1060 * 通信端点から受付口を解放し、
1061 * イベントフラグをクローズに設定する。
1062 */
1063 cep->rep = NULL;
1064
1065#if defined(_IP6_CFG) && defined(_IP4_CFG)
1066 cep->rep4 = NULL;
1067#endif
1068
1069 cep->fsm_state = TCP_FSM_CLOSED;
1070 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
1071 break;
1072
1073 case TFN_TCP_RCV_DAT:
1074 case TFN_TCP_RCV_BUF:
1075 break;
1076
1077 case TFN_TCP_CLS_CEP:
1078 cep->fsm_state = TCP_FSM_CLOSED;
1079 tcp_respond(NULL, cep, cep->rcv_nxt, cep->snd_una - 1,
1080 cep->rbufsz - cep->rwbuf_count, TCP_FLG_RST);
1081 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
1082 break;
1083 }
1084
1085 if (IS_PTR_DEFINED(cep->callback)) {
1086
1087#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1088
1089 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)E_RLWAI);
1090
1091#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1092
1093 ER error = E_RLWAI;
1094
1095 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&error);
1096
1097#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1098
1099 }
1100 else
1101 error = E_OBJ;
1102 cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
1103 }
1104 else
1105
1106#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1107
1108 error = rel_wai(cep->rcv_tskid);
1109
1110 cep->rcv_tskid = TA_NULL;
1111 cep->rcv_tfn = TFN_TCP_UNDEF;
1112 }
1113
1114 /* 通信端点のロックを解除する。*/
1115 syscall(sig_sem(cep->semid_lock));
1116
1117 return error;
1118 }
1119
1120/*
1121 * tcp_can_cep -- ペンディングしている処理のキャンセル【標準機能】
1122 */
1123
1124ER
1125tcp_can_cep (ID cepid, FN fncd)
1126{
1127 T_TCP_CEP *cep;
1128 ER error = E_OK, snd_err, rcv_err;
1129
1130 /* API 機能コードをチェックする。*/
1131 if (!VALID_TFN_TCP_CAN(fncd))
1132 return E_PAR;
1133
1134 /* TCP 通信端点 ID をチェックする。*/
1135 if (!VALID_TCP_CEPID(cepid))
1136 return E_ID;
1137
1138 /* TCP 通信端点を得る。*/
1139 cep = GET_TCP_CEP(cepid);
1140
1141 /* TCP 通信端点をチェックする。*/
1142 if (!VALID_TCP_CEP(cep))
1143 return E_NOEXS;
1144
1145 if (fncd == TFN_TCP_ALL) { /* TFN_TCP_ALL の処理 */
1146 snd_err = tcp_can_snd(cep, fncd);
1147 rcv_err = tcp_can_rcv(cep, fncd);
1148
1149 /*
1150 * snd_err と rcv_err のどちらも EV_NOPND
1151 * なら、ペンディングしていないのでエラー
1152 */
1153 if (snd_err == EV_NOPND && rcv_err == EV_NOPND)
1154 error = E_OBJ;
1155 else {
1156 if (snd_err == EV_NOPND)
1157 snd_err = E_OK;
1158 if (rcv_err == EV_NOPND)
1159 rcv_err = E_OK;
1160
1161 if (snd_err != E_OK)
1162 error = snd_err;
1163 else if (rcv_err != E_OK)
1164 error = rcv_err;
1165 }
1166 }
1167
1168 else if (IS_TFN_TCP_RCV(fncd)) { /* 受信処理のキャンセル */
1169 if ((error = tcp_can_rcv(cep, fncd)) == EV_NOPND)
1170 error = E_OBJ;
1171 }
1172
1173 else { /* 送信処理のキャンセル */
1174 if ((error = tcp_can_snd(cep, fncd)) == EV_NOPND)
1175 error = E_OBJ;
1176 }
1177
1178 return error;
1179 }
1180
1181#endif /* of #ifdef __tcp_can_cep */
1182
1183#ifdef TCP_CFG_EXTENTIONS
1184
1185#ifdef __tcp_cre_cep
1186
1187/*
1188 * tcp_cre_cep -- TCP 通信端点の生成【拡張機能】
1189 */
1190
1191ER
1192tcp_cre_cep (ID cepid, T_TCP_CCEP *pk_ccep)
1193{
1194 T_TCP_CEP *cep;
1195 ER error;
1196
1197 /* TCP 通信端点 ID をチェックする。*/
1198 if (!VALID_TCP_CEPID(cepid))
1199 return E_ID;
1200
1201 /* pk_ccep が NULL ならエラー */
1202 if (pk_ccep == NULL)
1203 return E_PAR;
1204
1205 /* TCP 通信端点を得る。*/
1206 cep = GET_TCP_CEP(cepid);
1207
1208 /* TCP 通信端点が、動的生成用でなければエラー */
1209 if (!DYNAMIC_TCP_CEP(cep))
1210 return E_ID;
1211
1212 /* 通信端点をロックする。*/
1213 syscall(wai_sem(cep->semid_lock));
1214
1215 /*
1216 * TCP 通信端点をチェックする。生成済みであればエラー
1217 */
1218 if (VALID_TCP_CEP(cep))
1219 error = E_OBJ;
1220 else {
1221
1222 /* TCP 通信端点生成情報をコピーする。*/
1223 cep->cepatr = pk_ccep->cepatr; /* 通信端点属性 */
1224 cep->sbuf = pk_ccep->sbuf; /* 送信用ウィンドバッファ */
1225 cep->sbufsz = pk_ccep->sbufsz; /* 送信用ウィンドバッファサイズ */
1226 cep->rbuf = pk_ccep->rbuf; /* 受信用ウィンドバッファ */
1227 cep->rbufsz = pk_ccep->rbufsz; /* 受信用ウィンドバッファサイズ */
1228 cep->callback = (void*)pk_ccep->callback; /* コールバック */
1229
1230 /* TCP 通信端点を生成済みにする。*/
1231 cep->flags |= TCP_CEP_FLG_VALID;
1232 error = E_OK;
1233 }
1234
1235 /* 通信端点のロックを解除する。*/
1236 syscall(sig_sem(cep->semid_lock));
1237
1238 return error;
1239 }
1240
1241#endif /* of #ifdef __tcp_cre_cep */
1242
1243/*
1244 * tcp_del_cep -- TCP 通信端点の削除【拡張機能】
1245 */
1246
1247#ifdef __tcp_del_cep
1248
1249ER
1250tcp_del_cep (ID cepid)
1251{
1252 T_TCP_CEP *cep;
1253 ER error;
1254
1255 /* TCP 通信端点 ID をチェックする。*/
1256 if (!VALID_TCP_CEPID(cepid))
1257 return E_ID;
1258
1259 /* TCP 通信端点を得る。*/
1260 cep = GET_TCP_CEP(cepid);
1261
1262 /* TCP 通信端点が、動的生成用でなければエラー */
1263 if (!DYNAMIC_TCP_CEP(cep))
1264 return E_ID;
1265
1266 /* 通信端点をロックする。*/
1267 syscall(wai_sem(cep->semid_lock));
1268
1269 /*
1270 * TCP 通信端点をチェックする。以下の場合はエラー
1271 * ・未生成。
1272 * ・使用中。
1273 */
1274 if (!VALID_TCP_CEP(cep))
1275 error = E_NOEXS;
1276 else if (cep->fsm_state != TCP_FSM_CLOSED)
1277 error = E_OBJ;
1278 else {
1279
1280 /* TCP 通信端点を未生成にする。*/
1281 cep->flags &= ~TCP_CEP_FLG_VALID;
1282 error = E_OK;
1283 }
1284
1285 /* 通信端点のロックを解除する。*/
1286 syscall(sig_sem(cep->semid_lock));
1287
1288 return error;
1289 }
1290
1291#endif /* of #ifdef __tcp_del_cep */
1292
1293#ifdef __tcp_snd_oob
1294
1295/*
1296 * tcp_snd_oob -- 緊急データの送信【拡張機能】
1297 */
1298
1299ER_UINT
1300tcp_snd_oob (ID cepid, void *data, int_t len, TMO tmout)
1301{
1302 T_TCP_CEP *cep;
1303 ER_UINT error;
1304
1305#ifdef TCP_CFG_NON_BLOCKING
1306
1307 /* data が NULL か、len < 0 ならエラー */
1308 if (data == NULL || len < 0)
1309 return E_PAR;
1310
1311#else /* of #ifdef TCP_CFG_NON_BLOCKING */
1312
1313 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
1314 if (data == NULL || len < 0 || tmout == TMO_NBLK)
1315 return E_PAR;
1316
1317#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1318
1319 /*
1320 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1321 * すでに記録されていれば、ペンディング中なのでエラー
1322 */
1323 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_OOB)) != E_OK)
1324 return error;
1325
1326 /* 送信できるか、通信端点の状態を見る。*/
1327 if ((error = tcp_can_send_more(cep, TFN_TCP_SND_OOB, tmout)) != E_OK)
1328 goto err_ret;
1329
1330#ifdef TCP_CFG_NON_BLOCKING
1331
1332 /* タイムアウトをチェックする。*/
1333 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1334
1335 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
1336 if (!TCP_IS_SWBUF_FULL(cep)) {
1337
1338 /* 送信ウィンドバッファにデータを書き込む。*/
1339 error = TCP_WRITE_SWBUF(cep, data, (uint_t)len);
1340
1341 /* 送信緊急ポインタを設定する。*/
1342 cep->snd_up = cep->snd_una + cep->swbuf_count;
1343
1344 /* 出力をポストする。*/
1345 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1346 sig_sem(SEM_TCP_POST_OUTPUT);
1347
1348 /* コールバック関数を呼び出す。*/
1349#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1350 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_OOB, (void*)error);
1351#else
1352 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_OOB, (void*)&error);
1353#endif
1354 error = E_WBLK;
1355 goto err_ret;
1356 }
1357 else {
1358 cep->snd_data = data;
1359 cep->snd_len = len;
1360 cep->snd_nblk_tfn = TFN_TCP_SND_OOB;
1361 TCP_ALLOC_SWBUF(cep);
1362
1363 return E_WBLK;
1364 }
1365 }
1366 else { /* 非ノンブロッキングコール */
1367
1368#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1369
1370 /* 送信ウィンドバッファが空くのを待つ。*/
1371 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
1372 goto err_ret;
1373
1374 /* 送信ウィンドバッファにデータを書き込む。*/
1375 if ((error = TCP_WRITE_SWBUF(cep, data, (uint_t)len)) > 0) {
1376
1377 /* 送信緊急ポインタを設定する。*/
1378 cep->snd_up = cep->snd_una + cep->swbuf_count;
1379
1380 /* データを送信する。送信ウィンドバッファがフルのときは強制的に送信する。*/
1381 if (TCP_IS_SWBUF_FULL(cep))
1382 cep->flags |= TCP_CEP_FLG_FORCE | TCP_CEP_FLG_FORCE_CLEAR;
1383
1384 /* 出力をポストする。*/
1385 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1386 sig_sem(SEM_TCP_POST_OUTPUT);
1387 }
1388
1389#ifdef TCP_CFG_NON_BLOCKING
1390
1391 }
1392
1393#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1394
1395err_ret:
1396 cep->snd_tskid = TA_NULL;
1397 cep->snd_tfn = TFN_TCP_UNDEF;
1398 return error;
1399 }
1400
1401#endif /* of #ifdef __tcp_snd_oob */
1402
1403#ifdef __tcp_rcv_oob
1404
1405/*
1406 * tcp_rcv_oob -- 緊急データの受信【拡張機能】
1407 *
1408 * 注意: 送信側が複数オクテットのデータを送信しても、
1409 * 緊急ポインタが指す 1 オクテットのデータのみ受信する。
1410 */
1411
1412ER_UINT
1413tcp_rcv_oob (ID cepid, void *data, int_t len)
1414{
1415 T_TCP_CEP *cep;
1416 uint8_t *urg;
1417
1418 /* TCP 通信端点 ID をチェックする。*/
1419 if (!VALID_TCP_CEPID(cepid))
1420 return E_ID;
1421
1422 /* data が NULL か、len < 0 ならエラー */
1423 if (data == NULL || len < 0)
1424 return E_PAR;
1425
1426 /* TCP 通信端点を得る。*/
1427 cep = GET_TCP_CEP(cepid);
1428
1429 /* 受信できるか、通信端点の状態を見る。*/
1430 /* 受信できるか、fsm_state を見る。*/
1431 if (!TCP_FSM_CAN_RECV_MORE(cep->fsm_state))
1432 return E_OBJ;
1433
1434 /*
1435 * 緊急データ入りのセグメントの TCP ヘッダが
1436 * 設定されていなければ、緊急データを受信していない。
1437 */
1438 if (cep->urg_tcph == NULL)
1439 return E_OBJ;
1440
1441 /* len == 0 ならバッファオーバーフロー */
1442 if (len == 0)
1443 return E_BOVR;
1444
1445 /* 緊急ポインタが指す 1 オクテットのデータを読み取る。*/
1446 urg = (uint8_t*)cep->urg_tcph + TCP_DATA_OFF(cep->urg_tcph->doff) + cep->urg_tcph->urp + TCP_CFG_URG_OFFSET;
1447 *(uint8_t*)data = *urg;
1448
1449 /* 読み取ったデータから後ろの SDU を前に詰める。*/
1450 memcpy(urg, urg + 1, cep->urg_tcph->sum - (cep->urg_tcph->urp + TCP_CFG_URG_OFFSET) - 1);
1451
1452 /* tcp_rcv_oob() が呼出されたこと知らせるために、NULL を設定する。*/
1453 cep->urg_tcph = NULL;
1454
1455 return 1;
1456 }
1457
1458#endif /* of #ifdef __tcp_rcv_oob */
1459
1460#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1461
1462#ifdef TCP_CFG_EXTENTIONS
1463
1464#ifdef __tcp_del_rep
1465
1466/*
1467 * tcp_del_rep -- TCP 受付口の削除【拡張機能】
1468 */
1469
1470#if defined(SUPPORT_INET6) && TNUM_TCP6_REPID > 0
1471
1472#if defined(SUPPORT_INET4) && TNUM_TCP4_REPID > 0
1473
1474ER
1475tcp_del_rep (ID repid)
1476{
1477
1478 /*
1479 * TCP 受付口 ID をチェックする。
1480 * IPv6 用 TCP 受付口であれば、
1481 * IPv6 用の「TCP 受付口の削除関数(本体)」を呼出す。
1482 */
1483 //NET_DEBUG_TCP3("tcp_del_rep1[r=%d,n=%d,x=%d]\n",
1484 // repid, TMIN_TCP6_REPID, tmax_tcp6_repid);
1485 //NET_DEBUG_TCP3("tcp_del_rep2[r=%d,n=%d,x=%d]\n",
1486 // repid, TMIN_TCP4_REPID, tmax_tcp4_repid);
1487 if (VALID_TCP6_REPID(repid))
1488 return tcp6_del_rep_body(repid);
1489
1490 /*
1491 * TCP 受付口 ID をチェックする。
1492 * IPv4 用 TCP 受付口であれば、
1493 * IPv4 用の「TCP 受付口の削除関数(本体)」を呼出す。
1494 */
1495 else if (VALID_TCP4_REPID(repid))
1496 return tcp4_del_rep_body(repid);
1497 else
1498 return E_ID;
1499
1500 }
1501
1502#else /* of #if defined(SUPPORT_INET4) && TNUM_TCP4_REPID > 0 */
1503
1504ER
1505tcp_del_rep (ID repid)
1506{
1507
1508 /* TCP 受付口 ID をチェックする。*/
1509 if (VALID_TCP6_REPID(repid))
1510 return tcp6_del_rep_body(repid);
1511 else
1512 return E_ID;
1513
1514 }
1515
1516#endif /* of #if defined(SUPPORT_INET4) && TNUM_TCP4_REPID > 0 */
1517
1518#else /* of #if defined(SUPPORT_INET6) && TNUM_TCP6_REPID > 0 */
1519
1520ER
1521tcp_del_rep (ID repid)
1522{
1523
1524 /* TCP 受付口 ID をチェックする。*/
1525 if (VALID_TCP4_REPID(repid))
1526 return tcp4_del_rep_body(repid);
1527 else
1528 return E_ID;
1529
1530 }
1531
1532#endif /* of #if defined(SUPPORT_INET6) && TNUM_TCP6_REPID > 0 */
1533
1534#endif /* of #ifdef __tcp_del_rep */
1535
1536/*
1537 * tcp_set_opt -- TCP 通信端点オプションの設定【拡張機能】
1538 *
1539 * 注意: 設定可能な TCP 通信端点オプションは無いため、E_PAR が返される。
1540 */
1541
1542#ifdef __tcp_set_opt
1543
1544ER
1545tcp_set_opt (ID cepid, int_t optname, void *optval, int_t optlen)
1546{
1547 T_TCP_CEP *cep;
1548
1549 /* TCP 通信端点 ID をチェックする。*/
1550 if (!VALID_TCP_CEPID(cepid))
1551 return E_ID;
1552
1553 /* TCP 通信端点を得る。*/
1554 cep = GET_TCP_CEP(cepid);
1555
1556 /* TCP 通信端点をチェックする。*/
1557 if (!VALID_TCP_CEP(cep))
1558 return E_NOEXS;
1559
1560 return E_PAR;
1561 }
1562
1563#endif /* of #ifdef __tcp_set_opt */
1564
1565/*
1566 * tcp_get_opt -- TCP 通信端点オプションの設定【拡張機能】
1567 *
1568 * 注意: 設定可能な TCP 通信端点オプションは無いため、E_PAR が返される。
1569 */
1570
1571#ifdef __tcp_get_opt
1572
1573ER
1574tcp_get_opt (ID cepid, int_t optname, void *optval, int_t optlen)
1575{
1576 T_TCP_CEP *cep;
1577
1578 /* TCP 通信端点 ID をチェックする。*/
1579 if (!VALID_TCP_CEPID(cepid))
1580 return E_ID;
1581
1582 /* TCP 通信端点を得る。*/
1583 cep = GET_TCP_CEP(cepid);
1584
1585 /* TCP 通信端点をチェックする。*/
1586 if (!VALID_TCP_CEP(cep))
1587 return E_NOEXS;
1588
1589 return E_PAR;
1590 }
1591
1592#endif /* of #ifdef __tcp_get_opt */
1593
1594#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1595
1596#endif /* of #ifdef SUPPORT_TCP */
Note: See TracBrowser for help on using the repository browser.