source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/tcp_subr_ncs.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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