📄 tcpss.c
字号:
/* Since we are setting the FIN bit we must
bump the tcp_data_len for this packet. This
length is used during seq number and ack
comparrision. */
(prt->out.nextPacket->mem_tcp_data_len)++;
/* Save a pointer to the next packet to send. Then move
the next pointer forward. nextPacket should always
be NULL after these steps. */
buf_ptr = prt->out.nextPacket;
prt->out.nextPacket = prt->out.nextPacket->next;
/* Clear the event flag. */
prt->xmitFlag = NU_CLEAR;
/* Send the buffer. */
TCP_Xmit(prt, buf_ptr);
}
prt->state = SFW1; /* wait for ACK of FIN */
return_status = -1;
}
break; /* do nothing for now ?*/
case SCWAIT: /* other side already closed */
/* Send the FIN. */
if (prt->out.nextPacket == NU_NULL)
{
prt->out.tcp_flags = TFIN | TACK;
TCPSS_Send_SYN_FIN(prt, 0);
}
else
{
if (prt->xmitFlag == NU_SET)
{
UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);
prt->out.tcp_flags = TPUSH | TACK | TFIN;
/* Since we are setting the FIN bit we must
bump the tcp_data_len for this packet. This
length is used during seq number and ack
comparrision. */
(prt->out.nextPacket->mem_tcp_data_len)++;
/* Save a pointer to the next packet to send. Then move
the next pointer forward. nextPacket should always
be NULL after these steps. */
buf_ptr = prt->out.nextPacket;
prt->out.nextPacket = prt->out.nextPacket->next;
/* Clear the event flag. */
prt->xmitFlag = NU_CLEAR;
/* Send the buffer. */
TCP_Xmit(prt, buf_ptr);
}
}
/* Deallocate any date that is in the in window. */
if (sock_ptr->s_recvbytes)
{
MEM_Buffer_Cleanup(&sock_ptr->s_recvlist);
}
/* Update the connection state. */
prt->state = SLAST;
return_status = -1;
break;
case STWAIT: /* time out yet? */
if (INT32_CMP( (TCP_Ports[pnum]->out.lasttime + WAITTIME),
NU_Retrieve_Clock()) < 0)
{
prt->state = SCLOSED;
}
/* Upon returning the socket will be released. So break
the port's link to this socket. */
prt->p_socketd = -1;
return_status = NU_SUCCESS;
break;
case SLAST:
/* If the state is SLAST, then a FIN has already been sent. We
are waiting for an ACK. If one is not received the
retransmit timeout will eventually close this connection.
*/
return_status = -1;
break;
case SCLOSING:
case SCLOSED:
/* Upon returning the socket will be released. So break
the port's link to this socket. */
prt->p_socketd = -1;
return_status = NU_SUCCESS;
break;
default:
break;
}
}
else
{
return (1);
}
return (return_status);
} /* end TCPSS_Net_Close() */
/*************************************************************************
*
* FUNCTION
*
* TCPSS_Window_Probe
*
* DESCRIPTION
*
* Time out for three seconds. Then if the window has not been
* updated send a 1 byte packet(windowprobe).
*
* INPUTS
*
* *prt Pointer to a port.
* nbytes The number of bytes in the buffer parameter.
* *buffer Pointer to a data buffer.
*
* OUTPUTS
*
* The number of bytes that were sent in window probes.
*
*************************************************************************/
static INT32 TCPSS_Window_Probe(TCP_PORT *prt, UINT16 nbytes, UINT8 HUGE *buffer)
{
UINT16 nsent = 0;
NET_BUFFER *buf_ptr = NU_NULL;
/* Set the probe flag. */
prt->probeFlag = NU_SET;
/* Set a timer event to resume this task. */
UTL_Timerset(WINPROBE, (UNSIGNED)prt->p_socketd, PROBETIMEOUT, 0);
/* Probe the foreign host while he is advertising a window size of 0. */
while(prt->out.size == 0)
{
/* Preserve the the task pointer. */
SCK_Sockets[prt->p_socketd]->s_TXTask = NU_Current_Task_Pointer();
/* Suspend this task. */
SCK_Suspend_Task(SCK_Sockets[prt->p_socketd]->s_TXTask);
SCK_Sockets[prt->p_socketd]->s_TXTask = NU_NULL;
/* If a close was initiated while suspension was in effect abort
the window probe. */
if (prt->state != SEST)
return(NU_NOT_ESTAB);
/* if the windowsize is still zero and no unacknowledged data has been
* sent and the buffer has untransmitted data, then send a window
* probe. We depend on the retransmit logic to resend the window probe
* until either the probe is acknowledged or the window is opened. */
if( (prt->out.size == 0) && (prt->out.contain == 0) && (nsent < nbytes))
{
buf_ptr = (NET_BUFFER *)MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);
if (buf_ptr != NU_NULL)
{
/* Point the data pointer at an offset into the buffer large
enough to leave room for the header information. */
buf_ptr->data_ptr = buf_ptr->mem_parent_packet +
NET_MAX_TCP_HEADER_SIZE;
/* move the data into the packet buffer */
memcpy(buf_ptr->data_ptr, buffer, 1);
/* Initialize the data length of this buffer. */
buf_ptr->data_len = 1;
buf_ptr->mem_tcp_data_len = 1;
buf_ptr->mem_total_data_len = 1;
buf_ptr->mem_option_len = 0;
/* Initialize the list that this packet will be deallocated to when
transmission is complete.
*/
buf_ptr->mem_dlist = &prt->out.packet_list;
buf_ptr->mem_port_index = prt->pindex;
/* Update the amount of data in this port. */
prt->out.contain++;
/* Update the number of packets in this port. */
prt->out.num_packets++;
/* Increment the number of bytes we have sent so far. */
nsent++;
/* Move the location from which we are copying forward. */
buffer++;
/* Send the completed Packet. */
TCP_Xmit(prt, buf_ptr);
}
}
else if (prt->out.size > 0)
break;
/* Set a timer event to resume this task just before the retransmits
is about finishing. */
UTL_Timerset(WINPROBE, (UNSIGNED)prt->p_socketd,
(UNSIGNED)(prt->p_rto - 1),0);
/* reset retransmits number, make the probing forever. MQ */
if (buf_ptr)
buf_ptr->mem_retransmits = 1;
}
/* At this point if there is a packet on the outgoing packet list. Then
* that means the foreign host opened up his window without
* acknowledging the window probe. Since the probe contains the next byte
* expected by the foreign host, go ahead and retransmit it. Otherwise, an
* out of order packet situation will occur and it will take longer to fully
* recover from the 0 windowsize. */
if (prt->out.packet_list.head != NU_NULL)
{
/* Clear the timer that will retransmit the window probe. */
UTL_Timerunset(WINPROBE, (UNSIGNED)prt->p_socketd, (INT32)1);
TCP_Retransmit(prt, prt->out.packet_list.head->mem_seqnum);
}
/* Clear the probe flag. */
prt->probeFlag = NU_CLEAR;
return(nsent);
} /* end TCPSS_Window_Probe() */
/************************************************************************
*
* FUNCTION
*
* TCPSS_Net_Send
*
* DESCRIPTION
*
* This function examines the ports outwindow and sends the data
* that is queued in the windows packet_list. All of the data may
* not be sent immediately. The decision to send data immediately
* or to hold off is based on the Nagle Algorithm
* (RFC 1122, page 98).
*
* INPUTS
*
* *prt Pointer to a port.
* *buf_ptr
*
* OUTPUTS
*
* The number of bytes that were sent.
*
*************************************************************************/
static STATUS TCPSS_Net_Send(TCP_PORT *prt, NET_BUFFER *buf_ptr)
{
STATUS nsent = 0, status;
TCP_WINDOW *wind;
wind = &prt->out;
/* Check to see if the PUSH flag has been set (i.e., the Nagle Algorithm
has been disabled). If so send every packet immediately with the
push flag set. */
if(wind->push)
{
prt->out.tcp_flags |= TPUSH;
/* Send the packet. */
if ((status = TCP_Xmit(prt, buf_ptr)) == NU_SUCCESS)
/* Return the number of data bytes sent. */
nsent = (STATUS)buf_ptr->mem_total_data_len;
else
/* Return the error value. */
nsent = status;
}
/* Should the next packet be sent? This decision is based on the Nagle
* Algorithm (RFC 1122, page 98). Following are the four cases when a
* packet should be sent:
* 1) If a maximum size packet can be sent.
* 2) If there is no unacknowledged data and the data is pushed and
* all queued data can be sent. Note that at this point all queued
* data can be sent, else it would not be queued.
* 3) If there is no unacknowledged data and some specified fraction of
* the maximum windowsize can be sent. In this case we send if at
* least half the max windowsize can be sent.
* 4) If the data is pushed and an override timeout occurs.
*/
else if( (buf_ptr->mem_total_data_len >= prt->sendsize) ||
(wind->nxt == wind->ack) ||
((wind->nxt == wind->ack) && (buf_ptr->mem_total_data_len >=
(prt->maxSendWin >> 1))) )
{
/* Send the packet. */
if ((status = TCP_Xmit(prt, buf_ptr)) == NU_SUCCESS)
/* Return the number of data bytes sent. */
nsent = (UINT16) buf_ptr->mem_total_data_len;
else
/* Return the error value. */
nsent = status;
}
/* Return the number of data bytes that were sent. */
return(nsent);
} /* end TCPSS_Net_Send() */
#endif /* INCLUDE_TCP == NU_TRUE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -