📄 tcp.c
字号:
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++;
}
}
/** \brief Initialize TCP module
* \ingroup core_initializer
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 21.07.2002
* \return
* \li -1 - error
* \li >0 - number of sockets initialized
* \warning
* \li This function <b>must</b> be invoked at startup before any
* other TCP functions are invoked.
*
* This function initializes all sockets and corresponding tcbs to known
* state. Timers are also allocated for each socket and everything is
* brought to a predefined state.
*
*/
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);
TCP_DEBUGOUT("Initializing TCP");
for(i=0; i < NO_OF_TCPSOCKETS; i++) {
soc = &tcp_socket[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 ) {
TCP_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 ) {
TCP_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;
TCP_DEBUGOUT(".");
}
TCP_DEBUGOUT("\n\rTCP Initialized\n\r");
/* Return number of sockets initialized */
return(i+1);
}
/*******************************************************************************/
/******* TCP Internal functions ********/
/*******************************************************************************/
/** \brief Check and process the received TCP frame
* \ingroup periodic_functions
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 12.07.2002
* \param frame pointer to received ip_frame structure
* \param len length of data contained in IP datagram (in bytes)
* \return
* \li -1 - Error (packet not OK, or not TCP,or something else)
* \li >0 - Packet OK
*
* Invoke this function to process received TCP frames. See main_demo.c for
* an example on how to accomplish this.
*/
INT16 process_tcp_in (struct ip_frame* frame, UINT16 len)
{
struct tcb* soc;
UINT16 hlen;
UINT8 olen;
UINT16 dlen;
UINT16 i;
INT8 sochandle;
INT16 temp;
/* Is this TCP? */
TCP_DEBUGOUT("Processing TCP...\n\r");
if( frame->protocol != IP_TCP ) {
TCP_DEBUGOUT("ERROR: The protocol is not TCP\n\r");
return(-1);
}
/* Calculate checksum for received packet */
NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
if( tcp_check_cs (frame, len) == 1) {
TCP_DEBUGOUT("TCP Checksum OK\n\r");
} else {
TCP_DEBUGOUT("ERROR:TCP Checksum failed\r\n");
return(-1);
}
/* Get the header */
/* Get the header */
NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
received_tcp_packet.sport = RECEIVE_NETWORK_W();
received_tcp_packet.dport = RECEIVE_NETWORK_W();
received_tcp_packet.seqno = (((UINT32)RECEIVE_NETWORK_B()) << 24);
received_tcp_packet.seqno |= (((UINT32)RECEIVE_NETWORK_B()) << 16);
received_tcp_packet.seqno |= (((UINT32)RECEIVE_NETWORK_B()) << 8);
received_tcp_packet.seqno |= RECEIVE_NETWORK_B();
received_tcp_packet.ackno = (((UINT32)RECEIVE_NETWORK_B()) << 24);
received_tcp_packet.ackno |= (((UINT32)RECEIVE_NETWORK_B()) << 16);
received_tcp_packet.ackno |= (((UINT32)RECEIVE_NETWORK_B()) << 8);
received_tcp_packet.ackno |= RECEIVE_NETWORK_B();
received_tcp_packet.hlen_flags = RECEIVE_NETWORK_W();
received_tcp_packet.window = RECEIVE_NETWORK_W();
received_tcp_packet.checksum = RECEIVE_NETWORK_W();
received_tcp_packet.urgent = RECEIVE_NETWORK_W();
/* Little check for options */
hlen = received_tcp_packet.hlen_flags & 0xF000;
hlen >>= 10;
if( hlen < MIN_TCP_HLEN ) {
TCP_DEBUGOUT("ERROR: Received TCP Header too short\r\n");
return(-1);
}
if(hlen == MIN_TCP_HLEN)
TCP_DEBUGOUT("TCP does not contain options\r\n");
olen = hlen - MIN_TCP_HLEN;
if( olen > MAX_TCP_OPTLEN ) {
TCP_DEBUGOUT("ERROR: Received TCP header contains too long option field\r\n");
return(-1);
}
/* Calculate data length */
if( hlen > len ) {
TCP_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++)
received_tcp_packet.opt[i] = RECEIVE_NETWORK_B();
/* Try to find rigth socket to process with */
sochandle = tcp_mapsocket(frame, &received_tcp_packet);
if(sochandle < 0) {
TCP_DEBUGOUT("ERROR: Processing TCP packet failed\r\n");
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
}
received_tcp_packet.buf_index = frame->buf_index + hlen;
NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
/* Get socket reference */
soc = &tcp_socket[sochandle];
/* Process the packet on TCP State Machine */
switch(soc->state) {
case TCP_STATE_CONNECTED:
TCP_DEBUGOUT("CONNECTED State\r\n");
/* Check for RESET */
if(received_tcp_packet.hlen_flags & TCP_FLAG_RESET) {
TCP_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( received_tcp_packet.hlen_flags & TCP_FLAG_SYN ) {
/* Is it the SYN+ACK we have already ACKed but maybe ACK lost? */
if( received_tcp_packet.hlen_flags & TCP_FLAG_ACK ) {
/* It's SYN+ACK but how about sequence */
if( (received_tcp_packet.seqno + 1) == soc->receive_next ) {
if( received_tcp_packet.ackno == soc->send_next ) {
TCP_DEBUGOUT("Received SYN+ACK again\r\n");
/* ACK the SYN */
soc->myflags = TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
return(0);
}
}
/* It is maybe SYN again so it haven't get our SYN + ACK */
/* Let our retransmission handle it */
return(0);
}
}
/* Do we have unacked data? */
if( soc->send_unacked != soc->send_next ) {
/* Yep, is the ACK valid? */
if( (received_tcp_packet.hlen_flags & TCP_FLAG_ACK) == 0) {
TCP_DEBUGOUT("Packet without ACK and unacked data. Packet not processed\r\n");
return(0);
}
if( received_tcp_packet.ackno == soc->send_next ) {
/* We don't have unacked data now */
soc->send_unacked = soc->send_next;
/* Inform application */
soc->event_listener(sochandle, TCP_EVENT_ACK, soc->rem_ip, soc->remport);
}
}
/* Is the sequence OK */
if(soc->receive_next != received_tcp_packet.seqno)
{
/* Out of range, inform what we except */
DEBUGOUT("Too big sequence number received\r\n");
soc->myflags = TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
return(0);
}
/* Generate data event to application */
#ifdef IPv6
soc->event_listener(sochandle, TCP_EVENT_DATA, (IPv6Addr *)&dlen, 0);
#else
soc->event_listener(sochandle, TCP_EVENT_DATA, dlen, 0);
#endif
soc->receive_next += dlen;
/* Is the FIN flag set? */
if( received_tcp_packet.hlen_flags & TCP_FLAG_FIN ) {
TCP_DEBUGOUT("Other end want's to close\r\n");
/* Inform application if we don't have unacked data */
if( soc->send_unacked == soc->send_next) {
soc->event_listener(sochandle, TCP_EVENT_CLOSE, soc->rem_ip, soc->remport);
/* ACK FIN and set our own FIN */
soc->receive_next++;
soc->send_next++;
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_FIN;
tcp_newstate(soc, TCP_STATE_LAST_ACK);
tcp_sendcontrol(sochandle);
return(0);
}
}
/* ACK the data if there was it */
if(dlen) {
soc->myflags = TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
}
tcp_newstate(soc, TCP_STATE_CONNECTED);
return(0);
break;
case TCP_STATE_FREE:
/* Reset connection */
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
break;
case TCP_STATE_CLOSED:
/* Reset connection */
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
break;
case TCP_STATE_LISTENING:
TCP_DEBUGOUT("LISTENING State...\r\n");
/* Check Flags */
if(received_tcp_packet.hlen_flags & TCP_FLAG_RESET) {
TCP_DEBUGOUT("ERROR:Reset received\r\n");
tcp_newstate(soc, TCP_STATE_LISTENING);
return(-1);
}
if(received_tcp_packet.hlen_flags & TCP_FLAG_ACK) {
TCP_DEBUGOUT("ERROR:Ack received\r\n");
tcp_newstate(soc, TCP_STATE_LISTENING);
/* Reset connection */
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
}
if((received_tcp_packet.hlen_flags & TCP_FLAG_SYN) == 0) {
TCP_DEBUGOUT("ERROR:No SYN set on packet\r\n");
tcp_newstate(soc, TCP_STATE_LISTENING);
/* Reset connection */
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
}
/* OK, SYN received */
/* Inform application and see if accepted */
temp = (INT16)soc->event_listener(sochandle, TCP_EVENT_CONREQ, soc->rem_ip, soc->remport);
if( temp == -1) {
TCP_DEBUGOUT("Application disregarded connection request\r\n");
tcp_sendreset(&received_tcp_packet, frame->sip);
return(-1);
}
if( temp == -2 ) {
TCP_DEBUGOUT("Application wants to think about accepting conreq\r\n");
return(1);
}
/* The connection request was accepted */
TCP_DEBUGOUT("Next state SYN_RECEIVED\r\n");
if(soc->flags & TCP_INTFLAGS_CLOSEPENDING)
soc->flags ^= TCP_INTFLAGS_CLOSEPENDING;
tcp_newstate(soc, TCP_STATE_SYN_RECEIVED);
soc->receive_next = received_tcp_packet.seqno + 1; /* Ack SYN */
soc->send_unacked = tcp_initseq();
soc->myflags = TCP_FLAG_SYN | TCP_FLAG_ACK;
tcp_sendcontrol(sochandle);
soc->send_next = soc->send_unacked + 1;
return(1);
break;
case TCP_STATE_SYN_RECEIVED:
TCP_DEBUGOUT("SYN_RECEIVED State...\r\n");
/* Check Flags */
if(received_tcp_packet.hlen_flags & TCP_FLAG_RESET) {
TCP_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 SYN+ACK (if we are the because of simultaneous open) */
if( (received_tcp_packet.hlen_flags & TCP_FLAG_SYN) &&
(received_tcp_packet.hlen_flags & TCP_FLAG_ACK) ) {
if( received_tcp_packet.ackno != soc->send_next ) {
TCP_DEBUGOUT("SYN+ACK received but wrong Ack\n\r");
return(-1);
}
TCP_DEBUGOUT("SYN+ACK received, this side established\n\r");
/* Get peer's seq number */
soc->receive_next = received_tcp_packet.seqno;
soc->receive_next++; /* ACK SYN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -