📄 tcp.c
字号:
if( ReceivedTCPPacket.ackno != soc->send_next )
{
DEBUGOUT("ACK received but wrong Ack\n\r");
return(-1);
}
DEBUGOUT("Last ACK received, next LISTENING or CLOSED\r\n");
/* We have no unacked data */
soc->send_unacked = soc->send_next;
if(soc->type & TCP_TYPE_SERVER)
tcp_newstate(soc, TCP_STATE_LISTENING);
else
tcp_newstate(soc, TCP_STATE_CLOSED);
return(0);
}
/* Is it repeated FIN? */
if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_FIN )
{
DEBUGOUT("Repeated FIN, repeat ACK\n\r");
/* ACK FIN and all data */
soc->receive_next = ReceivedTCPPacket.seqno;
soc->receive_next++;
soc->receive_next += dlen;
soc->myflags = TCP_FLAG_FIN | TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
return(0);
}
tcp_sendreset(&ReceivedTCPPacket, frame->sip);
return(-1);
break;
case TCP_STATE_TIMED_WAIT:
DEBUGOUT("TIMED_WAIT 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);
}
/* Is it repeated FIN? */
if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_FIN )
{
DEBUGOUT("Repeated FIN, repeat ACK\n\r");
/* ACK FIN and all data */
soc->receive_next = ReceivedTCPPacket.seqno;
soc->receive_next++;
soc->receive_next += dlen;
soc->myflags = TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
return(0);
}
tcp_sendreset(&ReceivedTCPPacket, frame->sip);
return(-1);
break;
default:
DEBUGOUT("ERROR:TCP State machine in unknown state!!\r\n");
tcp_sendreset(&ReceivedTCPPacket, frame->sip);
RESET_SYSTEM();
}
DEBUGOUT("Should not be there!\r\n");
return(-1);
}
/********************************************************************************
Function: ProcessTCPOut
Parameters: INT8 sockethandle - handle to processed socket
UINT8* buf - data buffer
UINT16 blen - buffer length in bytes
UINT16 dlen - legth of data in bytes
Return val: INT16 - (-1) Not OK
>0 Packet OK
Date: 16.7.2002
Desc: Calculate checksum for TCP packet and send it to IP.
Buffer must contain 20 bytes free on start of it for TCP
header assembly.
*********************************************************************************/
INT16 ProcessTCPOut (INT8 sockethandle, UINT8* buf, UINT16 blen, UINT16 dlen)
{
struct tcb* soc;
UINT16 cs;
UINT8 cs_cnt;
UINT8* buf_start;
DEBUGOUT("Entering to send TCP packet\r\n");
if( sockethandle < 0 )
{
DEBUGOUT("ERROR:Socket Handle not valid (<0)\r\n");
return(-1);
}
if( sockethandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("ERROR:Socket Handle not valid (>NO_OF_TCPSOCKETS)\r\n");
return(-1);
}
if( (dlen + MIN_TCP_HLEN) > blen )
{
DEBUGOUT("ERROR:Transmit buffer too small for TCP header\r\n");
return(-1);
}
soc = &TCPSocket[sockethandle]; /* Get socket */
buf_start = buf;
if( (dlen + MIN_TCP_HLEN) > soc->send_mtu )
{
DEBUGOUT("ERROR:Send MTU exceeded\r\n");
return(-1);
}
/* Assemble TCP header to buffer */
*buf++ = (UINT8)(soc->locport >> 8);
*buf++ = (UINT8)soc->locport;
*buf++ = (UINT8)(soc->remport >> 8);
*buf++ = (UINT8)soc->remport;
*buf++ = (UINT8)(soc->send_unacked >>24);
*buf++ = (UINT8)(soc->send_unacked >>16);
*buf++ = (UINT8)(soc->send_unacked >>8);
*buf++ = (UINT8)(soc->send_unacked);
*buf++ = (UINT8)(soc->receive_next >>24);
*buf++ = (UINT8)(soc->receive_next >>16);
*buf++ = (UINT8)(soc->receive_next >>8);
*buf++ = (UINT8)(soc->receive_next);
*buf = MIN_TCP_HLEN >> 2;
*buf <<= 4;
buf++;
*buf++ = soc->myflags;
*buf++ = (UINT8)((TCP_DEF_MTU) >> 8);
*buf++ = (UINT8)TCP_DEF_MTU;
*buf++ = 0; /* Checksum */
*buf++ = 0;
*buf++ = 0; /* Urgent */
*buf++ = 0;
/* Calculate checksum */
cs = 0;
cs_cnt = 0;
/* Do it firstly to IP pseudo header */
cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)localmachine.localip, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 24), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 16), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)soc->rem_ip, cs_cnt++);
cs = IpCheckSum(cs, 0, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)IP_TCP, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)((dlen + MIN_TCP_HLEN) >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(dlen + MIN_TCP_HLEN), cs_cnt++);
/* Go to TCP header + data */
buf = buf_start;
cs = IpCheckSumBuf(cs, buf, dlen + MIN_TCP_HLEN);
cs = ~ cs;
#if 0
/* Is the padding required? */
if(dlen & 0x01)
{
DEBUGOUT("Padding required\r\n");
*buf = 0;
dlen++;
}
#endif
/* Save checksum in correct place */
buf = buf_start + 16;
*buf++ = (UINT8)(cs >> 8);
*buf = (UINT8)cs;
/* Send it to IP */
DEBUGOUT("Sending TCP...\r\n");
ProcessIPOut(soc->rem_ip, IP_TCP, soc->tos, 100, buf_start, dlen + MIN_TCP_HLEN);
DEBUGOUT("TCP packet sent\r\n");
return(0);
}
/********************************************************************************
Function: tcp_sendcontrol
Parameters: INT8 sochandle - handle to socket
Return val: void
Date: 17.7.2002
Desc: Send a control packet with predefined flags
*********************************************************************************/
void tcp_sendcontrol (INT8 sockethandle)
{
//struct tcb* soc;
DEBUGOUT("Entering to send TCP control packet\r\n");
if( sockethandle < 0 )
{
DEBUGOUT("ERROR:Socket Handle not valid (<0)\r\n");
return;
}
if( sockethandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("ERROR:Socket Handle not valid (>NO_OF_TCPSOCKETS)\r\n");
return;
}
//soc = &TCPSocket[sockethandle]; /* Get socket */
ProcessTCPOut(sockethandle, &tcp_tempbuf[0], MIN_TCP_HLEN + 1, 0);
return;
}
/********************************************************************************
Function: tcp_sendreset
Parameters: struct TCPFrame* frame - received TCP packet
UINT32 remip - remote IP address of packet
Return val: void
Date: 20.8.2002
Desc: Uses socket NO_OF_TCPSOCKETS to send a RESET packet to peer.
This function is used when we are establishing connection but
we receive something else than SYN or SYN+ACK when it's
possible that the peer has still old connection on which
needs to be resetted without canceling the connection establishment
on process.
*********************************************************************************/
void tcp_sendreset (struct TCPFrame *frame, UINT32 remip)
{
struct tcb* soc;
soc = &TCPSocket[NO_OF_TCPSOCKETS]; /* Get socket */
/* Is this itself a reset packet? */
if( frame->hlen_flags & TCP_FLAG_RESET )
return;
/* Set temporary tcb variables */
soc->rem_ip = remip;
soc->remport = frame->sport;
soc->locport = frame->dport;
soc->tos = 0;
soc->send_unacked = frame->ackno;
soc->myflags = TCP_FLAG_RESET | TCP_FLAG_ACK;
soc->receive_next = frame->seqno;
/* Is there SYN or FIN? */
if( (frame->hlen_flags & TCP_FLAG_SYN) || ( frame->hlen_flags & TCP_FLAG_FIN) )
soc->receive_next++;
soc->send_mtu = TCP_DEF_MTU;
tcp_sendcontrol(NO_OF_TCPSOCKETS);
}
/********************************************************************************
Function: tcp_initseq
Parameters: -
Return val: UINT32 initial sequence number
Date: 17.7.2002
Desc: Get and return initial sequence number
*********************************************************************************/
UINT32 tcp_initseq (void)
{
DEBUGOUT("Calculating initial sequence number\r\n");
return( ( (UINT32)BaseTimer << 24) | 0x00FFFFFF );
}
/********************************************************************************
Function: tcp_mapsocket
Parameters: struct IPFrame* ipframe - pointer to received IP frame
struct TCPFrame* tcpframe - pointer to frame to be mapped
Return val: INT8 - (-1) = Error (No resources)
- >0 = Handle to mapped socket
Date: 12.7.2002
Desc: Try to find a socket for received TCP packet or allocate
listening one
*********************************************************************************/
INT8 tcp_mapsocket (struct IPFrame* ipframe, struct TCPFrame* tcpframe)
{
struct tcb* soc;
UINT8 i;
/* Check if there is already connection on */
for( i=0; i < NO_OF_TCPSOCKETS; i++)
{
soc = &TCPSocket[i]; /* Get socket */
if(soc->state == TCP_STATE_LISTENING)
continue; /* No match */
if(soc->remport != tcpframe->sport)
continue;
if(soc->locport != tcpframe->dport)
continue;
if(soc->rem_ip != ipframe->sip)
continue;
/* There is connection on already */
DEBUGOUT("Active connection socket found\r\n");
return(i);
}
/* Allocate listening one if SYN packet (Connection Request) */
DEBUGOUT("No active connection, checking if SYN packet\r\n");
/* Is it SYN? */
if( (tcpframe->hlen_flags & TCP_FLAG_SYN) == 0 )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_ACK )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_RESET )
return(-1);
if( tcpframe->hlen_flags & TCP_FLAG_FIN )
return(-1);
DEBUGOUT("Trying to allocate listening one for SYN packet\r\n");
/* Search listening sockets */
for( i=0; i < NO_OF_TCPSOCKETS; i++)
{
soc = &TCPSocket[i]; /* Get socket */
if(soc->state != TCP_STATE_LISTENING)
continue;
if(soc->locport != tcpframe->dport)
continue;
/* Bind it */
soc->rem_ip = ipframe->sip;
soc->remport = tcpframe->sport;
DEBUGOUT("Allocated new socket\r\n");
return(i);
}
/* No success */
DEBUGOUT("ERROR:No socket found or allocated for TCP packet\r\n");
return(-1);
}
/********************************************************************************
Function: tcp_newstate
Parameters: struct tcb* soc - socket structure operated
UINT8 nstate - new state
Return val: void
Date: 18.7.2002
Desc: Change state of socket and reload timers.
Call this function periodically on connected state to keep
connection on.
*********************************************************************************/
void tcp_newstate (struct tcb* soc, UINT8 nstate)
{
soc->state = nstate;
soc->retries_left = TCP_DEF_RETRIES;
/* Retransmit timer */
init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);
/* In some states we don't want to wait for many retries (e.g. TIMED_WAIT) */
switch(soc->state)
{
case TCP_STATE_TIMED_WAIT:
soc->retries_left = 0;
break;
case TCP_STATE_SYN_SENT:
/* When we are sending SYN it's propably that ARP is not valid */
/* Do retransmit faster on first time */
init_timer(soc->retransmit_timerh, TCP_INIT_RETRY_TOUT);
soc->retries_left = TCP_CON_ATTEMPTS;
break;
case TCP_STATE_LAST_ACK:
case TCP_STATE_FINW1:
case TCP_STATE_FINW2:
case TCP_STATE_CLOSING:
soc->retries_left = 1;
break;
default:
break;
}
/* KeepAlive timer */
if(soc->state == TCP_STATE_CONNECTED)
init_timer(soc->persist_timerh, soc->tout);
return;
}
/********************************************************************************
Function: tcp_getfreeport
Parameters: void
Return val: UINT16 - 0 = no free ports
>0 = Free local TCP port
Date: 19.8.2002
Desc: Gets next free (not used) local port
*********************************************************************************/
UINT16 tcp_getfreeport (void)
{
struct tcb* soc;
static UINT16 lastport = 1;
UINT16 start;
UINT16 i;
/* Try with every port to every socket untill free found */
for( start = lastport++; start != lastport; lastport++)
{
if(lastport == TCP_PORTS_END)
lastport = 1;
for(i = 0; i < NO_OF_TCPSOCKETS; i++)
{
soc = &TCPSocket[i]; /* Get socket */
if( (soc->state > TCP_STATE_CLOSED) && (soc->locport == lastport) )
{
/* Blaah, this socket has reserved the port, go to next one */
break;
}
}
/* Did we found it? */
if( i == NO_OF_TCPSOCKETS)
break;
}
if(lastport == start)
{
DEBUGOUT("Out of TCP ports!!\n\r");
return(0);
}
return(lastport);
}
/********************************************************************************
Function: TCP_CheckCS
Parameters: struct IPFrame* ipframe - pointer to IP frame that carried TCP
UINT16 len - length of TCP portion
Return val: UINT8 0 - Checksum corrupted
UINT8 1 - Checksum OK
Date: 16.7.2002
Desc: Calculate is the TCP frame uncorrupted. May be
made more intelligent/faster by using carry method.
*********************************************************************************/
UINT8 TCP_CheckCS (struct IPFrame* ipframe, UINT16 len)
{
UINT16 cs;
UINT8 cs_cnt;
cs = 0;
cs_cnt = 0;
/* Do it firstly to IP pseudo header */
cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 24), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 16), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)ipframe->sip, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 24), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 16), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)ipframe->dip, cs_cnt++);
cs = IpCheckSum(cs, 0, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)ipframe->protocol, cs_cnt++);
cs = IpCheckSum(cs, (UINT8)(len >> 8), cs_cnt++);
cs = IpCheckSum(cs, (UINT8)len, cs_cnt++);
/* Go to TCP data */
while(len>15)
{
RECEIVE_NETWORK_BUF(tcp_tempbuf,16);
cs = IpCheckSumBuf(cs, tcp_tempbuf,16);
len -= 16;
cs_cnt += 16;
}
while(len--)
{
cs = IpCheckSum(cs, RECEIVE_NETWORK_B(), (UINT8)cs_cnt++);
}
cs = ~ cs;
if(cs != IP_GOOD_CS)
{
return (0);
}
/* It's OK */
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -