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.
sl_wifi_get_saved_firmware_status() needs to be called to fetch the error code returned by the firmware if the API returns -1 and errno is 0.
Modules#
Typedefs#
Socket Length is internal type.
Public type for socket length.
Internal type for sockaddr address family.
Public type for sockaddr address family.
Functions#
Create an endpoint for communication.
Bind a name to a socket.
Listen for connections on a socket.
Accept a connection on a socket.
Initiate a connection on a socket.
Receive a message from a socket.
Receive a message from a socket.
Send a message on a socket.
Send a message on a socket.
Set options on a socket.
Get options on a socket.
Get the name of the connected peer socket.
Get the current address assigned to a socket.
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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
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,
errnois updated.
The
typesupports 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| socklen_t | [in] | addr_len | The |
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:
Post-conditions:
On success the socket is associated with the supplied local address/port.
On failure the socket remains unbound;
errnois set.
Returns
Returns 0 if successful. Otherwise, returns -1 and sets the global variable
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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_idmust 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;
errnois set.
Returns
Returns 0 if successful. Otherwise, returns -1 and sets the global variable
errnoto 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
backlogin 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| socklen_t * | [inout] | addr_len | Pointer to a |
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.
Pre-conditions:
socket_idmust be a SOCK_STREAM socket created using socket(), bound using bind(), and placed in the listening state using listen().
Post-conditions:
On success a new, connected socket descriptor is returned for the peer connection;
addr/addr_lenare 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
errnoto 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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; |
| 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 |
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.
Pre-conditions:
socket_idmust be a descriptor created using socket().For TCP (SOCK_STREAM) any TLS / socket options (e.g. TCP_ULP, SL_SO_TLS_SNI) must be set using setsockopt() before calling connect().
The network profile must be up and the destination must be reachable.
Post-conditions:
Returns
Returns 0 if successful. Otherwise, returns -1 and sets the global variable
errnoto 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
errnoon failure.
Connecting to an invalid address, such as a null address, will result in an
EFAULTerror.
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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| 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:
Post-conditions:
On success
bufcontains 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
errnoset.
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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| 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 |
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:
Post-conditions:
On success
bufcontains the datagram/segment bytes and, whenfrom_addris 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
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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_idmust 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
errnois set.
Returns
Returns the number of bytes sent on success. Returns -1 on error and sets the global variable
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| socklen_t | [in] | to_addr_len | Size of the address structure pointed to by |
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:
Post-conditions:
On success the data is passed to the stack for transmission.
On failure no bytes are transmitted and
errnois 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
errnoon failure.
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.
| Type | Direction | Argument Name | Description | |||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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
| |||||||||||||||||||||||||||||||||
| socklen_t | [in] | option_length | The length of the option data, in bytes, pointed to by |
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().
Pre-conditions:
socket_idmust be a valid descriptor returned by socket().TLS-related options (TCP_ULP, SL_SO_CERT_INDEX, SL_SO_TLS_SNI, SL_SO_TLS_ALPN, SL_SO_VERIFY_DOMAIN_NAME) must be set before connect().
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
errnois set.
Returns
Returns 0 on successful completion. Returns -1 on error and sets the global variable
errnoto 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, andSL_SO_VERIFY_DOMAIN_NAMEare Silicon Labs specific options. This function is used before the socket is connected.
See Also
Example#
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); }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); }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); }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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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 |
| 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 |
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_idmust be a valid descriptor returned by socket().
Post-conditions:
On success
option_valueis populated andoption_lengthis updated with the number of bytes written.
Returns
Returns 0 on successful completion. Returns -1 on error and sets the global variable
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| int | [in] | socket_id | The socket ID or file descriptor for the specified socket. |
| struct sockaddr * | [out] | name | Pointer to a |
| 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 |
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.
Post-conditions:
On success
nameis populated with the peer's address andname_lenis updated with the actual size.
Returns
Returns 0 on success. Returns -1 on error and sets the global variable
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| int | [in] | socket_id | The socket ID or file descriptor for the specified socket. |
| struct sockaddr * | [out] | name | Pointer to a |
| 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 |
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:
Post-conditions:
On success
nameis populated with the local address/port andname_lenis updated with the actual size.
Returns
Returns 0 on success. Returns -1 on error and sets the global variable
errnoto 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
errnoon 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.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| 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.
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
errnoto 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_idwhen 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).
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;