source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/tcp_subr_ncs.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: 23.6 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 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
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 * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
67 * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.49.2.4 1999/08/29 16:29:55 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 <t_syslog.h>
77#include "kernel_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
87#endif /* of #ifdef TARGET_KERNEL_JSP */
88
89#include <tinet_defs.h>
90#include <tinet_config.h>
91
92#include <net/if.h>
93#include <net/if_ppp.h>
94#include <net/if_loop.h>
95#include <net/ethernet.h>
96#include <net/if_arp.h>
97#include <net/ppp_ipcp.h>
98#include <net/net.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 <netinet6/in6.h>
106#include <netinet6/in6_var.h>
107#include <netinet/in_var.h>
108#include <netinet/ip.h>
109#include <netinet/ip_var.h>
110#include <netinet/ip6.h>
111#include <netinet6/ip6_var.h>
112#include <netinet6/nd6.h>
113#include <netinet/tcp.h>
114#include <netinet/tcp_timer.h>
115#include <netinet/tcp_var.h>
116#include <netinet/tcp_fsm.h>
117#include <netinet/tcp_seq.h>
118#include <netinet/in_itron.h>
119
120#ifdef SUPPORT_TCP
121
122#ifndef TCP_CFG_SWBUF_CSAVE_ONLY
123
124/*
125 * TCP 通信端点の送信ウィンドバッファの省コピー機能が無効
126 */
127
128/*
129 * tcp_read_swbuf -- 送信ウィンドバッファからデータを読み出す。
130 */
131
132void
133tcp_read_swbuf_ncs (T_TCP_CEP *cep, T_NET_BUF *output, uint_t len, uint_t doff)
134{
135 uint8_t *wptr, *rptr;
136
137 /* SDU の大きさをチェックする。*/
138 if (GET_IP_SDU_SIZE(GET_IP_HDR(output)) < GET_TCP_HDR_SIZE2(output, IF_IP_TCP_HDR_OFFSET) + len) {
139 syslog(LOG_INFO, "[TCP] shrink SUD len: %d -> %d",
140 (uint16_t)len, (uint16_t)(GET_IP_SDU_SIZE(GET_IP_HDR(output)) - GET_TCP_HDR_SIZE2(output, IF_IP_TCP_HDR_OFFSET)));
141 len = GET_IP_SDU_SIZE(GET_IP_HDR(output)) - GET_TCP_HDR_SIZE2(output, IF_IP_TCP_HDR_OFFSET);
142 }
143
144 wptr = GET_TCP_SDU(output, IF_IP_TCP_HDR_OFFSET);
145
146 /* 通信端点をロックする。*/
147 syscall(wai_sem(cep->semid_lock));
148
149 rptr = cep->sbuf_rptr + doff;
150 if (rptr - (uint8_t*)cep->sbuf > cep->sbufsz) {
151
152 /* 転送開始が送信ウィンドバッファの終わりを超えるときの処理 */
153 rptr = (uint8_t*)cep->sbuf_rptr - (cep->sbufsz - doff);
154 }
155 else if (len + (rptr - (uint8_t*)cep->sbuf) > cep->sbufsz) {
156 uint_t sub;
157
158 /* 転送範囲がラウンドするときの処理 */
159 sub = (uint_t)(cep->sbufsz - (rptr - (uint8_t*)cep->sbuf));
160 memcpy((void*)wptr, rptr, (size_t)sub);
161 len -= sub;
162 wptr += sub;
163 rptr = (uint8_t*)cep->sbuf;
164 }
165 memcpy((void*)wptr, rptr, (size_t)len);
166
167 NET_COUNT_TCP(net_count_tcp[NC_TCP_SEND_DATA_SEGS], 1);
168 NET_COUNT_TCP(net_count_tcp[NC_TCP_SEND_DATA_OCTETS], len);
169
170 /* 通信端点のロックを解除する。*/
171 syscall(sig_sem(cep->semid_lock));
172 }
173
174/*
175 * tcp_drop_swbuf -- 送信ウィンドバッファから指定されたオクテット分削除する。
176 */
177
178void
179tcp_drop_swbuf_ncs (T_TCP_CEP *cep, uint_t len)
180{
181 uint_t last;
182
183 /* 通信端点をロックする。*/
184 syscall(wai_sem(cep->semid_lock));
185
186 last = cep->swbuf_count;
187
188 if (cep->sbuf_rptr + len > (uint8_t*)cep->sbuf + cep->sbufsz)
189 /* ラウンドするときの計算 */
190 cep->sbuf_rptr -= cep->sbufsz - len;
191 else
192 cep->sbuf_rptr += len;
193 cep->swbuf_count -= (uint16_t)len;
194
195 /* 通信端点のロックを解除する。*/
196 syscall(sig_sem(cep->semid_lock));
197
198#ifdef TCP_CFG_NON_BLOCKING
199
200 if (cep->snd_nblk_tfn == TFN_TCP_GET_BUF) { /* ノンブロッキングコール */
201
202 /* 通信端点をロックする。*/
203 syscall(wai_sem(cep->semid_lock));
204
205 /* 送信データ長を計算する。*/
206 if (cep->sbufsz - cep->swbuf_count > cep->sbufsz - (cep->sbuf_wptr - (uint8_t*)cep->sbuf))
207 /* 書込みポインタがラウンドするときは、書込みポインタから送信ウィンドバッファの終わりまで */
208 len = (uint_t)(cep->sbufsz - (cep->sbuf_wptr - (uint8_t*)cep->sbuf));
209 else
210 len = cep->sbufsz - cep->swbuf_count;
211
212 /* 通信端点のロックを解除する。*/
213 syscall(sig_sem(cep->semid_lock));
214
215 if (len > 0) {
216
217 /* tcp_get_buf の割当て長を設定する。*/
218 cep->get_buf_len = len;
219
220 /* 送信ウィンドバッファのアドレスを返す。*/
221 *cep->snd_p_buf = cep->sbuf_wptr;
222
223 if (IS_PTR_DEFINED(cep->callback))
224#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
225
226 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)(uint32_t)len);
227
228#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
229
230 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)&len);
231
232#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
233
234 else
235 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
236
237 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
238 cep->snd_tskid = TA_NULL;
239 cep->snd_tfn = cep->snd_nblk_tfn = TFN_TCP_UNDEF;
240 }
241 }
242
243#ifdef TCP_CFG_EXTENTIONS
244
245 else if (cep->snd_nblk_tfn == TFN_TCP_SND_DAT ||
246 cep->snd_nblk_tfn == TFN_TCP_SND_OOB) { /* ノンブロッキングコール */
247
248#else /* of #ifdef TCP_CFG_EXTENTIONS */
249
250 else if (cep->snd_nblk_tfn == TFN_TCP_SND_DAT) { /* ノンブロッキングコール */
251
252#endif /* of #ifdef TCP_CFG_EXTENTIONS */
253
254 ER_UINT error;
255
256 /* 送信ウィンドバッファにデータを書き込む。*/
257 error = TCP_WRITE_SWBUF(cep, cep->snd_data, (uint_t)cep->snd_len);
258
259#ifdef TCP_CFG_EXTENTIONS
260
261 /* 送信緊急ポインタを設定する。*/
262 if (cep->snd_nblk_tfn == TFN_TCP_SND_OOB)
263 cep->snd_up = cep->snd_una + error;
264
265#endif /* of #ifdef TCP_CFG_EXTENTIONS */
266
267 if (IS_PTR_DEFINED(cep->callback))
268
269#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
270
271 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)error);
272
273#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
274
275 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)&error);
276
277#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
278
279 else
280 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
281
282 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
283 cep->snd_tskid = TA_NULL;
284 cep->snd_tfn = cep->snd_nblk_tfn = TFN_TCP_UNDEF;
285 }
286 else {
287
288#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
289
290 /* 送信ウィンドバッファに空きが出来たら出力タスクを起床する。*/
291 if (last == cep->sbufsz && cep->swbuf_count < cep->sbufsz)
292 syscall(set_flg(cep->snd_flgid, TCP_CEP_EVT_SWBUF_READY));
293
294#ifdef TCP_CFG_NON_BLOCKING
295
296 }
297
298#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
299
300 if (cep->swbuf_count > 0) {
301 /* 送信ウィンドバッファにデータがあれば出力をポストする。*/
302 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
303 sig_sem(SEM_TCP_POST_OUTPUT);
304 }
305 }
306
307/*
308 * tcp_write_swbuf -- 送信ウィンドバッファにデータを書き込む。
309 */
310
311ER_UINT
312tcp_write_swbuf_ncs (T_TCP_CEP *cep, void *data, uint_t len)
313{
314 uint_t offset;
315
316 /* 通信端点をロックする。*/
317 syscall(wai_sem(cep->semid_lock));
318
319 /* len と送信ウィンドバッファの空きの小さい方を移すデータ数にする。*/
320 if (len > (cep->sbufsz - cep->swbuf_count))
321 len = cep->sbufsz - cep->swbuf_count;
322
323 /* 書き込みポインタがラウンドするときの処理 */
324 if (len > cep->sbufsz - (cep->sbuf_wptr - (uint8_t*)cep->sbuf)) {
325 offset = (uint_t)(cep->sbufsz - (cep->sbuf_wptr -(uint8_t*)cep->sbuf));
326 memcpy(cep->sbuf_wptr, data, (size_t)offset);
327 cep->sbuf_wptr = (uint8_t*)cep->sbuf;
328 cep->swbuf_count += offset;
329 }
330 else
331 offset = 0;
332
333 memcpy(cep->sbuf_wptr, (void*)((uint8_t*)data + offset), (size_t)(len - offset));
334 cep->sbuf_wptr += len - offset;
335 cep->swbuf_count += len - offset;
336
337 /* 通信端点のロックを解除する。*/
338 syscall(sig_sem(cep->semid_lock));
339
340 return (ER_UINT)len;
341 }
342
343/*
344 * tcp_wait_swbuf -- 送信ウィンドバッファが空くのを待つ。
345 */
346
347ER
348tcp_wait_swbuf_ncs (T_TCP_CEP *cep, TMO tmout)
349{
350 ER error;
351 FLGPTN flag;
352
353 while (cep->swbuf_count >= cep->sbufsz) {
354 /*
355 * 送信ウィンドバッファの空きがなければ、出力をポストして、
356 * 送信ウィンドバッファが空くまで待つ。
357 */
358 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
359 sig_sem(SEM_TCP_POST_OUTPUT);
360
361 if ((error = twai_flg(cep->snd_flgid, TCP_CEP_EVT_SWBUF_READY, TWF_ORW, &flag, tmout)) != E_OK) {
362 return error;
363 }
364 syscall(clr_flg(cep->snd_flgid, (FLGPTN)(~TCP_CEP_EVT_SWBUF_READY)));
365
366 /*
367 * 送信できるか、CEP の FSM 状態を見る。
368 * 送信ウィンドバッファが空くまで待つ間に、送信不能になった場合は、
369 * コネクションが切断されたことを意味している。
370 */
371 if (!TCP_FSM_CAN_SEND_MORE(cep->fsm_state)) {
372 return E_CLS;
373 }
374 }
375
376 return E_OK;
377 }
378/*
379 * tcp_get_swbuf_addr -- 送信ウィンドバッファの空きアドレスを獲得する。
380 */
381
382ER_UINT
383tcp_get_swbuf_addr_ncs (T_TCP_CEP *cep, void **p_buf)
384{
385 uint_t len;
386
387 /* 通信端点をロックする。*/
388 syscall(wai_sem(cep->semid_lock));
389
390 /* 送信ウィンドバッファの空きアドレスの先頭を設定する。*/
391 *p_buf = cep->sbuf_wptr;
392
393 /* 送信ウィンドバッファの空きサイズを計算する。*/
394 if (cep->sbufsz - cep->swbuf_count > cep->sbufsz - (cep->sbuf_wptr - (uint8_t*)cep->sbuf))
395 /* 書込みポインタがラウンドするときは、書込みポインタから送信ウィンドバッファの終わりまで */
396 len = (uint_t)(cep->sbufsz - (cep->sbuf_wptr - (uint8_t*)cep->sbuf));
397 else
398 len = cep->sbufsz - cep->swbuf_count;
399
400 /* 通信端点のロックを解除する。*/
401 syscall(sig_sem(cep->semid_lock));
402
403 /* 送信ウィンドバッファの空きデータ長を設定し、その値を返す。*/
404 cep->get_buf_len = len;
405 return (ER_UINT)len;
406 }
407
408/*
409 * tcp_send_swbuf -- 送信ウィンドバッファのデータを送信可能にする。
410 */
411
412void
413tcp_send_swbuf_ncs (T_TCP_CEP *cep, uint_t len)
414{
415 /* 通信端点をロックする。*/
416 syscall(wai_sem(cep->semid_lock));
417
418 cep->sbuf_wptr += len;
419 cep->swbuf_count += len;
420
421 /* 書込みポインタがラウンドするときの処理 */
422 if (cep->sbuf_wptr >= (uint8_t*)cep->sbuf + cep->sbufsz)
423 cep->sbuf_wptr = (uint8_t*)cep->sbuf;
424
425 /* tcp_get_buf の割当て長をリセットする。*/
426 cep->get_buf_len = 0;
427
428 /* 通信端点のロックを解除する。*/
429 syscall(sig_sem(cep->semid_lock));
430
431 /* 送信ウィンドバッファがフルのときは強制的に送信する。*/
432 if (cep->swbuf_count >= cep->sbufsz)
433 cep->flags |= TCP_CEP_FLG_FORCE | TCP_CEP_FLG_FORCE_CLEAR;
434 }
435
436/*
437 * tcp_is_swbuf_full -- 送信ウィンドバッファが満杯かチェックする。
438 */
439
440bool_t
441tcp_is_swbuf_full_ncs (T_TCP_CEP *cep)
442{
443 return cep->swbuf_count >= cep->sbufsz;
444 }
445
446#endif /* of #ifndef TCP_CFG_SWBUF_CSAVE_ONLY */
447
448#ifndef TCP_CFG_RWBUF_CSAVE_ONLY
449
450/*
451 * TCP 通信端点の受信ウィンドバッファの省コピー機能が無効
452 */
453
454/*
455 * tcp_drop_rwbuf -- 受信ウィンドバッファから指定されたオクテット分削除する。
456 */
457
458void
459tcp_drop_rwbuf_ncs (T_TCP_CEP *cep, uint_t len)
460{
461 cep->rwbuf_count -= len;
462 cep->rbuf_rptr += len;
463
464 /* 読み出しポインタがラウンドするときの処理 */
465 if (cep->rbuf_rptr >= (uint8_t*)cep->rbuf + cep->rbufsz)
466 cep->rbuf_rptr = (uint8_t*)cep->rbuf;
467 }
468
469/*
470 * tcp_read_rwbuf -- 受信ウィンドバッファから指定されたオクテット分読み出す。
471 */
472
473uint_t
474tcp_read_rwbuf_ncs (T_TCP_CEP *cep, void *data, uint_t len)
475{
476 uint_t offset;
477
478 /* 通信端点をロックする。*/
479 syscall(wai_sem(cep->semid_lock));
480
481 /* len と受信ウィンドバッファのデータ数の小さい方を取り出すデータ数にする。*/
482 if (len > cep->rwbuf_count)
483 len = cep->rwbuf_count;
484
485 /* 読み出しポインタがラウンドするときの処理 */
486 if (len > cep->rbufsz - (cep->rbuf_rptr - (uint8_t*)cep->rbuf)) {
487 offset = (uint_t)(cep->rbufsz - (cep->rbuf_rptr -(uint8_t*)cep->rbuf));
488 memcpy(data, cep->rbuf_rptr, (size_t)offset);
489 cep->rwbuf_count -= offset;
490 cep->rbuf_rptr = (uint8_t*)cep->rbuf;
491 }
492 else
493 offset = 0;
494
495 memcpy((void*)((uint8_t*)data + offset), cep->rbuf_rptr, (size_t)(len - offset));
496 cep->rwbuf_count -= len - offset;
497 cep->rbuf_rptr += len - offset;
498
499 /* 通信端点のロックを解除する。*/
500 syscall(sig_sem(cep->semid_lock));
501
502 return len;
503 }
504
505/*
506 * tcp_get_rwbuf_addr -- 受信ウィンドバッファの空きアドレスを獲得する。
507 */
508
509uint_t
510tcp_get_rwbuf_addr_ncs (T_TCP_CEP *cep, void **p_buf)
511{
512 uint_t len;
513
514 /* 通信端点をロックする。*/
515 syscall(wai_sem(cep->semid_lock));
516
517 /* 受信ウィンドバッファのデータ長を計算する。*/
518 if (cep->rwbuf_count > cep->rbufsz - (cep->rbuf_rptr - (uint8_t*)cep->rbuf))
519 /* ポインタがラウンドするときは受信ウィンドバッファの終わりまで */
520 len = (uint_t)(cep->rbufsz - (cep->rbuf_rptr - (uint8_t*)cep->rbuf));
521 else
522 len = cep->rwbuf_count;
523
524 /* 受信ウィンドバッファのデータのアドレスの先頭を設定する。*/
525 *p_buf = cep->rbuf_rptr;
526
527 /* 通信端点のロックを解除する。*/
528 syscall(sig_sem(cep->semid_lock));
529
530 /* 受信ウィンドバッファのデータ長を設定し、その値を返す。*/
531 cep->rcv_buf_len = len;
532 return len;
533 }
534
535/*
536 * tcp_write_rwbuf -- 受信ウィンドバッファにデータを書き込む。
537 *
538 * 注意:
539 * 入力 input は、T_TCP_Q_HDR によりリンクされ、
540 * 並べ替えが終了していなければならない。また、
541 * 追加するデータは、受信ウィンドバッファに収まること。
542 */
543
544void
545tcp_write_rwbuf_ncs (T_TCP_CEP *cep, T_NET_BUF *input, uint_t thoff)
546{
547 T_TCP_Q_HDR *qhdr;
548 uint_t offset, inlen, last;
549
550 /* 通信端点をロックする。*/
551 syscall(wai_sem(cep->semid_lock));
552
553 qhdr = (T_TCP_Q_HDR*)GET_TCP_HDR(input, thoff);
554
555 /* 受信済みシーケンス番号を更新する。*/
556 cep->rcv_nxt += qhdr->slen;
557
558 last = cep->rwbuf_count;
559 inlen = qhdr->slen;
560
561 /* 緊急データの SDU 補正を行う。*/
562 if (qhdr->urp > 0 && inlen > 0) {
563 inlen -= qhdr->urp;
564 qhdr->slen -= qhdr->urp;
565 qhdr->urp = 0;
566 }
567
568 /*
569 * FIN フラグが付いたセグメントは inlen == 0 になることもある。
570 * これは、アプリケーションに、相手からこれ以上データが送られて
571 * こないことを知らせるためである。
572 */
573 if (inlen > 0) {
574
575 /* 書き込みポインタがラウンドするときの処理 */
576 if (inlen > cep->rbufsz - (cep->rbuf_wptr - (uint8_t*)cep->rbuf)) {
577 offset = (uint_t)(cep->rbufsz - (cep->rbuf_wptr - (uint8_t*)cep->rbuf));
578 memcpy(cep->rbuf_wptr, (void*)(GET_TCP_SDU(input, thoff) + qhdr->soff), (size_t)offset);
579 cep->rbuf_wptr = (uint8_t*)cep->rbuf;
580 cep->rwbuf_count += offset;
581 inlen -= offset;
582 }
583 else
584 offset = 0;
585
586 memcpy(cep->rbuf_wptr, (void*)(GET_TCP_SDU(input, thoff) + qhdr->soff + offset), (size_t)inlen);
587 cep->rbuf_wptr += inlen;
588 cep->rwbuf_count += inlen;
589
590 NET_COUNT_TCP(net_count_tcp[NC_TCP_RECV_DATA_SEGS], 1);
591 NET_COUNT_TCP(net_count_tcp[NC_TCP_RECV_DATA_OCTETS], inlen);
592 }
593
594 syscall(rel_net_buf(input));
595
596#ifdef TCP_CFG_NON_BLOCKING
597
598 if (cep->rcv_nblk_tfn == TFN_TCP_RCV_BUF) { /* ノンブロッキングコール */
599
600 int_t len;
601
602 /* 受信ウィンドバッファの空きデータ長を計算する。*/
603 if (cep->rwbuf_count > cep->rbufsz - (cep->rbuf_rptr - (uint8_t*)cep->rbuf)) {
604 /* ポインタがラウンドするときは受信ウィンドバッファの終わりまで */
605 len = (uint_t)(cep->rbufsz - (cep->rbuf_rptr - (uint8_t*)cep->rbuf));
606 }
607 else
608 len = cep->rwbuf_count;
609
610 /* 通信端点のロックを解除する。*/
611 syscall(sig_sem(cep->semid_lock));
612
613 /*
614 * FIN フラグが付いたセグメントは inlen == 0 になることもある。
615 * これは、アプリケーションに、相手からこれ以上データが送られて
616 * こないことを知らせるためである。
617 */
618 if (len > 0 || inlen == 0) {
619
620 /* tcp_rcv_buf の割当て長を設定する。*/
621 cep->rcv_buf_len = len;
622
623 /* 受信ウィンドバッファのアドレスを返す。*/
624 *cep->rcv_p_buf = cep->rbuf_rptr;
625
626
627 if (IS_PTR_DEFINED(cep->callback))
628
629#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
630
631 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)(uint32_t)len);
632
633#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
634
635 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
636
637#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
638
639 else
640 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
641
642 if (len == 0) {
643
644 /*
645 * 通信端点をロックして、
646 * 受信ウィンドバッファキューのネットワークバッファを解放する。
647 */
648 syscall(wai_sem(cep->semid_lock));
649 TCP_FREE_RWBUFQ(cep);
650 syscall(sig_sem(cep->semid_lock));
651 }
652 }
653
654 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
655 cep->rcv_tskid = TA_NULL;
656 cep->rcv_tfn = cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
657 }
658
659 else if (cep->rcv_nblk_tfn == TFN_TCP_RCV_DAT) { /* ノンブロッキングコール */
660 ER_UINT len;
661
662 /* 通信端点のロックを解除する。*/
663 syscall(sig_sem(cep->semid_lock));
664
665 /* 受信ウィンドバッファからデータを取り出す。*/
666 if ((len = TCP_READ_RWBUF(cep, cep->rcv_data, (uint_t)cep->rcv_len)) > 0) {
667 /* 相手にウィンドウサイズが変わったことを知らせるため出力をポストする。*/
668 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
669 sig_sem(SEM_TCP_POST_OUTPUT);
670 }
671
672 /*
673 * FIN フラグが付いたセグメントは inlen == 0 になることもある。
674 * これは、アプリケーションに、相手からこれ以上データが送られて
675 * こないことを知らせるためである。
676 */
677 if (len > 0 || inlen == 0) {
678
679 if (IS_PTR_DEFINED(cep->callback))
680
681#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
682
683 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)(uint32_t)len);
684
685#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
686
687 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
688
689#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
690
691 else
692 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
693 }
694
695 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
696 cep->rcv_tskid = TA_NULL;
697 cep->rcv_tfn = cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
698
699 }
700 else {
701
702#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
703
704 /* 通信端点のロックを解除する。*/
705 syscall(sig_sem(cep->semid_lock));
706
707 if (inlen == 0 && cep->rwbuf_count == 0) {
708 /*
709 * 受信ウィンドバッファ内のデータ数が 0 で、
710 * 相手から FIN フラグが付いたセグメントを受信したときは、
711 * 通信端点をロックして、
712 * 受信ウィンドバッファキューのネットワークバッファを解放する。
713 */
714 syscall(wai_sem(cep->semid_lock));
715 TCP_FREE_RWBUFQ(cep);
716 syscall(sig_sem(cep->semid_lock));
717 }
718
719 /*
720 * 受信ウィンドバッファにデータが入るか、 inlen == 0 の時、入力タスクを起床する。
721 * FIN フラグが付いたセグメントは inlen == 0 になることもある。
722 * これは、アプリケーションに、相手からこれ以上データが送られて
723 * こないことを知らせるためである。
724 */
725 if ((last == 0 && cep->rwbuf_count > 0) || inlen == 0)
726 syscall(set_flg(cep->rcv_flgid, TCP_CEP_EVT_RWBUF_READY));
727
728#ifdef TCP_CFG_NON_BLOCKING
729
730 }
731
732#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
733
734 }
735
736#endif /* of #ifndef TCP_CFG_RWBUF_CSAVE_ONLY */
737
738#endif /* of #ifdef SUPPORT_TCP */
Note: See TracBrowser for help on using the repository browser.