BSD Sockets#

This section provides a reference to BSD Socket API functions.

The BSD socket implementation tries to emulate the standards library to the extent possible for embedded offerings from Silabs. There are substantial limitation/exceptions however, and those are mentioned under Note section in the subsequent API documentation of BSD sockets.

Note

  • BSD Sockets support only synchronous socket operations. For asynchronous operations, refer to the SiWx91x sockets.

Modules#

sockaddr

TOS Defines

Socket Type

Socket Option Name

TLS Option Value

Socket Option Level

Socket Address Family

Socket Protocol

Typedefs#

typedef uint32_t

Socket Length is internal type.

typedef __socklen_t

Public type for socket length.

typedef uint8_t

Internal type for sockaddr address family.

Public type for sockaddr address family.

Functions#

int
socket(int domain, int type, int protocol)

Create an endpoint for communication.

int
bind(int socket_id, const struct sockaddr *addr, socklen_t addr_len)

Bind a name to a socket.

int
listen(int socket_id, int backlog)

Listen for connections on a socket.

int
accept(int socket_id, struct sockaddr *addr, socklen_t *addr_len)

Accept a connection on a socket.

int
connect(int socket_id, const struct sockaddr *addr, socklen_t addr_len)

Initiate a connection on a socket.

ssize_t
recv(int socket_id, void *buf, size_t buf_len, int flags)

Receive a message from a socket.

ssize_t
recvfrom(int socket_id, void *buf, size_t buf_len, int flags, struct sockaddr *from_addr, socklen_t *from_addr_len)

Receive a message from a socket.

ssize_t
send(int socket_id, const void *buf, size_t buf_len, int flags)

Send a message on a socket.

ssize_t
sendto(int socket_id, const void *buf, size_t buf_len, int flags, const struct sockaddr *to_addr, socklen_t to_addr_len)

Send a message on a socket.

int
setsockopt(int socket_id, int option_level, int option_name, const void *option_value, socklen_t option_length)

Set options on a socket.

int
getsockopt(int socket_id, int option_level, int option_name, void *option_value, socklen_t *option_length)

Get options on a socket.

int
getpeername(int socket_id, struct sockaddr *name, socklen_t *name_len)

Get the name of the connected peer socket.

int
getsockname(int socket_id, struct sockaddr *name, socklen_t *name_len)

Get the current address assigned to a socket.

int
close(int socket_id)

Close a socket.

Typedef Documentation#

__socklen_t#

__socklen_t

Socket Length is internal type.

It represents the length of a socket address that is used internally within network system calls to specify the size of address structures.


socklen_t#

socklen_t

Public type for socket length.

It is a public alias for the internal __socklen_t type. You can use it to specify the length of socket addresses in the network system calls.


__sa_family_t#

__sa_family_t

Internal type for sockaddr address family.

The address family of a socket address is used internally within the system to specify the address type (for example, IPv4 and IPv6).


sa_family_t#

sa_family_t

Public type for sockaddr address family.

It is a public alias for the internal ___sa_family_t. It specifies the address family of a socket address in user applications.


Function Documentation#

socket#

int socket (int domain, int type, int protocol)

Create an endpoint for communication.

Parameters
TypeDirectionArgument NameDescription
int[in]domain

Specifies a communication domain, selecting the protocol family to be used for communication. Must be one of the values from Socket Address Family. Only AF_INET and AF_INET6 are supported.

int[in]type

Specifies the semantics of communication for the socket. Must be one of the values from BSD_SOCKET_TYPES. Currently defined types are SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, and SOCK_SEQPACKET. Only SOCK_STREAM and SOCK_DGRAM are supported.

int[in]protocol

Specifies a particular protocol to be used with the socket. Normally, only a single protocol exists to support a particular socket type within a given protocol family. However, if multiple protocols exist, a specific protocol must be specified. The protocol number to use is specific to the communication domain. Must be one of the values from Socket Protocol. Use IPPROTO_TCP with SOCK_STREAM and IPPROTO_UDP with SOCK_DGRAM.

The socket() function creates an endpoint for communication and returns a file descriptor that refers to that endpoint. The file descriptor returned by a successful call would be the lowest-numbered file descriptor not currently open for the process.

  • Pre-conditions:

    • The Wi-Fi/Net stack must be initialized and a network profile (STA or AP) must be up.

    • If socket resources are configured using sl_si91x_config_socket(), that call must have been made before socket().

  • Post-conditions:

Returns

  • Returns the socket ID or file descriptor that references the socket upon success. Returns -1 if an error occurs and sets errno.

Return values

  • >=0: Valid socket descriptor.

  • -1/EAFNOSUPPORT: domain

  • -1/EPROTONOSUPPORT: protocol

  • -1/EINVAL: Invalid combination of

  • -1/EMFILE: No free socket descriptor available (socket pool exhausted).

  • -1/ENOMEM: Not enough memory to allocate the socket.

Note

  • Thread safety:

    • Thread-safe: multiple threads may call socket() concurrently to obtain distinct descriptors.

  • Side effects:

    • Allocates an entry in the internal socket pool. On failure, errno is updated.

  • The type supports SOCK_STREAM and SOCK_DGRAM only.

See Also

  • Example#

    Create a TCP/IPv4 stream socket and check for errors:

    int sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock_fd < 0) {
      printf("socket() failed, errno = %d\r\n", errno);
      return -1;
    }
    

Create a UDP/IPv4 datagram socket:

int udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udp_fd < 0) {
  printf("UDP socket() failed, errno = %d\r\n", errno);
  return -1;
}

bind#

int bind (int socket_id, const struct sockaddr * addr, socklen_t addr_len)

Bind a name to a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

const struct sockaddr *[in]addr

Pointer to a sockaddr structure containing the address to be assigned to the socket. Must be non-NULL and sa_family must match the family used in socket().

socklen_t[in]addr_len

The addr_len parameter specifies the size, in bytes, of the address structure pointed to by addr. Must be sizeof(struct sockaddr_in) for IPv4 or sizeof(struct sockaddr_in6) for IPv6.

When a socket is created with socket(), it exists in a namespace (address family) but, has no address assigned to it. The bind() function assigns the address specified by addr to the socket referred to by the file descriptor socket_id.
Traditionally, this operation is called "assigning a name to a socket".

It is normally necessary to assign a local address using bind() before a SOCK_STREAM socket may receive connections.

  • Pre-conditions:

    • socket_id must be a valid descriptor returned by socket().

    • bind() must be called before listen() on a TCP server socket and before sending/receiving on a UDP socket that needs a fixed local port.

  • Post-conditions:

    • On success the socket is associated with the supplied local address/port.

    • On failure the socket remains unbound; errno is set.

Returns

  • Returns 0 if successful. Otherwise, returns -1 and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: addr

  • -1/EADDRINUSE: The requested address/port is already in use.

  • -1/EAFNOSUPPORT: addr->sa_family

  • -1/EACCES: The requested address is protected and the caller lacks permission.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor. Serialize concurrent access to socket_id.

  • Side effects:

    • Reserves the local address/port in the stack; updates errno on failure.

See Also

  • Example#

    Bind a TCP server socket to any local interface on port 5000:

    struct sockaddr_in local_addr = { 0 };
    local_addr.sin_family      = AF_INET;
    local_addr.sin_port        = 5000;
    local_addr.sin_addr.s_addr = INADDR_ANY;
    
    if (bind(sock_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
      printf("bind() failed, errno = %d\r\n", errno);
      close(sock_fd);
      return -1;
    }
    

listen#

int listen (int socket_id, int backlog)

Listen for connections on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

int[in]backlog

The backlog argument defines the maximum number of pending connections that can be queued. Must be > 0 and typically must not exceed the configured maximum (see sl_si91x_config_socket()).

The listen() function marks the socket referred to by socket_id as a passive socket, that is, as a socket that would be used to accept incoming connection requests using accept(). This function applies only to sockets of type SOCK_STREAM or SOCK_SEQPACKET.

  • Pre-conditions:

    • socket_id must be a SOCK_STREAM socket created using socket() and bound using bind().

    • A willingness to accept incoming connections and a queue limit for incoming connections must be specified with listen(), and then the connections can be accepted with accept().

  • Post-conditions:

    • On success the socket transitions into the listening state and can be passed to accept().

    • On failure the socket state is unchanged; errno is set.

Returns

  • Returns 0 if successful. Otherwise, returns -1 and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EOPNOTSUPP: The socket type does not support

  • -1/EINVAL: The socket is not bound,

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Allocates a pending-connection queue of size backlog in the stack.

See Also

  • Example#

    Mark the TCP server socket as passive with a backlog of 1 connection:

    if (listen(sock_fd, 1) < 0) {
      printf("listen() failed, errno = %d\r\n", errno);
      close(sock_fd);
      return -1;
    }
    

accept#

int accept (int socket_id, struct sockaddr * addr, socklen_t * addr_len)

Accept a connection on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

Socket identification number of the socket to accept. This socket must have been created with socket(), bound to an address with bind(), and set to listen for connections with listen().

struct sockaddr *[out]addr

Pointer to a sockaddr structure that will be filled with the address of the connecting entity, as known to the communications layer. The exact format of the addr argument is determined by the domain in which the communication is occurring. A null pointer may be specified for addr if the address information is not desired; in this case, addr_len is not used and should also be null.

socklen_t *[inout]addr_len

Pointer to a socklen_t variable. Initially, it should contain the amount of space pointed to by addr. On return, it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types, currently with SOCK_STREAM. Must be non-NULL when addr is non-NULL.

The accept() system call is used with connection-based socket types (for example, SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket (socket_id), creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket (socket_id) is unaffected by this call.

If no pending connections are present on the queue and the original socket is not marked as non-blocking, this function blocks the caller until a connection is present. If the original socket is marked non-blocking and no pending connections are present on the queue, accept() returns an error. The accepted socket may not be used to accept more connections. The original socket (socket_id) remains open.

  • Post-conditions:

    • On success a new, connected socket descriptor is returned for the peer connection; addr / addr_len are populated (if non-NULL).

    • The original listening descriptor remains open and can be used for further accept() calls.

Returns

  • Returns a non-negative integer that is a descriptor for the accepted socket if successful. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • >=0: Descriptor for the accepted connection.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: The socket is not listening (no prior

  • -1/EWOULDBLOCK: The socket is non-blocking and no pending connections are available.

  • -1/EMFILE: No free socket descriptor to allocate for the accepted connection.

  • -1/ECONNABORTED: A connection is aborted before

Note

  • Thread safety:

    • Not thread-safe on the same listening descriptor; serialize concurrent accept() calls.

  • Side effects:

    • Allocates a new socket slot for the accepted connection.

  • The accept() system call only supports blocking mode.

See Also

  • Example#

    Accept an incoming TCP client connection on a previously listened socket:

    struct sockaddr_in client_addr = { 0 };
    socklen_t          client_len  = sizeof(client_addr);
    
    int client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &client_len);
    if (client_fd < 0) {
      printf("accept() failed, errno = %d\r\n", errno);
      close(sock_fd);
      return -1;
    }
    printf("Client connected from port %u\r\n", ntohs(client_addr.sin_port));
    

connect#

int connect (int socket_id, const struct sockaddr * addr, socklen_t addr_len)

Initiate a connection on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

const struct sockaddr *[in]addr

The addr argument of type sockaddr is the address is that to which datagrams are to be sent. Must be non-NULL; sa_family must match the socket family.

socklen_t[in]addr_len

The addr_len argument of type socklen_t indicates the amount of space pointed to by address, in bytes. Must be sizeof(struct sockaddr_in) for IPv4 or sizeof(struct sockaddr_in6) for IPv6.

The connect() system call connects the socket referred to by the file descriptor socket_id to the address specified by addr.
The addr_len argument specifies the size of addr. The format of the address in addr is determined by the address space of the socket socket_id; see socket() for further details.

If socket_id is of type SOCK_DGRAM, the connect() system call specifies the peer with which the socket is to be associated. If the socket is of type SOCK_STREAM, the connect() system call attempts to make a connection to another socket. The other socket is specified by addr, which is an address in the communications space of the socket. Each communications space interprets the addr argument in its own way. Generally, stream sockets may successfully connect() only once; datagram sockets can use connect() multiple times to change their association.

  • Post-conditions:

    • On success a TCP socket enters the connected state and can be used with send() / recv().

    • For UDP the peer is cached and /@refrecv() may be used without specifying a destination.

    • On failure the socket state is unchanged except for errno; the descriptor may need to be closed.

Returns

  • Returns 0 if successful. Otherwise, returns -1 and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: Invalid

  • -1/EFAULT: addr

  • -1/EAFNOSUPPORT: Address family does not match the socket family.

  • -1/ECONNREFUSED: Remote peer refused the connection.

  • -1/ETIMEDOUT: Connection attempt timed out.

  • -1/ENETUNREACH: No route to the remote peer.

  • -1/EALREADY: A previous connection attempt is still in progress.

  • -1/EISCONN: Socket is already connected.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Allocates internal TCP/TLS state. For TLS, initiates the handshake synchronously.

    • Updates errno on failure.

  • Connecting to an invalid address, such as a null address, will result in an EFAULT error.

See Also

  • Example#

    Connect a TCP client socket to a remote server at 192.168.0.100:5001:

    struct sockaddr_in server_addr = { 0 };
    server_addr.sin_family         = AF_INET;
    server_addr.sin_port           = 5001;
    sl_net_inet_addr("192.168.0.100", &server_addr.sin_addr.s_addr);
    
    if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
      printf("connect() failed, errno = %d\r\n", errno);
      close(sock_fd);
      return -1;
    }
    

recv#

ssize_t recv (int socket_id, void * buf, size_t buf_len, int flags)

Receive a message from a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

void *[out]buf

Pointer to the buffer that receives the data. Must be non-NULL.

size_t[in]buf_len

Length of the buffer pointed to by the buf parameter. Must be > 0.

int[in]flags

Controls the reception of the data. Currently, no flags are supported and this parameter should be set to 0.

The recv() function is normally used only on a connected socket. It receives messages from a socket and returns the length of the message on successful completion. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from. By default, recv() is a blocking API. To use it in a non-blocking manner, you can set the socket to non-blocking mode using setsockopt().

  • Pre-conditions:

    • For TCP the socket must be connected using connect() or obtained from accept().

    • For UDP the socket must be bound using bind() or connected using connect() to a peer.

  • Post-conditions:

    • On success buf contains the received bytes and the return value is the number of bytes read.

    • A return value of 0 indicates that the peer has performed an orderly shutdown (TCP).

Returns

  • Number of bytes received on success (0 on orderly peer close for TCP); -1 on error with errno set.

Return values

  • >0: Number of bytes read into

  • 0: Orderly shutdown by the peer (TCP).

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/ENOTCONN: Socket is not connected.

  • -1/EINVAL: buf

  • -1/EWOULDBLOCK: Non-blocking socket has no data available.

  • -1/ETIMEDOUT

  • -1/ECONNRESET: Peer reset the connection.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Blocks the calling thread unless SO_RCVTIMEO is set or the socket is non-blocking.

    • Updates errno on failure.

  • The recv() system call does not support any flags.

See Also

  • Example#

    Receive up to 1460 bytes from a connected TCP socket in a loop, processing the data on each successful read:

    uint8_t rx_buffer[1460];
    ssize_t bytes_read = 0;
    
    while ((bytes_read = recv(client_fd, rx_buffer, sizeof(rx_buffer), 0)) > 0) {
      ...
    }
    
    if (bytes_read < 0) {
      printf("recv() failed, errno = %d\r\n", errno);
    } else {
      printf("Peer closed the connection\r\n");
    }
    close(client_fd);
    

recvfrom#

ssize_t recvfrom (int socket_id, void * buf, size_t buf_len, int flags, struct sockaddr * from_addr, socklen_t * from_addr_len)

Receive a message from a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

void *[out]buf

Pointer to the buffer that receives the data. Must be non-NULL.

size_t[in]buf_len

The length of the buffer pointed to by the buf parameter, in bytes. Must be > 0.

int[in]flags

Controls the reception of the data. Currently, no flags are supported and this parameter should be set to 0.

struct sockaddr *[out]from_addr

Pointer to a socket address structure of type sockaddr that will be filled with the source address of the received message. If the source address is not required, this parameter can be NULL.

socklen_t *[inout]from_addr_len

A value-result argument of type socklen_t. Initially, it should contain the size of the buffer associated with from_addr. On return, it will be modified to indicate the actual size of the address stored there. If from_addr is NULL, this parameter is ignored. Must be non-NULL when from_addr is non-NULL.

The recvfrom() system call is used to receive messages from a socket and can be used to receive data on a socket whether or not it is connection-oriented. If from_addr is not a null pointer and the socket is not connection-oriented, the source address of the message is filled in.

  • Pre-conditions:

    • For UDP the socket must be bound using bind() (at least implicitly).

    • For TCP the socket must be connected or obtained from accept().

  • Post-conditions:

    • On success buf contains the datagram/segment bytes and, when from_addr is non-NULL, the source address is populated.

Returns

  • Returns the length of the message on successful completion. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • >=0: Number of bytes received (0 is valid for zero-length UDP datagrams).

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: buf

  • -1/EWOULDBLOCK: Non-blocking socket has no data available.

  • -1/ETIMEDOUT

  • -1/ECONNRESET: Peer reset the connection.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Blocks the calling thread unless SO_RCVTIMEO is set or the socket is non-blocking.

    • Truncated datagrams (UDP) cause silent discard of the excess bytes.

    • Updates errno on failure.

  • The recvfrom() system call does not support any flags.

See Also

  • Example#

    Receive a UDP datagram and retrieve the sender's address:

    uint8_t            buffer[1472];
    struct sockaddr_in peer_addr = { 0 };
    socklen_t          peer_len  = sizeof(peer_addr);
    
    ssize_t read_bytes = recvfrom(udp_fd,
                         buffer,
                         sizeof(buffer),
                         0,
                         (struct sockaddr *)&peer_addr,
                         &peer_len);
    if (read_bytes < 0) {
      printf("recvfrom() failed, errno = %d\r\n", errno);
    } else {
      printf("Received %d bytes from port %u\r\n", (int)n, ntohs(peer_addr.sin_port));
    }
    

send#

ssize_t send (int socket_id, const void * buf, size_t buf_len, int flags)

Send a message on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

const void *[in]buf

Pointer to the buffer containing the message to transmit. Must be non-NULL.

size_t[in]buf_len

The length of the message in bytes. Must be > 0 and must not exceed 1460 bytes for plain TCP/UDP or 1370 bytes for TLS.

int[in]flags

Controls the transmission of the data. Currently, no flags are supported and this parameter should be set to 0.

The send() function is used to transmit a message on a socket. This function can only be used when the socket is in a connected state. If the socket is connection-oriented, the protocol must support implied connect or the socket must be explicitly connected before use. No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1. If no message space is available at the socket to hold the message to be transmitted, then send() normally blocks, unless the socket is placed in non-blocking I/O mode.

  • Pre-conditions:

    • socket_id must be connected (TCP) or have cached a peer through connect() (UDP).

  • Post-conditions:

    • On success the data is passed to the stack for transmission. Return value indicates bytes accepted.

    • On failure no bytes are transmitted and errno is set.

Returns

  • Returns the number of bytes sent on success. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • >=0: Number of bytes accepted by the stack for transmission.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/ENOTCONN: Socket is not connected.

  • -1/EINVAL: buf

  • -1/EMSGSIZE: Message is too large to be sent atomically.

  • -1/EPIPE: Peer has closed the connection (TCP).

  • -1/ECONNRESET: Peer reset the connection.

  • -1/ENOBUFS: Not enough buffer space in the stack; try again later.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Enqueues the payload in the firmware send queue; transmission happens asynchronously.

    • Updates errno on failure.

    • The send() system call currently supports only blocking mode.

    • The send() system call does not guarantee that the packets are transmitted to the remote node; they are enqueued in the local queue.

    • The send() system call does not support any flags.

    • The send() system call can send a maximum of 1460 bytes in the case of plain TCP/UDP. For TLS, the maximum buffer length is 1370 bytes.

See Also

  • Example#

    Send a buffer on a connected TCP socket:

    const uint8_t tx_buffer[] = "Hello, server!";
    ssize_t sent = send(sock_fd, tx_buffer, sizeof(tx_buffer) - 1, 0);
    if (sent < 0) {
      printf("send() failed, errno = %d\r\n", errno);
    }
    

sendto#

ssize_t sendto (int socket_id, const void * buf, size_t buf_len, int flags, const struct sockaddr * to_addr, socklen_t to_addr_len)

Send a message on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

const void *[in]buf

Pointer to the buffer containing the message to transmit. Must be non-NULL.

size_t[in]buf_len

The length of the message in bytes. Must be > 0 and must not exceed 1460 bytes for plain TCP/UDP or 1370 bytes for TLS.

int[in]flags

Controls the transmission of the data. Due to firmware limitations, sendto() does not support any flags and this parameter should be set to 0.

const struct sockaddr *[in]to_addr

Pointer to a sockaddr structure containing the address of the target. Must be non-NULL for connectionless sockets unless the socket is already connected.

socklen_t[in]to_addr_len

Size of the address structure pointed to by to_addr, in bytes. Must be sizeof(struct sockaddr_in) for IPv4 or sizeof(struct sockaddr_in6) for IPv6.

The sendto() function is used to transmit a message on a socket. This function can be used at any time if the socket is in connectionless mode. If the socket is in connection mode, the protocol must support implied connect or the socket must be in a connected state before use. The address of the target is specified by to_addr with to_addr_len indicating its size. If the socket is in a connected state, the target address passed to sendto() is ignored. If the message is too long to pass atomically through the protocol, the error EMSGSIZE is returned, and the message is not transmitted.

  • Pre-conditions:

    • For UDP the socket must have been created using socket() (optionally bound using bind()).

    • For a connected socket, to_addr is ignored.

  • Post-conditions:

    • On success the data is passed to the stack for transmission.

    • On failure no bytes are transmitted and errno is set.

Returns

  • The number of octets sent. If an error occurred, a value of -1 is returned.

Return values

  • >=0: Number of bytes accepted by the stack for transmission.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: Invalid argument (

  • -1/EAFNOSUPPORT: to_addr

  • -1/EMSGSIZE: Message is too large to be sent atomically.

  • -1/ENOBUFS: Not enough buffer space in the stack; try again later.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Enqueues the datagram in the firmware send queue; transmission happens asynchronously.

    • Updates errno on failure.

    • The sendto() system call can only send a maximum of 1460 bytes in the case of plain TCP/UDP. For TLS, the maximum buffer length is 1370 bytes.

    • The sendto() system call does not support any flags.

See Also

  • Example#

    Send a UDP datagram to a specific remote address/port:

    const uint8_t      payload[]    = "Hello UDP";
    struct sockaddr_in target_addr  = { 0 };
    target_addr.sin_family          = AF_INET;
    target_addr.sin_port            = 5002;
    sl_net_inet_addr("192.168.0.100", &target_addr.sin_addr.s_addr);
    
    ssize_t sent = sendto(udp_fd,
                          payload,
                          sizeof(payload) - 1,
                          0,
                          (const struct sockaddr *)&target_addr,
                          sizeof(target_addr));
    if (sent < 0) {
      printf("sendto() failed, errno = %d\r\n", errno);
    }
    

setsockopt#

int setsockopt (int socket_id, int option_level, int option_name, const void * option_value, socklen_t option_length)

Set options on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

int[in]option_level

The level at which the option is being set. One of the values from Socket Option Level.

int[in]option_name

The option to be configured. Accepts values from Socket Option Name. Currently, following options are supported:

const void *[in]option_value

A pointer to the buffer containing the value for the option. Most socket-level options utilize an int argument for option_value. For boolean options, set option_value to a non-zero value to enable the option or to zero to disable it. For non-boolean options, option_value should contain the specific data required for the option. The value of the parameter.

option_name

option_value

description

SO_RCVTIMEO

sl_si91x_time_value

Socket Receive timeout. sl_si91x_time_value structure is used to represent time in two parts: seconds and microseconds.

SO_KEEPALIVE

uint16_t

Set TCP keepalive in seconds

SO_MAX_RETRANSMISSION_TIMEOUT_VALUE

uint8_t

Maximum retransmission timeout value that should be in the power of 2 for TCP in seconds

TCP_ULP

uint8_t

Supported one of the values from TLS Option Value

IP_TOS

uint16_t

Supported one of the values from TOS Defines (Values 0-7 are deprecated)

SL_SO_CERT_INDEX

uint8_t

Supported values for certificate index range from 0 - 3

SL_SO_HIGH_PERFORMANCE_SOCKET

BIT(7)

Set high performance socket

SL_SO_TLS_SNI

sl_si91x_socket_type_length_value_t

Server name indication for the socket

SL_SO_TLS_ALPN

sl_si91x_socket_type_length_value_t

Application layer protocol negotiation for the socket

SL_SO_VERIFY_DOMAIN_NAME

uint8_t *

Expected domain name for TLS certificate verification; firmware uses this for server certificate CN/SAN check.

socklen_t[in]option_length

The length of the option data, in bytes, pointed to by option_value. Must match the type expected by option_name (see the table above).

The setsockopt() system call manipulates the options associated with a socket. Options may exist at multiple protocol levels; they are always present at the uppermost "socket" level. When manipulating socket options, the level at which the option resides and the name of the option must be specified. To manipulate options at the socket level, option_level is specified as SOL_SOCKET. To manipulate options at any other level, the protocol number of the appropriate protocol controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, option_level should be set to the protocol number of TCP. The option_value and option_length arguments are used to access option values for setsockopt().

  • Post-conditions:

    • On success the option is applied to the socket. Subsequent calls on the socket observe the new behavior.

    • On failure the option is unchanged and errno is set.

Returns

  • Returns 0 on successful completion. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: option_value

  • -1/ENOPROTOOPT: option_name

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Changes internal state of the socket (timeouts, TLS parameters, keepalive, etc.).

    • TLS options alter the next connect() handshake.

  • The options SL_SO_CERT_INDEX, SL_SO_HIGH_PERFORMANCE_SOCKET, SL_SO_TLS_SNI, SL_SO_TLS_ALPN, and SL_SO_VERIFY_DOMAIN_NAME are Silicon Labs specific options. This function is used before the socket is connected.

See Also

  • Example#

    1. Set a 5-second receive timeout on a socket:

      struct sl_si91x_time_value rx_timeout = { .tv_sec = 5, .tv_usec = 0 };
      if (setsockopt(sock_fd,
                     SOL_SOCKET,
                     SO_RCVTIMEO,
                     &rx_timeout,
                     sizeof(rx_timeout)) < 0) {
        printf("setsockopt(SO_RCVTIMEO) failed, errno = %d\r\n", errno);
      }
      
    2. Enable TCP keepalive (30 seconds):

      uint16_t keepalive_sec = 30;
      if (setsockopt(sock_fd,
                     SOL_SOCKET,
                     SO_KEEPALIVE,
                     &keepalive_sec,
                     sizeof(keepalive_sec)) < 0) {
        printf("setsockopt(SO_KEEPALIVE) failed, errno = %d\r\n", errno);
      }
      
    3. Enable TLS 1.2 on the socket prior to connect():

      if (setsockopt(sock_fd,
                     SOL_TCP,
                     TCP_ULP,
                     TLS_1_2,
                     sizeof(TLS_1_2)) < 0) {
        printf("setsockopt(TCP_ULP) failed, errno = %d\r\n", errno);
      }
      
    4. Select the TLS certificate stored at index 1:

      uint8_t cert_index = 1;
      if (setsockopt(sock_fd,
                     SOL_SOCKET,
                     SL_SO_CERT_INDEX,
                     &cert_index,
                     sizeof(cert_index)) < 0) {
        printf("setsockopt(SL_SO_CERT_INDEX) failed, errno = %d\r\n", errno);
      }
      

getsockopt#

int getsockopt (int socket_id, int option_level, int option_name, void * option_value, socklen_t * option_length)

Get options on a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

int[in]option_level

The level at which the option is defined. One of the values from Socket Option Level.

int[in]option_name

The name of the option to retrieve. One of the values from Socket Option Name. The option_name argument and any specified options are passed uninterpreted to the appropriate protocol module for interpretation.

void *[out]option_value

Pointer to a buffer where the retrieved option value will be stored. Must be non-NULL.

socklen_t *[inout]option_length

A value-result argument of type socklen_t. Initially, it should contain the size of the buffer pointed to by option_value. On return, it will be modified to indicate the actual size of the value returned. If no option value is to be supplied or returned, option_value may be NULL. Must be non-NULL; initial value must be >= the size required by option_name.

The getsockopt() system call retrieves the options associated with a socket. Options may exist at multiple protocol levels; they are always present at the uppermost "socket" level. When retrieving socket options, the level at which the option resides and the name of the option must be specified. To retrieve options at the socket level, option_level is specified as SOL_SOCKET. To retrieve options at any other level, the protocol number of the appropriate protocol controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, option_level should be set to the protocol number of TCP. The option_value and option_length arguments identify a buffer in which the value for the requested options are to be returned.

  • Pre-conditions:

    • socket_id must be a valid descriptor returned by socket().

  • Post-conditions:

    • On success option_value is populated and option_length is updated with the number of bytes written.

Returns

  • Returns 0 on successful completion. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: option_value

  • -1/ENOPROTOOPT: option_name

Note

  • Thread safety:

    • Not thread-safe on the same descriptor; serialize concurrent access.

  • Side effects:

    • Updates errno on failure. Does not modify socket behavior.

  • The following options are currently supported:

    • SO_RCVTIMEO: Receive timeout.

    • SO_KEEPALIVE: Keep connections alive.

    • TCP_ULP: TCP upper layer protocol.

    • SO_MAX_RETRANSMISSION_TIMEOUT_VALUE: Maximum retransmission timeout value.

    • IP_TOS: Type of service.

See Also

  • Example#

    Read back the current receive timeout of a socket:

    struct sl_si91x_time_value rx_timeout = { 0 };
    socklen_t                  opt_len    = sizeof(rx_timeout);
    
    if (getsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &rx_timeout, &opt_len) < 0) {
      printf("getsockopt(SO_RCVTIMEO) failed, errno = %d\r\n", errno);
    } else {
      printf("Current RX timeout: %ld sec, %ld usec\r\n",
             (long)rx_timeout.tv_sec,
             (long)rx_timeout.tv_usec);
    }
    

getpeername#

int getpeername (int socket_id, struct sockaddr * name, socklen_t * name_len)

Get the name of the connected peer socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

struct sockaddr *[out]name

Pointer to a sockaddr structure that will be filled with the address of the peer socket. Must be non-NULL.

socklen_t *[inout]name_len

A value-result argument of type socklen_t. Initially, it should contain the size of the buffer pointed to by name. On return, it will be modified to indicate the actual size of the address returned (in bytes). Must be non-NULL.

The getpeername() system call returns the address of the peer connected to the socket specified by socket_id. The address is returned in the buffer pointed to by name, and the actual size of the address is returned in the variable pointed to by name_len. If the buffer provided is too small, the address is truncated.

  • Pre-conditions:

  • Post-conditions:

    • On success name is populated with the peer's address and name_len is updated with the actual size.

Returns

  • Returns 0 on success. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/ENOTCONN: Socket is not connected.

  • -1/EINVAL: name

Note

  • Thread safety:

    • Safe to call concurrently with I/O on the same descriptor; read-only access to socket state.

  • Side effects:

    • Updates errno on failure. Does not modify socket behavior.

See Also

  • Example#

    Fetch the remote peer's address for a connected TCP socket:

    struct sockaddr_in peer_addr = { 0 };
    socklen_t          peer_len  = sizeof(peer_addr);
    
    if (getpeername(client_fd, (struct sockaddr *)&peer_addr, &peer_len) < 0) {
      printf("getpeername() failed, errno = %d\r\n", errno);
    } else {
      printf("Peer port: %u\r\n", ntohs(peer_addr.sin_port));
    }
    

getsockname#

int getsockname (int socket_id, struct sockaddr * name, socklen_t * name_len)

Get the current address assigned to a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

struct sockaddr *[out]name

Pointer to a sockaddr structure that will be filled with the address of the socket. Must be non-NULL.

socklen_t *[inout]name_len

A value-result argument of type socklen_t. Initially, it should contain the size of the buffer pointed to by name. On return, it will be modified to indicate the actual size of the address returned (in bytes). Must be non-NULL.

The getsockname() system call returns the current address to which the socket socket_id is bound. The address is returned in the buffer pointed to by name, and the actual size of the address is returned in the variable pointed to by name_len. If the buffer provided is too small, the address is truncated.

  • Pre-conditions:

    • socket_id must be a descriptor returned by socket(). The socket should be bound (explicitly using bind() or implicitly).

  • Post-conditions:

    • On success name is populated with the local address/port and name_len is updated with the actual size.

Returns

  • Returns 0 on success. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EINVAL: name

Note

  • Thread safety:

    • Safe to call concurrently with I/O on the same descriptor; read-only access to socket state.

  • Side effects:

    • Updates errno on failure. Does not modify socket behavior.

See Also

  • Example#

    Retrieve the local address/port bound to a socket (useful when port was 0):

    struct sockaddr_in local_addr = { 0 };
    socklen_t          local_len  = sizeof(local_addr);
    
    if (getsockname(sock_fd, (struct sockaddr *)&local_addr, &local_len) < 0) {
      printf("getsockname() failed, errno = %d\r\n", errno);
    } else {
      printf("Bound to local port %u\r\n", ntohs(local_addr.sin_port));
    }
    

close#

int close (int socket_id)

Close a socket.

Parameters
TypeDirectionArgument NameDescription
int[in]socket_id

The socket ID or file descriptor for the specified socket.

The close() function closes a socket identified by socket_id, so that it no longer refers to any file and can be reused. This function releases the resources associated with the socket and makes the socket descriptor available for reuse.

  • Pre-conditions:

  • Post-conditions:

    • The descriptor is released back to the pool and must not be used for further operations.

    • Any pending I/O on the descriptor is aborted; queued unsent data may be discarded.

Returns

  • Returns 0 on success. Returns -1 on error and sets the global variable errno to indicate the error.

Return values

  • 0: Success.

  • -1/EBADF: socket_id

  • -1/ENOTSOCK: socket_id

  • -1/EIO: I/O error while finalising the close sequence.

Note

  • Thread safety:

    • Not thread-safe on the same descriptor. The caller must ensure that no other thread is operating on socket_id when close() is invoked.

  • Side effects:

    • Releases stack resources (TCP state, TLS context, internal buffers).

    • Closing a server socket or the first client socket may close all associated sockets (see note).

    • Calling close() on a server socket or the first client socket will close all associated sockets.

    • If close() is called on a non-existing socket, the error EBADF (Bad file descriptor) will be set in errno.

See Also

  • Example#

    Always close a socket in both success and error paths to avoid leaks:

    if (close(sock_fd) < 0) {
      printf("close() failed, errno = %d\r\n", errno);
    }
    sock_fd = -1;