Wi-SUN Sockets#

Wi-SUN sockets are based on the well-known BSD socket API, also known as the POSIX socket API. Each socket represents a handle for the local endpoint of a communication circuit.

Earlier Silicon Labs socket API was deprecated in release 1.8 and removed in release 2.0.

API Overview#

While Wi-SUN sockets follow the BSD socket API conventions, there are some limitations and omissions in the implementation as described below.

  • Wi-SUN FAN supports only IPv6, so none of the IPv4-specific socket functionality is available

  • Socket handles are specific to Wi-SUN sockets and cannot be used as file descriptors in C library function calls or other APIs

  • POSIX signals are not supported, socket signaling uses Wi-SUN API events instead

Functions supported:

Following functions are not supported:

  • gethostbyname()

  • gethostbyaddr()

  • poll()

Migration to BSD Socket API#

The following table details the mapping between the BSD socket API and the former Silicon Labs socket API.

Former Silicon Labs Socket API Function

BSD Function

sl_wisun_open_socket()

socket()

sl_wisun_bind_socket()

bind()

sl_wisun_listen_on_socket()

listen()

sl_wisun_connect_socket()

connect()

sl_wisun_accept_on_socket()

accept()

sl_wisun_send_on_socket()

send()

sl_wisun_sendto_on_socket()

sendto()

sl_wisun_receive_on_socket()

recv()

sl_wisun_close_socket()

close()

sl_wisun_get_socket_option()

getsockopt()

sl_wisun_set_socket_option()

setsockopt()

Socket Life Cycle#

In general, a socket is created by explicitly calling socket() and must be explicitly closed by calling close(). This both closes the communication circuit and frees any resources allocated to the socket.

In certain protocols, the communication circuit may be closed by the remote peer. This is indicated with a SL_WISUN_MSG_SOCKET_CLOSING_IND_ID event. Although the socket connection is closed, the system resources will not be freed until the application calls close().

Exchanging Data#

Certain protocols require a socket in a connected state, meaning the underlying protocol must first establish a session with the remote peer before data can be exchanged. It is also optionally possible on certain connectionless protocols. In either case, connecting a socket creates a direct communication link with a remote peer, allowing the socket to be used only with that particular peer.

To switch a socket into connected state, use connect(). See the table below for protocol details.

Protocol

Unconnected

Connected

IPPROTO_UDP

MAY

MAY

IPPROTO_TCP

MUST NOT

MUST

IPPROTO_ICMP

MUST

MUST NOT

Transmit#

When a socket is in unconnected state, sendto() is used to transmit data. The function requires the application to specify the remote peer address and port number on each call. When a socket is connected, send() is used instead. Because the socket is "locked" into a single remote peer, address and port number are not needed.

A successful return code indicates the socket has buffered the provided data and the application may free the data resources. The application receives a SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID event when a part or all buffered data has been sent, depending on the used protocol.

Receive#

To manage received socket data, the socket can be either in indication mode or in polling mode. All sockets default to polling mode.

In polling mode, the application will receive a SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID event on data reception. The received data is stored in the socket buffer until the application reads it using recv() or recvfrom(). A socket that generated a SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID will never block.

In indication mode, the received data is sent as a SL_WISUN_MSG_SOCKET_DATA_IND_ID event as soon as it is received. The application must either handle the data immediately or store it for later processing. Either way, the socket will not keep the data once the event handler returns.

Blocking operations#

By default, socket operations are blocking, i.e. the calling RTOS task is suspended until the socket operation completes. Sockets can be configured as non-blocking either by or'ing SOCK_NONBLOCK flag to the type parameter of socket(), or using the socket option SO_NONBLOCK. Only a single blocking operation per socket is allowed.

Client#

TCP Example#

  1. Open a TCP socket using socket(AFINET_6, SOCK_STREAM, IPPROTO_TCP).

  2. Initiate connection to the remote server using connect().

  3. Wait for SL_WISUN_MSG_SOCKET_CONNECTED_IND_ID event.

  4. ... Exchange data with the remote server ...

  5. Close the socket using close().

UDP Example#

  1. Open an UDP socket using socket(AFINET_6, SOCK_DGRAM, IPPROTO_UDP).

  2. ... Exchange data with the remote server ...

  3. Close the socket using close().

Server#

TCP Example#

  1. Open a TCP socket using socket(AFINET_6, SOCK_STREAM, IPPROTO_TCP).

  2. Set the server socket port number using bind().

  3. Set the server socket into listening state using listen().

  4. Wait for SL_WISUN_MSG_SOCKET_CONNECTION_AVAILABLE_IND_ID event.

  5. Accept the client connection using accept() on the server socket.

  6. ... Exchange data with the remote client using the newly created client socket ...

  7. Close the client socket using close().

  8. Go to 4.

UDP Example#

  1. Open an UDP socket using socket(AFINET_6, SOCK_DGRAM, IPPROTO_UDP).

  2. Set the socket port number using bind().

  3. ... Exchange data with the remote client ...