📄 tcp.c
字号:
/***************************************************************************************
File: tcp.c
Date: 10.7.2002
Version: 0.1
Author: Jari Lahti (jari@violasystems.com)
Description: This file contains TCP processing functionality
Version Info: 10.7.2002 - First version (JaL)
***************************************************************************************/
#include "opentcp.h"
struct TCPFrame ReceivedTCPPacket;
struct tcb TCPSocket[NO_OF_TCPSOCKETS + 1];
UINT8 tcp_tempbuf[MIN_TCP_HLEN + 1];
/*******************************************************************************/
/******* TCP API functions ********/
/*******************************************************************************/
/********************************************************************************
Function: tcp_getsocket
Parameters: UINT8 soctype - type of socket wanted (client, server or clientserver)
UINT8 tos - type of service for socket
UINT16 tout - timeout of socket in seconds
INT32 (*listener)(INT8, UINT8, UINT32, UINT32) - listening function
Return val: INT8 - (-1) = Error
- >0 = handle to reserved socket
Date: 21.7.2002
Desc: Try to get free socket from socket pool and return handle to it
*********************************************************************************/
INT8 tcp_getsocket (UINT8 soctype, UINT8 tos, UINT16 tout, INT32 (*listener)(INT8, UINT8, UINT32, UINT32) )
{
INT8 i;
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( (soctype != TCP_TYPE_SERVER) &&
(soctype != TCP_TYPE_CLIENT) &&
(soctype != TCP_TYPE_CLIENT_SERVER) &&
(soctype != TCP_TYPE_NONE) )
{
DEBUGOUT("Invalid socket type requested\r\n");
return(-1);
}
if(listener == 0)
{
DEBUGOUT("ERROR:Event listener function not specified\r\n");
return(-1);
}
DEBUGOUT("Searching for free TCP socket...\r\n");
for(i=0; i < NO_OF_TCPSOCKETS; i++)
{
soc = &TCPSocket[i]; /* Get Socket */
if(soc->state == TCP_STATE_FREE)
{
/* We found it */
DEBUGOUT("Free socket found\r\n");
soc->state = TCP_STATE_RESERVED;
soc->type = soctype;
soc->tos = tos;
soc->event_listener = listener;
soc->rem_ip = 0;
soc->remport = 0;
soc->locport = 0;
soc->flags = 0;
soc->tout = (UINT32)tout * TIMERTIC;
return(i);
}
}
/* We are there so no socket found */
DEBUGOUT("No socket found\r\n");
return(-1);
}
/********************************************************************************
Function: tcp_releasesocket
Parameters: INT8 sochandle - handle to socket to be released
Return val: INT8 - (-1) = Error
- >0 = handle to released socket
Date: 21.7.2002
Desc: Try to release given socket
*********************************************************************************/
INT8 tcp_releasesocket (INT8 sochandle)
{
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
if( (soc->state != TCP_STATE_FREE) &&
(soc->state != TCP_STATE_RESERVED) &&
(soc->state != TCP_STATE_CLOSED) )
{
DEBUGOUT("Socket is not on valid state to be released\r\n");
return(-1);
}
/* We are there so all OK */
soc->state = TCP_STATE_FREE;
soc->type = TCP_TYPE_NONE;
soc->tos = 0;
soc->event_listener = 0;
soc->rem_ip = 0;
soc->remport = 0;
soc->locport = 0;
soc->flags = 0;
return(sochandle);
}
/********************************************************************************
Function: tcp_listen
Parameters: INT8 sochandle - handle to socket to be placed on listen
UINT16 port - port to listen for
Return val: INT8 - (-1) = Error
- >0 = Handle to listening socket (OK)
Date: 12.7.2002
Desc: Try to set TCP socket to listen on given port
*********************************************************************************/
INT8 tcp_listen (INT8 sochandle, UINT16 port)
{
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
if( (soc->type & TCP_TYPE_SERVER) == 0 )
{
DEBUGOUT("Socket has no server properties\r\n");
return(-1);
}
if( soc->event_listener == 0)
{
DEBUGOUT("ERROR:No event listener function specified\r\n");
return(-1);
}
if( (soc->state != TCP_STATE_RESERVED) &&
(soc->state != TCP_STATE_LISTENING) &&
(soc->state != TCP_STATE_CLOSED) &&
(soc->state != TCP_STATE_TIMED_WAIT) )
{
DEBUGOUT("Not possible to listen, socket on connected state\r\n");
return(-1);
}
/* Init socket */
soc->state = TCP_STATE_LISTENING;
//soc->type = TCP_TYPE_SERVER;
soc->flags = 0;
soc->rem_ip = 0;
soc->remport = 0;
soc->locport = port;
soc->send_unacked = 0;
soc->myflags = 0;
soc->send_next = 0xFFFFFFFF;
soc->send_mtu = TCP_DEF_MTU;
//soc->rtt = 0;
soc->receive_next = 0;
soc->retries_left = 0;
DEBUGOUT("TCP listening socket created\r\n");
return(sochandle);
}
/********************************************************************************
Function: tcp_connect
Parameters: UINT8 sochandle - handle to socket to be used
UINT32 ip - ip address to connect to
UINT16 rport - port to connect to
UINT16 myport - local port
Return val: INT8 - (-1) = Error
- >0 = Connection procedure started (OK)
Date: 21.7.2002
Desc: Try to connect to remote IP & port
*********************************************************************************/
INT8 tcp_connect (INT8 sochandle, UINT32 ip, UINT16 rport, UINT16 myport )
{
struct tcb* soc;
DEBUGOUT("FUNCTION: tcp_connect\r\n");
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
/* Is the local port defined */
if( myport == 0 )
myport = tcp_getfreeport();
if( myport == 0 )
return(-1);
soc = &TCPSocket[sochandle]; /* Get referense */
/* Do we have client properties? */
if( (soc->type & TCP_TYPE_CLIENT) == 0 )
{
DEBUGOUT("Socket has no client properties\r\n");
return(-1);
}
if( soc->event_listener == 0)
{
DEBUGOUT("ERROR:No event listener function specified\r\n");
return(-1);
}
/* Are we on LISTENING, RESERVED or CLOSED state */
if( (soc->state != TCP_STATE_RESERVED) &&
(soc->state != TCP_STATE_LISTENING) &&
(soc->state != TCP_STATE_CLOSED) )
{
DEBUGOUT("Socket on unvalid state to initialize CONNECT\r\n");
return(-1);
}
/* Then just set parameters and send SYN */
soc->rem_ip = ip;
soc->remport = rport;
soc->locport = myport;
soc->flags = 0;
soc->send_mtu = TCP_DEF_MTU;
/* get initial sequence number */
soc->send_unacked = tcp_initseq();
soc->send_next = soc->send_unacked + 1;
soc->myflags = TCP_FLAG_SYN;
tcp_sendcontrol(sochandle);
tcp_newstate(soc, TCP_STATE_SYN_SENT);
return(sochandle);
}
/********************************************************************************
Function: tcp_send
Parameters: INT8 sockethandle - handle to processed socket
UINT8* buf - data buffer (start of user data)
UINT16 blen - buffer length in bytes (user space)
UINT16 dlen - legth of data in bytes (user data)
Return val: INT16 - (-1) Not OK
>0 Number of bytes sent
Date: 25.7.2002
Desc: Send user data by using TCP
*********************************************************************************/
INT16 tcp_send (INT8 sockethandle, UINT8* buf, UINT16 blen, UINT16 dlen)
{
struct tcb* soc;
DEBUGOUT("Entering to send TCP data 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);
}
soc = &TCPSocket[sockethandle]; /* Get socket */
if(soc->state != TCP_STATE_CONNECTED)
{
DEBUGOUT("TCP is not connected!!\r\n");
return(-1);
}
if(soc->send_unacked != soc->send_next)
{
DEBUGOUT("TCP contains unacked data, cannot send more\r\n");
return(-1);
}
if( dlen > blen )
dlen = blen;
if(dlen + MIN_TCP_HLEN > soc->send_mtu)
{
if(soc->send_mtu > MIN_TCP_HLEN)
dlen = soc->send_mtu - MIN_TCP_HLEN;
else
return(-1);
}
soc->send_next += dlen;
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_PUSH;
ProcessTCPOut(sockethandle, buf - MIN_TCP_HLEN, blen + MIN_TCP_HLEN + 1, dlen);
return(dlen);
}
/********************************************************************************
Function: tcp_close
Parameters: INT8 sochandle - handle to socket to be closed
Return val: INT8 - (-2) = Unacked data, try again
- (-1) = Error (General)
- >0 = Handle to closed socket (OK)
Date: 21.7.2002
Desc: Try to close socket to closed state
*********************************************************************************/
INT8 tcp_close (INT8 sochandle)
{
struct tcb* soc;
DEBUGOUT("FUNCTION: tcp_close\r\n");
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
switch(soc->state)
{
case TCP_STATE_LISTENING:
tcp_newstate(soc, TCP_STATE_CLOSED);
break;
case TCP_STATE_SYN_RECEIVED:
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_FIN;
soc->send_unacked++;
soc->send_next++;
tcp_sendcontrol(sochandle);
tcp_newstate(soc, TCP_STATE_FINW1);
break;
case TCP_STATE_SYN_SENT:
tcp_newstate(soc, TCP_STATE_CLOSED);
break;
case TCP_STATE_FINW1:
case TCP_STATE_FINW2:
case TCP_STATE_CLOSING:
case TCP_STATE_TIMED_WAIT:
case TCP_STATE_LAST_ACK:
/* We are closing already */
break;
case TCP_STATE_CONNECTED:
/* Is there unacked data? */
if(soc->send_unacked == soc->send_next )
{
/* There is no unacked data */
soc->myflags = TCP_FLAG_ACK | TCP_FLAG_FIN;
soc->send_next++;
tcp_sendcontrol(sochandle);
tcp_newstate(soc, TCP_STATE_FINW1);
}
else
{
/* Can't do much but raise pollable flag to soc->flags */
/* and process it on tcp_poll */
soc->flags |= TCP_INTFLAGS_CLOSEPENDING;
return(sochandle);
}
break;
default:
return(-1);
}
return(sochandle);
}
/********************************************************************************
Function: tcp_getstate
Parameters: INT8 sochandle - handle to socket to be queried
Return val: INT8 - (-1) = Error
- >0 = State of socket
Date: 21.7.2002
Desc: Return the state of wanted socket
*********************************************************************************/
INT8 tcp_getstate (INT8 sochandle)
{
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
return(soc->state);
}
/********************************************************************************
Function: tcp_checksend
Parameters: UINT8 sochandle - handle to socket to be inspected
Return val: INT16 - (-1) = Not possible to send
- >0 = Free buffer space
Date: 23.7.2002
Desc: Check is it possible to send data by using given socket
*********************************************************************************/
INT16 tcp_checksend (UINT8 sochandle)
{
struct tcb* soc;
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
if(soc->state != TCP_STATE_CONNECTED)
return(-1);
if(soc->send_unacked == soc->send_next)
return(soc->send_mtu);
return(-1);
}
/********************************************************************************
Function: tcp_abort
Parameters: INT8 sochandle - handle to socket to be aborted
Return val: INT8 - (-1) = Error
- >0 = Handle to aborted socket
Date: 21.7.2002
Desc: Reset connection and place socket to closed state
*********************************************************************************/
INT8 tcp_abort (INT8 sochandle)
{
struct tcb* soc;
DEBUGOUT("FUNCTION: tcp_abort\r\n");
if( NO_OF_TCPSOCKETS < 0 )
return(-1);
if( NO_OF_TCPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_TCPSOCKETS )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 )
{
DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
soc = &TCPSocket[sochandle]; /* Get referense */
switch (soc->state)
{
case TCP_STATE_FREE:
return(-1);
case TCP_STATE_RESERVED:
case TCP_STATE_CLOSED:
return(sochandle);
case TCP_STATE_TIMED_WAIT:
case TCP_STATE_LISTENING:
tcp_newstate(soc, TCP_STATE_CLOSED);
return(sochandle);
case TCP_STATE_SYN_SENT:
case TCP_STATE_SYN_RECEIVED:
case TCP_STATE_CONNECTED:
case TCP_STATE_FINW1:
case TCP_STATE_FINW2:
case TCP_STATE_CLOSING:
case TCP_STATE_LAST_ACK:
soc->myflags = TCP_FLAG_RESET;
tcp_sendcontrol(sochandle);
tcp_newstate(soc, TCP_STATE_CLOSED);
return(sochandle);
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -