Functions

int32_t connect (SOCKET *so, void *data, uint32_t send_max, int32_t timeout)
 Actively establish a connection. More...
 
int32_t shutdown (SOCKET *so, int32_t timeout)
 Active shut-down of a TCP connection. More...
 
SOCKET * accept (SOCKET *so)
 Check TCP state; if connection established, the socket descriptor is returned else NULL. More...
 
int32_t tcp_listen (SOCKET *so)
 Switch socket to listening state. More...
 
uint16_t tcp_set_option (SOCKET *so, uint32_t option, uint32_t val)
 Set a TCP option. More...
 
int16_t tcp_get_state (SOCKET *so)
 Determine tcp state. More...
 
uint16_t tcp_tx_complete (SOCKET *so)
 Test if the last TCP transmission was acknowledged. More...
 
uint32_t tcp_pending_window (SOCKET *so)
 returns the number of unacknowledged bytes More...
 
uint16_t tcp_force_retransmit (SOCKET *so)
 force a retransmit More...
 
int16_t tcp_set_keep_alive_time (SOCKET *so, uint32_t time)
 Set keep alive time. More...
 
void tcp_send_zero_window (void *so)
 send a zero window packet More...
 
void tcp_send_window_update (void *so)
 update window size More...
 

Detailed Description

Function Documentation

int32_t connect ( SOCKET *  so,
void *  data,
uint32_t  send_max,
int32_t  timeout 
)

Actively establish a connection. A three-way-hand-shake is performed to negotiate transfer parameters. If a timeout of 0 is specified, this function returns immediately after a SYN is sent. You may identify the error condition by reading socket_struct ->error_code.

Parameters
so- the socket to use
data- pointer to a buffer to hold the data. The data type is defined by the socket.
send_max- specifies the maximum tries to connect to host
timeout- timeout if peer could not be connected measured in net_isq() loop counts
Returns
true if connection successfully established, SOCKET_ERROR in case of errors.
Library:
net.lib
Prototype:
net.h

In case of a successful connection (return code 1/true) event code SO_CONNECTION_ESTABLISHED is temporarily set. A parallel net_recv() function call or the corresponding callback function (if any) may signal this event code.

Possible error codes:

Note
This handshake requires some buffer space (up to 40 bytes of parameters). To avoid allocating additional buffer memory, you must specify the buffer to use during negotiation. Typically this is the same buffer which is used for data transfer later after the connection was established.
See also
socket_struct ->error_code
SO_IN_USE, SO_DNS_ERR, SO_NO_LINK, SO_TIMED_OUT, SO_NOT_ESTABLISHED

Blocking example:

//****************************************************************************
// open socket:
//****************************************************************************
25,
if ( mail == INVALID_SOCKET )
{
//**************************************************************************
// couldn't get a free socket, free memory and return
//**************************************************************************
free (mail_data);
return (ret);
} // if
//****************************************************************************
// set the receive buffer size
//****************************************************************************
set_recv_buffer (mail, mail_data, MAX_DATA);
//****************************************************************************
// try to connect to mail server
// 20 retries
// 6000000 loop counts timeout
//****************************************************************************
if ( connect (mail, mail_data, 20, 6000000) != TRUE )
{
//**************************************************************************
// connect error, free memory and return
//**************************************************************************
socket_close (mail);
free (mail_data);
return (ret);
}


Unblocking example for DSP/BIOS:

ret = connect (so, data, 1, 0);
switch (ret)
{
case SO_NOT_ESTABLISHED: // if parameter timeout was 0
for (;;)
{
//****************************************************************
// wait for semaphore
//****************************************************************
SEM_pend (&Sem, SYS_FOREVER);
//****************************************************************
// check connection
//****************************************************************
if (tcp_get_state(so) == TCP_ESTABLISHED) break;
//****************************************************************
// to do: process timeout, do error handling, use shutdown() in
// case of errors
//****************************************************************
}
break;
case SO_IN_USE: // socket already connected
case SO_DNS_ERR: // address could not be resolved
case SO_NO_LINK; // no vaild link
case SO_TIMED_OUT: // timeout run out
default:
shutdown(so, 0); // shutdown immediately
// do further error handling
break;
}
Examples:
SMTP.c.
int32_t shutdown ( SOCKET *  so,
int32_t  timeout 
)

Active shut-down of a TCP connection. If socket option SO_TCP_STATE_CLOSED is not used, the socket state is switched back to TCP_LISTEN after sending out an ACK-FIN packet.

Parameters
so- the socket to use
timeout- timeout waiting for acknowledge finish from peer (measured in net_isq() loop counts). If timeout is zero, the socket state changes immediately to listening state (or TCP_CLOSED if SO_TCP_STATE_CLOSED is used) without waiting for a final ACK FIN from peer ( useful for hanging connection).
Returns
  • >0 if connection successfully terminated
  • <0 in case of errors
Note
This does not close the socket itself, only the connection is reset and must be re-established via connect if it should be used again.
See also
set_socket_option(), tcp_listen()
SO_TCP_STATE_CLOSED, TCP_LISTEN, TCP_CLOSED
Library:
net.lib
Prototype:
net.h
Note
You may identify the error condition by reading socket->error_code.
See also
socket_struct ->error_code
SO_TIMED_OUT
if ( get_reply_code (mail, mail_data) == 250 )
{
//**************************************************************************
// Send: QUIT
//**************************************************************************
if ( get_reply_code (mail, mail_data) == 221 )
{
//************************************************************************
// shutdown connection
//************************************************************************
shutdown (mail, 10000);
}
//**************************************************************************
// exit state machine
//**************************************************************************
send_state = IDLE_STATE;
//**************************************************************************
// set return value to success
//**************************************************************************
ret = TRUE;
}
else
{
//**************************************************************************
// exit state machine
//**************************************************************************
send_state = IDLE_STATE;
}
Examples:
Blocksend.c, PServer.c, and SMTP.c.
SOCKET * accept ( SOCKET *  so)
Parameters
so- listening socket
Returns
  • so if connected
  • NULL if unconnected

Check TCP state; if connection established, the socket descriptor is returned else NULL.

Library:
net.lib
Prototype:
net.h
//****************************************************************************
// check connection
//****************************************************************************
{
printf ("connection established");
}
Examples:
Blocksend.c.
int32_t tcp_listen ( SOCKET *  so)

By default a netlib TCP socket is in listening state after socket_open() or shutdown(). To change this behaviour use set_socket_option() with option SO_TCP_STATE_CLOSED. This adds two additional states to the TCP state machine (TCP_CLOSED and TCPS_FIN_WAIT_2). In this case use function tcp_listen() to switch state from TCP_CLOSED to TCP_LISTEN. After shutdown() or when errors occur the socket falls back into closed state and function tcp_listen() needs to be called again.

Parameters
so- the socket to switch to listening state
Returns
  • <0 invalid socket
  • TRUE success
See also
set_socket_option(), shutdown()
SO_TCP_STATE_CLOSED, TCP_LISTEN, TCP_CLOSED
Library:
net.lib
Prototype:
net.h
//****************************************************************************
// create TCP data server socket on port 5031
//****************************************************************************
5031,
{
prg_exit ("socket_open() failed");
}
//****************************************************************************
// add state closed and time wait state to TCP state machine
//****************************************************************************
...
//****************************************************************************
//activate listen state
//****************************************************************************
tcp_listen (tcp_server);
uint16_t tcp_set_option ( SOCKET *  so,
uint32_t  option,
uint32_t  val 
)
Parameters
so- valid socket
option- option to change
val- value
Returns
  • FALSE success
  • TRUE error

set TCP option for specified socket. Two options are available:

Library:
net.lib
Prototype:
net.h
See also
TCP_UNA_SEG, TCP_RETRANS_DELAY
// ***************************************************************************
// set TCP option for unacknowledged packet segment size of 4380 bytes
// ***************************************************************************
tcp_set_option (socket, TCP_UNA_SEG, 3*1460);
// ***************************************************************************
// set shorter TCP retransmit delay
// ***************************************************************************
Examples:
Blocksend.c.
int16_t tcp_get_state ( SOCKET *  so)
Parameters
so- the socket to use
Returns
  • <0 - invalid socket
  • else tcp state

This function returns the current TCP state

Library:
net.lib
Prototype:
net.h
See also
TCP_CLOSED, TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED
//****************************************************************************
//
// @brief handle Telnet Server
//
// @param telnet_server_type *telnet
// @return nothing
// @sa tcp_get_state() - netlib
// @sa net_send_string() - netlib
// @sa telnet_check_message() - this file
//
//****************************************************************************
void telnet_server ( telnet_server_type *telnet )
{
//**************************************************************************
// locals
//**************************************************************************
char netlib_rev_id[6];
char module_id[8];
//**************************************************************************
// check for connection established
//**************************************************************************
if ( tcp_get_state (telnet-> server) == TCP_ESTABLISHED )
{
//************************************************************************
// is it a new connection ?
//************************************************************************
if ( telnet-> so_state == SOCKET_DISCONNECTED )
{
//**********************************************************************
// retrieve HW and SW revision
//**********************************************************************
get_id (module_id);
get_netlib_ver (netlib_rev_id);
//**********************************************************************
// print info
//**********************************************************************
hello_msg[175] = module_id[1];
hello_msg[177] = module_id[2];
hello_msg[192] = module_id[3];
hello_msg[194] = module_id[4];
hello_msg[210] = netlib_rev_id[0]; // major version
hello_msg[211] = netlib_rev_id[1]; // minor version
hello_msg[213] = netlib_rev_id[3]; // major version
hello_msg[214] = netlib_rev_id[4]; // minor version
net_send_string (telnet-> server, hello_msg);
net_send_string (telnet-> server, commands);
telnet-> so_state = SOCKET_CONNECTED;
}
//************************************************************************
// check for new message
//************************************************************************
telnet_check_message (telnet);
}
else
{
//************************************************************************
// if server is listening
//************************************************************************
if ( tcp_get_state (telnet-> server) == TCP_LISTEN )
{
//**********************************************************************
// but status connected
//**********************************************************************
if ( telnet-> so_state == SOCKET_CONNECTED)
{
//********************************************************************
// clear status
//********************************************************************
telnet-> so_state = SOCKET_DISCONNECTED;
}
}
}
}
uint16_t tcp_tx_complete ( SOCKET *  so)
Parameters
so- valid socket
Returns
  • TRUE transmission complete
  • FALSE waiting for acknowledge

Check if all TCP data were acknowledged by the remote side. This may significantly decrease the performance, because a high performance TCP lives from the benefit of multiple packets being on the way (sliding window) and sending out the next portion of data even when the previous packet has not been acknowledged yet. As long as the remote side signals free buffer space, it is allowed to send out the next packet. To get track of which packets are on the way and which packets were transmitted and acknowledged, use function tcp_pending_window().

Library:
net.lib
Prototype:
net.h
//******************************************************************************
//
// @brief send data, check error condition, wait for completion
// @param socket - established TCP socket or UDP socket
// @param data - pointer to the beginning of data
// @param size - size of data [in DATATYPE counts]
// @param wait - wait for tcp completion (TCP only)
// @return 1 if successful or 0 in case of error
//
//******************************************************************************
int32_t net_send_safe (SOCKET *socket, void *data, uint32_t size, uint16_t wait)
{
//**************************************************************************
// locals
//**************************************************************************
unsigned char *bptr; // base pointer to data
uint32_t length = size<<socket-> data_shift;// block length
uint32_t max_packet_size; // max packet size
uint32_t send_length; // packet length
int32_t net_send_return = NET_SEND_PENDING; // net_send() return value
uint16_t wait_for_completion; // wait for completion flag
//**************************************************************************
// base pointer to data
//**************************************************************************
bptr= (unsigned char *)data;
//**************************************************************************
// depending on protocol setup max packet size
//**************************************************************************
max_packet_size = (socket-> proto == IPT_TCP)? TCP_MAX_PACKET_SIZE : UDP_MAX_PACKET_SIZE;
while ( length > 0L )
{
//**********************************************************************
// limit send length to maximum packet size
//**********************************************************************
send_length = ((length > max_packet_size) ? max_packet_size : length);
net_isq ();
//**********************************************************************
// @important note:
// net_send() must not be called while errors are pending
//**********************************************************************
if ( socket-> error_code == SO_NO_ERROR )
{
net_send_return = net_send (socket, bptr, (uint16_t)send_length>>socket-> data_shift);
//******************************************************************
// advance base pointer, decrement length
//******************************************************************
bptr+= send_length;
length -= send_length;
} // if
else
{
net_send_return = NET_SEND_PENDING;
}
//**********************************************************************
// handle event conditions:
// some events must be monitored to detect connection or link loss
//**********************************************************************
if (net_send_event_handler (socket, CPrintf, net_send_return))
{
//******************************************************************
// a fatal error was detected, terminate this function immediately
//******************************************************************
return (0L);
}
if ( (socket-> proto == IPT_TCP) && (tcp_get_state (socket) != TCP_ESTABLISHED ) )
{
//******************************************************************
// sending TCP data if not established makes no sense
//******************************************************************
return (0L);
}
} // while ( length > 0 )
//**************************************************************************
// TCP sockets only: wait for completion
// this is required if the data content is going to be changed after leaving
// this function (e.g. for re-transmits).
//**************************************************************************
wait_for_completion = (socket-> proto == IPT_TCP)? wait: 0;
while ( wait_for_completion)
{
if ( tcp_tx_complete(socket) )
{
break;
} // if
net_isq ();
}
return (1L);
}
Examples:
Blocksend.c.
uint32_t tcp_pending_window ( SOCKET *  so)
Parameters
so- valid socket
Returns
  • 0 - transmission complete
  • >0 - transmission pending
  • 0xFFFFFFFF - Invalid socket or not established

This function returns the amount of data (in bytes) that is waiting for to be acknowledged (data that has been passed to the stack with function net_send()). It is useful to get track of buffers currently in use to handle ring-buffering or just to verify successful transmission. When tested for return value 0 this function replaces tcp_tx_complete().

Library:
net.lib
Prototype:
net.h
uint16_t tcp_force_retransmit ( SOCKET *  so)
Parameters
so- valid socket
Returns
  • 1 - Socket error
  • 0 - function proceeded

If this function is called, a retransmit of the oldest pending packet is forced. This is useful when the remote side has not acknowledged outstanding packets for a certain time and the DSP needs to maintain the buffers.

Library:
net.lib
Prototype:
net.h
int16_t tcp_set_keep_alive_time ( SOCKET *  so,
uint32_t  time 
)
Parameters
so- the socket to use
time- keep alive time
Returns
(-1) invalid socket

Set keep alive time. When a TCP connection is idle for a certain time, internet routers may drop the connection due to time-out. To prevent the connection being dropped, KEEP ALIVE packets are used. A KEEP ALIVE packet is a valid TCP packet with NULL data bytes and must be acknowledged by the remote connected side. This effect can be used to keep track of a connection path even over routers or multiple switches. When three consecutive KEEP ALIVE packets were not acknowledged by the remote side, the socket error code is set to SO_TIMED_OUT. The user can handle this condition to try a re-connect().

Library:
net.lib
Prototype:
net.h
See also
SO_TIMED_OUT
//****************************************************************************
// open socket
//****************************************************************************
tcp_socket = socket_open (ANY_ADDRESS,
5031,
if ( tcp_socket == INVALID_SOCKET )
{
prg_exit ("socket_open() failed");
} // if
//****************************************************************************
// set keep alive time
//****************************************************************************
tcp_set_keep_alive_time (tcp_socket, 1500000); // ~10s
Examples:
Blocksend.c, and Echo.c.
void tcp_send_zero_window ( void *  so)
Parameters
so- the socket to use
Returns
nothing

When time consuming operations are required which do not allow to call the main network processing function net_isq() (e.g. FLASH erase or program) or when no local buffer is available, use this function to prevent the remote side to send new data. This function immediately sends out a Zero Window TCP packet on the given connected socket which stops data packet transmission on this socket. Use function tcp_send_window_update() when the time consuming operation has finished or when a new buffer is available.

Library:
net.lib
Prototype:
net.h
See also
tcp_send_window_update()
Examples:
Echo.c.
void tcp_send_window_update ( void *  so)
Parameters
so- the socket to use
Returns
nothing

This functions sends out an Window Update packet. Necessary after the TCP was stopped before by function tcp_send_zero_window().

Library:
net.lib
Prototype:
net.h
See also
tcp_send_zero_window()
Examples:
Echo.c.