📄 tcp.c
字号:
return(-1);
}
}
/********************************************************************************
Function: tcp_poll
Parameters: void
Return val: void
Date: 19.7.2002
Desc: Poll TCP sockets for timeout
*********************************************************************************/
void tcp_poll (void)
{
struct tcb* soc;
static UINT8 handle = 0;
UINT8 i;
INT32 temp;
UINT8 old_retries;
if(handle >= NO_OF_TCPSOCKETS)
handle = 0;
for(i=0; i < NO_OF_TCPSOCKETS; i++ )
{
if(handle >= NO_OF_TCPSOCKETS)
handle = 0;
soc = &TCPSocket[handle];
switch(soc->state)
{
case TCP_STATE_FREE:
case TCP_STATE_RESERVED:
case TCP_STATE_CLOSED:
case TCP_STATE_LISTENING:
break;
case TCP_STATE_CONNECTED:
/* In CONNECTED State we have */
/* something to do only if we have unacked data */
/* or if connection has been IDLE too long or */
/* unserved close is isuued by user */
/* or we want to keep lower layer alive */
/* if(soc->send_next > soc->send_unacked)
temp = soc->send_next - soc->send_unacked;
else
temp = soc->send_unacked - soc->send_next;
*/
temp = soc->send_next - soc->send_unacked;
/* Unserved Close? */
if(soc->flags & TCP_INTFLAGS_CLOSEPENDING)
{
/* Can we send the close now */
if(temp == 0)
{
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_FIN;
soc->send_next++;
tcp_sendcontrol(handle);
tcp_newstate(soc, TCP_STATE_FINW1);
soc->flags ^= TCP_INTFLAGS_CLOSEPENDING;
handle++;
return;
}
}
/* Socket timeout? */
if(check_timer(soc->persist_timerh) == 0)
{
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_FIN;
soc->send_next++;
tcp_sendcontrol(handle);
tcp_newstate(soc, TCP_STATE_FINW1);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_CLOSE, soc->rem_ip, soc->remport);
handle++;
return;
}
/* Is there unacked data? */
if(temp == 0)
{
/* Make sure we do not enter to retransmit imidiately when data */
/* But if ARP is not ready ensure fast retransmit */
if( arp_keepcache(soc->rem_ip) < 0 )
init_timer(soc->retransmit_timerh, TCP_INIT_RETRY_TOUT);
else
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
break;
}
/* Is there timeout? */
if( check_timer(soc->retransmit_timerh) != 0 )
break;
DEBUGOUT("Timeout on CONNECTED State\r\n");
/* De we have retries left */
if(soc->retries_left == 0)
{
/* No retries, must reset */
DEBUGOUT("Retries used up, resetting\r\n");
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(handle);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
handle++;
return;
}
soc->retries_left--;
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
/* Yep, there is unacked data */
/* Application should send the old data */
if(temp>soc->send_mtu)
temp = soc->send_mtu;
/* Rewind Send Next because the send process will adjust it */
/* So cheat the tcp_send to think there is no unacked data */
soc->send_next = soc->send_unacked;
/* tcp_send will set the retries_left to maximum but this is */
/* retransmitting already so we need to retain it in order to */
/* avoid dead-lock */
old_retries = soc->retries_left;
temp = soc->event_listener(handle, TCP_EVENT_REGENERATE, (UINT32)temp, 0);
soc->retries_left = old_retries;
if(temp <= 0)
{
/* No data by application, must be something wrong */
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(handle);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
handle++;
return;
}
/* Application has send data */
handle++;
return;
case TCP_STATE_SYN_SENT:
case TCP_STATE_SYN_RECEIVED:
/* Is there timeout? */
if( check_timer(soc->retransmit_timerh) != 0 )
break;
DEBUGOUT("Timeout\r\n");
/* Yep, timeout. Is there reties left? */
if( soc->retries_left )
{
soc->retries_left--;
if(soc->state == TCP_STATE_SYN_SENT)
init_timer(soc->retransmit_timerh, TCP_SYN_RETRY_TOUT);
else
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
tcp_sendcontrol(handle);
handle++;
return;
}
else
{
/* Retries used up */
DEBUGOUT("Retries used up, resetting\r\n");
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(handle);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
handle++;
return;
}
break;
case TCP_STATE_TIMED_WAIT:
/* Is there timeout? */
if( check_timer(soc->retransmit_timerh) != 0 )
break;
DEBUGOUT("Timeout\r\n");
if(soc->retries_left)
{
soc->retries_left--;
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
break;
}
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
break;
case TCP_STATE_LAST_ACK:
case TCP_STATE_FINW1:
case TCP_STATE_CLOSING:
/* Is there timeout? */
if( check_timer(soc->retransmit_timerh) != 0 )
break;
DEBUGOUT("Timeout\r\n");
/* Yep, timeout. Is there reties left? */
if( soc->retries_left )
{
soc->retries_left--;
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
soc->myflags = TCP_FLAG_FIN | TCP_FLAG_ACK;
tcp_sendcontrol(handle);
handle++;
return;
}
else
{
/* Retries used up */
DEBUGOUT("Retries used up, resetting\r\n");
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(handle);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
handle++;
return;
}
break;
case TCP_STATE_FINW2:
/* Is there timeout? */
if( check_timer(soc->retransmit_timerh) != 0 )
break;
DEBUGOUT("Timeout\r\n");
/* Yep, timeout. Is there reties left? */
if( soc->retries_left )
{
/* Still keep waiting for FIN */
soc->retries_left--;
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
break;
}
else
{
/* Retries used up */
DEBUGOUT("Retries used up, resetting\r\n");
if(soc->type & TCP_TYPE_SERVER )
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(handle);
/* Inform application */
soc->event_listener(handle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
handle++;
return;
}
break;
default:
break;
}
/* Go to next socket if there was no event */
handle++;
}
}
/********************************************************************************
Function: tcp_init
Parameters: -
Return val: INT8 - (-1) = Error
- >0 = Number of sockets initialized
Date: 14.6.2002
Desc: Set TCP sockets to known values.
Called once when processor starts!
*********************************************************************************/
INT8 tcp_init (void)
{
UINT16 i;
INT16 h;
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(0);
DEBUGOUT("Initializing TCP");
for(i=0; i < NO_OF_TCPSOCKETS; i++)
{
soc = &TCPSocket[i]; /* Get Socket */
h = -1;
soc->state = TCP_STATE_FREE;
soc->type = TCP_TYPE_NONE;
soc->flags = 0;
soc->rem_ip = 0;
soc->remport = 0;
soc->locport = 0;
soc->myflags = 0;
soc->send_mtu = TCP_DEF_MTU;
soc->tos = 0;
soc->tout = 0;
soc->event_listener = 0;
/* Reserve Timers */
h = get_timer();
if( h < 0 )
{
DEBUGOUT("\n\rERROR:Error getting timer for TCP Socket!\n\r");
return(-1);
}
init_timer(h,0); /* No timeout */
soc->persist_timerh = h;
h = get_timer();
if( h < 0 )
{
DEBUGOUT("\n\rERROR:Error getting timer for TCP Socket!\n\r");
return(-1);
}
init_timer(h,0); /* No timeout */
soc->retransmit_timerh = h;
soc->retries_left = 0;
DEBUGOUT(".");
}
DEBUGOUT("\n\rTCP Initialized\n\r");
/* Return number of sockets initialized */
return(i+1);
}
/*******************************************************************************/
/******* TCP Internal functions ********/
/*******************************************************************************/
/********************************************************************************
Function: ProcessTCPIn
Parameters: struct IPFrame* frame - pointer to received IP frame structure
UINT16 len - legth of data in bytes
Return val: INT16 - (-1) Not OK
>0 Packet OK
Date: 12.7.2002
Desc: Check and process received TCP frame
*********************************************************************************/
INT16 ProcessTCPIn (struct IPFrame* frame, UINT16 len)
{
struct tcb* soc;
UINT16 hlen;
UINT8 olen;
UINT16 dlen;
UINT16 i;
INT8 sochandle;
INT16 temp;
/* Is this TCP? */
DEBUGOUT("Processing TCP...\n\r");
if( frame->protocol != IP_TCP )
{
DEBUGOUT("ERROR: The protocol is not TCP\n\r");
return(-1);
}
/* Calculate checksum for received packet */
NETWORK_RECEIVE_INITIALIZE(frame->BufIndex);
if( TCP_CheckCS(frame, len) == 1)
{
DEBUGOUT("TCP Checksum OK\n\r");
}
else
{
DEBUGOUT("ERROR:TCP Checksum failed\r\n");
return(-1);
}
/* Get the header */
NETWORK_RECEIVE_INITIALIZE(frame->BufIndex);
ReceivedTCPPacket.sport = RECEIVE_NETWORK_B();
ReceivedTCPPacket.sport <<= 8;
ReceivedTCPPacket.sport |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.dport = RECEIVE_NETWORK_B();
ReceivedTCPPacket.dport <<= 8;
ReceivedTCPPacket.dport |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.seqno = RECEIVE_NETWORK_B();
ReceivedTCPPacket.seqno <<= 8;
ReceivedTCPPacket.seqno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.seqno <<= 8;
ReceivedTCPPacket.seqno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.seqno <<= 8;
ReceivedTCPPacket.seqno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.ackno = RECEIVE_NETWORK_B();
ReceivedTCPPacket.ackno <<= 8;
ReceivedTCPPacket.ackno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.ackno <<= 8;
ReceivedTCPPacket.ackno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.ackno <<= 8;
ReceivedTCPPacket.ackno |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.hlen_flags = RECEIVE_NETWORK_B();
ReceivedTCPPacket.hlen_flags <<= 8;
ReceivedTCPPacket.hlen_flags |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.window = RECEIVE_NETWORK_B();
ReceivedTCPPacket.window <<= 8;
ReceivedTCPPacket.window |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.checksum = RECEIVE_NETWORK_B();
ReceivedTCPPacket.checksum <<= 8;
ReceivedTCPPacket.checksum |= RECEIVE_NETWORK_B();
ReceivedTCPPacket.urgent = RECEIVE_NETWORK_B();
ReceivedTCPPacket.urgent <<= 8;
ReceivedTCPPacket.urgent |= RECEIVE_NETWORK_B();
/* Little check for options */
hlen = ReceivedTCPPacket.hlen_flags & 0xF000;
hlen >>= 10;
if( hlen < MIN_TCP_HLEN )
{
DEBUGOUT("ERROR: Received TCP Header too short\r\n");
return(-1);
}
if(hlen == MIN_TCP_HLEN)
DEBUGOUT("TCP does not contain options\r\n");
olen = hlen - MIN_TCP_HLEN;
if( olen > MAX_TCP_OPTLEN )
{
DEBUGOUT("ERROR: Received TCP header contains too long option field\r\n");
return(-1);
}
/* Calculate data length */
if( hlen > len )
{
DEBUGOUT("ERROR: TCP header longer than packet\r\n");
return(-1);
}
dlen = len - hlen - olen;
/* Get options (if any) */
for(i=0; i<olen;i++)
ReceivedTCPPacket.opt[i] = RECEIVE_NETWORK_B();
/* Try to find rigth socket to process with */
sochandle = tcp_mapsocket(frame, &ReceivedTCPPacket);
if(sochandle < 0)
{
DEBUGOUT("ERROR: Processing TCP packet failed\r\n");
tcp_sendreset(&ReceivedTCPPacket, frame->sip);
return(-1);
}
ReceivedTCPPacket.BufIndex = frame->BufIndex + hlen;
NETWORK_RECEIVE_INITIALIZE(ReceivedTCPPacket.BufIndex);
/* Get socket reference */
soc = &TCPSocket[sochandle];
/* Process the packet on TCP State Machine */
switch(soc->state)
{
case TCP_STATE_CONNECTED:
DEBUGOUT("CONNECTED State\r\n");
/* Check for RESET */
if(ReceivedTCPPacket.hlen_flags & TCP_FLAG_RESET)
{
DEBUGOUT("ERROR:Reset received\r\n");
/* Inform application */
soc->event_listener(sochandle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);
if(soc->type & TCP_TYPE_SERVER)
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
return(-1);
}
/* Check for SYN (If the peer didn't get our SYN+ACK or ACK) */
if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_SYN )
{
/* Is it the SYN+ACK we have already ACKed but maybe ACK lost? */
if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_ACK )
{
/* It's SYN+ACK but how about sequence */
if( (ReceivedTCPPacket.seqno + 1) == soc->receive_next )
{
if( ReceivedTCPPacket.ackno == soc->send_next )
{
DEBUGOUT("Received SYN+ACK again\r\n");
/* ACK the SYN */
soc->myflags = TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -