18 KiB
Socket API
This chapter describes the socket use and the available APIs.
API Headers
Socket API can be fully harnessed by including the following header files:
#include net_interface.h
#include socket_api.h
Socket types available
Sockets are a common abstraction model for network communication and are used in most Operating Systems (OS). The 6LoWPAN stack API follows the Berkeley Software Distribution (BSD) socket API conventions closely with some extensions necessitated by the event-based scheduling model. The stack supports the socket types shown in Table 3-18.
Table 3-18 Socket types
Socket name | Socket description |
---|---|
SOCKET_UDP |
UDP socket type. |
SOCKET_TCP |
TCP socket type. |
SOCKET_ICMP |
ICMP raw socket type; see section ICMP socket instruction. |
SOCKET_RAW |
raw IPv6 socket type. |
ICMP socket instruction
When using Internet Control Message Protocol (ICMP) sockets, the minimum packet length is eight bytes where the first four bytes comprise the ICMP header, as described in Table 3-19. The stack will calculate the checksum automatically before transmitting the packet.
Table 3-19 General ICMP packet structure
Type | Code | Checksum | Payload | Notes |
---|---|---|---|---|
1 | 1 | 2 | n (min. 4) | Length in bytes |
0xXX |
0xXX |
0x00 0x00 |
n bytes | Transmit |
0xXX |
0xXX |
0xXX 0xXX |
n bytes | Receive |
ICMP echo request with four bytes of payload (ping6), as shown in Table 3-20.
Table 3-20 ICMP echo request
Type | Code | Checksum | Payload |
---|---|---|---|
0x80 |
0x00 |
0x00 0x00 |
0x00 0x01 0x02 0x03 |
ICMP echo response for the message, as shown in Table 6-4.
Table 3-21 ICMP echo response
Type | Code | Checksum | Payload |
---|---|---|---|
0x81 |
0x00 |
0xXX 0xXX |
0x00 0x01 0x02 0x03 |
Receive callback structure
When there is data to read from the socket, a receive callback function is called from the stack with the socket event parameter. A socket event can be, for example, a change in the state of the Transmission Control Protocol (TCP) socket and the socket Transmit (TX) process is ready or the process failed (SOCKET_TX_FAIL
or SOCKET_TX_DONE)
. All supported socket event types are listed in Table 3-22. The receive callback function must be defined when a socket is opened using the socket_open( )
API.
The socket call back structure, socket_callback_t
is defined as below:
typedef struct socket_callback_t {
uint8_t event_type;
int8_t socket_id;
int8_t interface_id;
uint16_t d_len;
uint8_t LINK_LQI;
} socket_callback_t;
Member | Description |
---|---|
event_type |
Socket event type as provided in Table 3-22. |
socket_id |
The ID of the socket that caused the event. |
interface_id |
The network interface ID. Same as received from arm_nwk_interface_init . |
d_len |
The length of data available or sent. |
LINK_LQI |
The Link Quality Indicator value if the interface can provide any. |
Table 3-22 Supported socket event types
Event type | Description |
---|---|
SOCKET_DATA |
Data received. |
SOCKET_CONNECT_DONE |
TCP connection ready. |
SOCKET_CONNECT_FAIL |
TCP connection failed. |
SOCKET_CONNECT_AUTH_FAIL |
TCP connection authentication failed. |
SOCKET_INCOMING_CONNECTION |
TCP connection state change from listen to establishment. |
SOCKET_TX_FAIL |
Socket data send failed. |
SOCKET_CONNECT_CLOSED |
TCP connection closed. |
SOCKET_CONNECTION_RESET |
TCP connection reset. |
SOCKET_NO_ROUTER |
No route available to destination. |
SOCKET_TX_DONE |
TX process done (one per datagram, or if stream will be called each time some data acknowledged) |
SOCKET_NO_RAM |
If no RAM is present. |
SOCKET_CONNECTION_PROBLEM |
If TCP is suffering a connection problem (a soft event, it continues to retry). |
An example parsing socket event:
#define APP_SOCK_RX_SIZE 250
/*Application socket payload buffer used for RX and TX*/
static uint8_t rx_buffer[APP_SOCK_RX_SIZE];
void main_receive
(SOCKET_NO_ROUTER
void *cb
)
{
socket_callback_t *cb_res = cb;
int16_t length;
if( cb_res->event_type == SOCKET_DATA )
{
sn_nsdl_addr_s sn_addr_s;
//Read data from the RX buffer
length = socket_read( cb_res->socket_id,
&app_src,
rx_buffer,
APP_SOCK_RX_SIZE );
if( length )
{
if( cb_res->socket_id == app_udp_socket )
{
// Handles data received in UDP socket
sn_nsdl_process_coap(rx_buffer, length, &sn_addr_s);
}
}
}
}
Using TCP sockets
When a TCP socket is opened, it is in an unusable state and must be set to either a listen or connect state before it can be used to receive or transmit data.
You can set the socket to a listen state with the socket_listen( )
function. After the call, the socket can accept an incoming connection from a remote host. The TCP implementation of the 6LoWPAN stack supports only one connection from a remote host.
To connect the TCP socket to a remote host, call socket_connect( )
with the correct arguments. After the function call, an application (non-blocking) must await the socket event to confirm the successful state change of the socket.
After receiving a successful state event, data can be sent using the socket_send( )
call.
The connection can be shut down by calling function socket_shutdown( )
. The 6LoWPAN stack shuts down the connection automatically after a server timeout or when the remote end closes the connection. When the socket is no longer needed it must be released by calling the function socket_close( )
.
Using UDP and ICMP sockets
A User Datagram Protocol (UDP) socket is ready to receive and send data immediately after a successful call to socket_open( )
. Data can then be transmitted using the socket_sendto( )
function call. The same function call can also be used for an ICMP socket.
Detailed Socket API usage
This section describes the socket layer functions in more detail. Each function is presented with example parameters and possible return values.
How to open a socket
To initialize a socket ready for communication:
int8_t socket_open
(
uint8_t protocol,
uint16_t identifier,
void (*passed_fptr)(void *)
)
Parameter | Description |
---|---|
protocol |
The protocol to be used over this socket and valid values for the argument are:SOCKET_UDP UDP: standard communication.SOCKET_TCP TCP: standard communication.SOCKET_ICMP ICMPv6: used for ping functionality.SOCKET_RAW raw IPv6: used for other specialised protocols. |
identifier |
The port identifier for UDP and TCP. 0 indicates that the port is not specified and it will be selected automatically when using the socket. The port can also be bound later with the function socket_bind() . |
passed_fptr |
A function pointer to the desired socket receive callback function. |
- Return value
- 0 Socket ID, used as a reference to the specific socket in subsequent calls.
- -1 No free sockets or invalid protocol.
How to release a socket
To release a socket:
int8_t socket_close( int8_t socket )
Parameter | Description |
---|---|
socket |
The socket ID of the socket to be released. |
- Return value
- 0 Socket release successful.
- -1 Socket release failed. Socket ID invalid or already released.
How to bind a socket
To bind socket to a port and address:
int8_t socket_bind
(
int8_t socket,
const ns_address_t *address
)
Parameter | Description |
---|---|
socket |
The socket ID returned by socket_open . |
address |
Structure that contains port and/or address to be bound to the socket. |
- Return value
- 0 on success.
- -1 if given address is NULL.
- -2 if port is already bound to another socket.
- -4 if socket is already bound.
- -5 bind is not supported on this type of socket.
The port and the address can be bound only once. The port can also be bound to the socket with the function socket_open( )
.
To bind a local address to a socket based on a destination address and address selection preferences:
int8_t socket_bind2addrsel
(
int8_t socket,
const ns_address_t *dst_address
)
Parameter | Description |
---|---|
socket |
The socket ID returned by socket_open . |
dst_address |
Destination address to which the socket wants to communicate. |
- Return value
- 0 on success.
- -1 if given address is NULL or socket ID is invalid.
- -2 if memory allocation failed.
- -3 if socket is already bound to address.
- -4 if interface cannot be found.
- -5 if source address selection fails.
- -6 bind2addrsel is not supported on this type of socket.
How to connect a socket
To connect a socket to a remote host:
int8_t socket_connect
(
int8_t socket,
ns_address_t *address,
uint8_t randomly_take_src_numbers
)
Parameter | Description |
---|---|
socket |
The socket ID, which is used to connect to the remote host. |
address |
A pointer to an address_t structure that contains the address of the remote host. |
randomly_take_src_numbers |
Value 1 indicates that a randomly selected source port number is used. |
- Return value
- 0 Valid request.
- -1 Fail.
How to read data from a socket
To read received data from a socket:
int16_t socket_read
(
int8_t socket,
ns_address_t *address,
uint8_t *buffer,
uint16_t length
)
Parameter | Description |
---|---|
socket |
The socket ID of the socket to be read. |
address |
A pointer to an address structure containing the source address of the packet (populated by the stack). Can be NULL. |
buffer |
A pointer to a byte array containing the payload of the packet. |
length |
The length of the payload data to be stored in the buffer. |
- Return value
- > 0 The length of the data copied to the buffer.
- 0 No data is available to read.
- -1 Invalid input parameters.
The application receives an event type SOCKET_DATA
to its receive socket callback when the data is available. The application
must read the data from the callback because the stack frees the data after it has called the receive socket callback.
All data must be read by one call. If data is too long to fit in the supplied buffer the excess bytes are discarded.
How to send data to a socket
To transmit data using a socket, the 6LoWPAN stack offers two different functions depending on the transport layer protocol that is used, as shown in Table 3-23.
After successfully calling the function, the application must await the TX process to complete.
Table 3-23 The two transmit function calls
Function | Socket types |
---|---|
socket_sendto( ) |
UDP, ICMP and RAW |
socket_send( ) |
TCP, or UDP if connected |
Table 3-24 describes the possible response events when the outcome of the function call is successful.
Table 3-24 The possible response events following a successful function call
Response Event | Socket Type | Description |
---|---|---|
SOCKET_TX_DONE |
TCP/UDP | UDP: link layer TX ready (d_len = length of datagram). TCP: some data acknowledged (d_len = unacknowledged data remaining in send queue). |
SOCKET_TX_FAIL |
TCP/UDP | UDP: link layer TX fails. TCP: transmit timeout (no ACKs) and connection closed. |
SOCKET_CONNECTION_RESET |
TCP | Either the peer reset the connection or there was a protocol error. Connection closed. |
To transmit data on an unconnected socket:
int8_t socket_sendto
(
int8_t socket,
ns_address_t address,
uint8_t *buffer,
uint16_t length
)
Parameter | Description |
---|---|
socket |
The socket ID to use for transmission. |
address |
A pointer to an address structure containing the destination address of the packet (populated by the application). |
buffer |
A pointer to a byte array containing the payload of the packet. |
length |
The length of the payload data in the buffer. |
- Return value
- >0 Data packet accepted by the stack.
- -1 Fail.
To send data via a connected socket:
Note: A socket connection must be ready before using this function. The stack will automatically use the address of the remote connected host address as the destination for the packet.
int8_t socket_send
(
int8_t socket,
uint8_t *buffer,
uint16_t length
)
Parameter | Description |
---|---|
socket |
The socket ID to use for transmission. |
buffer |
A pointer to a byte array containing the payload of the packet. |
length |
The length of the payload data in the buffer. |
- Return value
- >0 Data packet accepted by the stack.
- -1 Fail.
TCP socket configuration
The TCP socket configuration API offers three function calls, as shown in Table 3-25 and are further described.
Table 3-25 The TCP socket configuration functions
Function | Description |
---|---|
socket_listen() |
Set socket to the listen state. |
socket_accept() |
Accepts an incoming TCP connection. |
socket_shutdown() |
Shut down socket connection. |
To set a TCP socket into the listen state:
int8_t socket_listen
(
int8_t socket,
uint8_t backlog
)
Parameter | Description |
---|---|
socket |
The socket ID that is to be set to the listen state. |
backlog |
The pending connections queue size. |
- Return value
- 0 Valid request.
- -1 Fail.
For connecting a socket, please refer to the section above How to connect a socket.
There are three possible responses from the stack for socket_connect( )
:
-
SOCKET_CONNECT_DONE
- TCP handshake ready.
-
SOCKET_CONNECT_FAIL
- TCP handshake fail - connection actively refused or protocol error.
-
SOCKET_TX_FAIL
- TCP handshake fail - timed out.
For accepting an incoming TCP connection, use socket_accept()
function.
int8_t socket_accept()
(
int8_t listen_socket_id,
ns_address_t *addr,
void (*passed_fptr) (void *)
)
Parameter | Description |
---|---|
listen_socket_id |
The socket ID of the listening socket. |
addr |
Pointer to the address structure where you wish to save the address |
passed_fptr |
A function pointer to a function that is called whenever a data frame is received to the new socket |
- Return value
- 0 or greter than zero, i.e., id for the new socket.
- -1 Fail.
To shut down a TCP connection:
int8_t socket_shutdown
(
int8_t socket,
uint8_t how
)
Parameter | Description |
---|---|
socket |
The socket ID of the socket to be shut down. |
how |
How socket is to be shut down, one of SOCKET_SHUT_RD , SOCKET_SHUT_WR or SOCKET_SHUT_RDWR . |
- Return value
- 0 Valid request.
- Note:This does not imply that the state of the socket has been successfully changed.
- -1 Fail.
Modifying socket options
To specify miscellaneous options for a socket:
int8_t socket_setsockopt
(
int8_t socket,
uint8_t level,
uint8_t opt_name,
const void *opt_value,
uint16_t opt_len
)
Parameter | Description |
---|---|
socket |
The socket ID. |
level |
The option level. |
opt_name |
The option name. |
opt_value |
A pointer to the value of the specified option. |
opt_len |
The size of the data pointed to by a value. |
- Return value
- 0 Done.
- -1 Invalid socket ID.
- -2 Invalid or unsupported option.
- -3 Invalid option value.
Each socket has unique control of the following items:
- IPv6 traffic class, option name:
SOCKET_IPV6_TCLASS
- Socket source address mode, option name:
SOCKET_IPV6_ADDRESS_SELECT
A socket uses a configured setup until the user changes it with a new function call.
Note: SOCKET_IPV6_ADDRESS_SELECT
is only supported when the interface bootstrap address mode is NET_6LOWPAN_MULTI_GP_ADDRESS
.
How to set address mode for a socket
A socket can be configured to use a primary or secondary address as the source address when transmitting packets using socket_sendto( )
. The primary (default) address is an IPv6 address that is created using a short address type, whereas the secondary address, also IPv6 based, is created using a MAC address type. The source address is currently the only configurable parameter using socket_configuration
and when multimode is not used, the source address configuration has no effect. The primary address is the default address when no configuration is needed.
int8_t set_coap_socket_src_address_mode(int16_t address_mode)
{
return socket_setsockopt(app_udp_socket,SOCKET_IPPROTO_IPV6,
SOCKET_IPV6_ADDRESS_SELECT, &address_mode),sizeof(address_mode)));
}
How to set traffic class for a socket
You can use socket_setsockopt()
to set the socket traffic class. When this option is set, it will stay until modified. Therefore, if you want to set the class for one specific packet, you must call socket_setsockopt()
again with a default traffic class after the packet has been sent.
Parameters for Traffic class:
Parameter | Description |
---|---|
socket |
The socket identified. |
level |
SOCKET_IPPROTO_IPV6 |
opt_name |
SOCKET_IPV6_TCLASS |
opt_value |
A pointer to int16_t value. Valid values are from 0 to 255. -1 is for system default. |
opt_len |
The size of int16_t , 2 bytes. |
RFC 4594 specifies the appropriate traffic class values. The 6LoWPAN stack does not interpret the specified traffic class. It is just passed through.
How to set flow label for a socket
You can use socket_setsockopt()
to set the socket flow label.
Parameters for flow label:
Parameter | Description |
---|---|
socket |
The socket identified. |
level |
SOCKET_IPPROTO_IPV6 |
opt_name |
SOCKET_IPV6_FLOW_LABEL |
opt_value |
A pointer to int32_t value. Valid values are from 0 to 0xfffff . -1 is for system default (set with arm_nwk_ipv6_auto_flow_label() ). -2 will always autogenerate a flow label, regardless of system default. |
opt_len |
The size of int32_t , 4 bytes. |
The stack auto-generates flow labels on outgoing packets following the guidelines in RFC 6437. The stack does not interpret the flow label on received packets, and nor does the socket API report flow label to the application.