📄 tcp_data.c
字号:
/* Check if extent of received data has been extended. */ /*-----------------------------------------------------------------*/ if (RxBuf->app_len) { /*---------------------------------------------------------------*/ /* Increment receive sequence numbers and buffer count. */ /*---------------------------------------------------------------*/ sock->rcv_nxt += RxBuf->app_len; sock->rb_count += RxBuf->app_len; sock->rcv_win -= RxBuf->app_len; /*---------------------------------------------------------------*/ /* Mark buffer as holding socket data. */ /*---------------------------------------------------------------*/ RxBuf->flush = sock; TcpAssert(RxBuf->seg_record == NULL); /*---------------------------------------------------------------*/ /* Append buffer to socket receive queue. */ /*---------------------------------------------------------------*/ RxBuf->next = NULL; if (sock->rq_head == NULL) sock->rq_head = RxBuf; else sock->rq_tail->next = RxBuf; sock->rq_tail = RxBuf; /*---------------------------------------------------------------*/ /* Append buffer to end of free list and prevent later free. */ /*---------------------------------------------------------------*/ tcpRetRcvBuf(RxBuf); RxBuf = NULL; /*---------------------------------------------------------------*/ /* Check if out of order segments have been received. */ /*---------------------------------------------------------------*/ if (sock->oosq) { SegRecord *seg_record = sock->oosq; /*-------------------------------------------------------------*/ /* For fast recovery, acknowledge segments that close gaps. */ /*-------------------------------------------------------------*/ sock->flags |= SF_SENDFLG; /*-------------------------------------------------------------*/ /* Check if queued segment records close additional gaps. */ /*-------------------------------------------------------------*/ while (SEQ_LE(seg_record->seq, sock->rcv_nxt)) { int overlap = sock->rcv_nxt - seg_record->seq; int len = seg_record->len - overlap; NetBuf *buf = seg_record->buf; /*-----------------------------------------------------------*/ /* Check if segment record extends the sequence space. */ /*-----------------------------------------------------------*/ if (len > 0) { sock->rcv_nxt += len; sock->rb_count += len; sock->rcv_win -= len; /*---------------------------------------------------------*/ /* Check if segment record has an attached buffer. */ /*---------------------------------------------------------*/ if (buf) { /*-------------------------------------------------------*/ /* Trim any duplicate data from beginning of buffer. */ /*-------------------------------------------------------*/ if (overlap) TcpTrimBeg(buf, overlap); /*-------------------------------------------------------*/ /* Append buffer to (guaranteed non-empty) socket queue. */ /*-------------------------------------------------------*/ buf->next = NULL; sock->rq_tail->next = buf; sock->rq_tail = buf; /*-------------------------------------------------------*/ /* Mark that buffer is no longer on segment queue. */ /*-------------------------------------------------------*/ buf->seg_record = NULL; } } /*-----------------------------------------------------------*/ /* Else, in preparation for freeing the segment record, if */ /* there is an attached buffer, clear the flush flag. */ /*-----------------------------------------------------------*/ else { if (buf) { buf->flush = NULL; buf->seg_record = NULL; } } /*-----------------------------------------------------------*/ /* Free record used by queue head and advance to next entry. */ /*-----------------------------------------------------------*/ sock->oosq = seg_record->next; seg_record->next = FreeRecQ; FreeRecQ = seg_record; seg_record = sock->oosq; if (seg_record == NULL) break; } /*-------------------------------------------------------------*/ /* Set TCPF_FIN if FIN and all earlier data received. */ /*-------------------------------------------------------------*/ if ((sock->flags & SF_OOOFIN) && SEQ_GE(sock->rcv_nxt, sock->ooo_fin)) { TcpFreeOoQ(sock); Net.Tcp->flags |= TCPF_FIN; } } /*---------------------------------------------------------------*/ /* Schedule delayed acknowledgment. */ /*---------------------------------------------------------------*/ NetTimerStart(&sock->ack_tmr, ACK_DELAY); /*---------------------------------------------------------------*/ /* Clipping to buffer, not announced window, may cause underrun. */ /*---------------------------------------------------------------*/ if (sock->rcv_win < 0) sock->rcv_win = 0; /*---------------------------------------------------------------*/ /* Unblock waiting readers by posting "data received" event. */ /*---------------------------------------------------------------*/ NetPostEvent(sock, SE_DATA_RCVD); } /*-----------------------------------------------------------------*/ /* If FIN, advance sequence and flag ACK needed/receiver closed. */ /*-----------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_FIN) { ++sock->rcv_nxt; sock->flags |= SF_GOTFIN | SF_SENDFLG; NetPostEvent(sock, SE_GOT_FIN); } } /*-------------------------------------------------------------------*/ /* Else segment has been received out of order. */ /*-------------------------------------------------------------------*/ else { /*-----------------------------------------------------------------*/ /* If segment has FIN, set flag and remember sequence number. */ /*-----------------------------------------------------------------*/ if (Net.Tcp->flags & TCPF_FIN) { sock->flags |= SF_OOOFIN; sock->ooo_fin = Net.Tcp->seq_num + RxBuf->app_len; } /*-----------------------------------------------------------------*/ /* If data, add buffer to received out-of-order queue. */ /*-----------------------------------------------------------------*/ if (RxBuf->app_len) add_seg(sock); /*-----------------------------------------------------------------*/ /* Acknowledge segments received out of order. */ /*-----------------------------------------------------------------*/ sock->flags |= SF_SENDFLG; } return 0;}/***********************************************************************//* TcpFlush: Copy segment data to socket's receive buffer *//* *//* Note: Handles case where data region straddles the end and *//* beginning of the socket receive buffer *//* *//***********************************************************************/void TcpFlush(NetBuf *buf){ SOCKET sock = buf->flush; int length, rcvoff; struct tcp *tcp = buf->ip_data; /*-------------------------------------------------------------------*/ /* If in OOS queue, clear associated buffer pointer. */ /*-------------------------------------------------------------------*/ if (buf->seg_record) { ((SegRecord *)buf->seg_record)->buf = NULL; buf->seg_record = NULL; } /*-------------------------------------------------------------------*/ /* Else unlink buffer from socket receive queue. */ /*-------------------------------------------------------------------*/ else { NetBuf *ptr, *prev = NULL; for (ptr = sock->rq_head; ptr != buf; ptr = ptr->next) { prev = ptr; TcpAssert(ptr); } if (prev) prev->next = buf->next; else sock->rq_head = buf->next; if (sock->rq_tail == buf) sock->rq_tail = prev; } /*-------------------------------------------------------------------*/ /* Calculate the data's offset into the socket receive buffer. */ /*-------------------------------------------------------------------*/ rcvoff = sock->rb_start + (tcp->seq_num - sock->rd_nxt); if (rcvoff >= sock->rb_size) rcvoff -= sock->rb_size; /*-------------------------------------------------------------------*/ /* Flush application data to socket buffer. */ /*-------------------------------------------------------------------*/ length = buf->app_len; if ((rcvoff + length) <= sock->rb_size) { memcpy(&sock->rbuf[rcvoff], buf->app_data, length); } else { int len1 = sock->rb_size - rcvoff; memcpy(&sock->rbuf[rcvoff], buf->app_data, len1); memcpy(&sock->rbuf[0], buf->app_data + len1, length - len1); } /*-------------------------------------------------------------------*/ /* Clear buffer's flush flag/pointer. */ /*-------------------------------------------------------------------*/ buf->flush = NULL;}/***********************************************************************//* TcpTrimBeg: Trims specified number of data bytes from front *//* *//* Inputs: buf = pointer to buffer being trimmed *//* todrop = number of bytes to drop *//* *//***********************************************************************/void TcpTrimBeg(NetBuf *buf, int todrop){ struct tcp *tcp = buf->ip_data; /*-------------------------------------------------------------------*/ /* Adjust segment's starting sequence number. */ /*-------------------------------------------------------------------*/ tcp->seq_num += todrop; /*-------------------------------------------------------------------*/ /* Adjust data pointer and length. */ /*-------------------------------------------------------------------*/ buf->app_data += todrop; buf->length -= todrop; buf->app_len -= todrop;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -