Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
features/nanostack/FEATURE_NANOSTACK/sal-stack-nanostack/docs/11_API_sockets.md@1:2b6e8130a0ac, 2018-02-22 (annotated)
- Committer:
- calmantara186
- Date:
- Thu Feb 22 14:05:19 2018 +0000
- Revision:
- 1:2b6e8130a0ac
- Parent:
- 0:f269e3021894
mbed os
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| elessair | 0:f269e3021894 | 1 | Socket API |
| elessair | 0:f269e3021894 | 2 | ============================== |
| elessair | 0:f269e3021894 | 3 | This chapter describes the socket use and the available APIs. |
| elessair | 0:f269e3021894 | 4 | |
| elessair | 0:f269e3021894 | 5 | ## API Headers |
| elessair | 0:f269e3021894 | 6 | |
| elessair | 0:f269e3021894 | 7 | Socket API can be fully harnessed by including the following header files: |
| elessair | 0:f269e3021894 | 8 | |
| elessair | 0:f269e3021894 | 9 | ``` |
| elessair | 0:f269e3021894 | 10 | #include net_interface.h |
| elessair | 0:f269e3021894 | 11 | #include socket_api.h |
| elessair | 0:f269e3021894 | 12 | ``` |
| elessair | 0:f269e3021894 | 13 | |
| elessair | 0:f269e3021894 | 14 | ## Socket types available |
| elessair | 0:f269e3021894 | 15 | |
| elessair | 0:f269e3021894 | 16 | 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_. |
| elessair | 0:f269e3021894 | 17 | |
| elessair | 0:f269e3021894 | 18 | **Table 3-18 Socket types** |
| elessair | 0:f269e3021894 | 19 | |
| elessair | 0:f269e3021894 | 20 | Socket name|Socket description |
| elessair | 0:f269e3021894 | 21 | -----------|------------------ |
| elessair | 0:f269e3021894 | 22 | `SOCKET_UDP`|UDP socket type. |
| elessair | 0:f269e3021894 | 23 | `SOCKET_TCP`|TCP socket type. |
| elessair | 0:f269e3021894 | 24 | `SOCKET_ICMP`|ICMP raw socket type; see section _ICMP socket instruction_. |
| elessair | 0:f269e3021894 | 25 | `SOCKET_RAW`|raw IPv6 socket type. |
| elessair | 0:f269e3021894 | 26 | |
| elessair | 0:f269e3021894 | 27 | ### ICMP socket instruction |
| elessair | 0:f269e3021894 | 28 | |
| elessair | 0:f269e3021894 | 29 | 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. |
| elessair | 0:f269e3021894 | 30 | |
| elessair | 0:f269e3021894 | 31 | **Table 3-19 General ICMP packet structure** |
| elessair | 0:f269e3021894 | 32 | |
| elessair | 0:f269e3021894 | 33 | Type|Code|Checksum|Payload|Notes |
| elessair | 0:f269e3021894 | 34 | ----|----|--------|-------|----- |
| elessair | 0:f269e3021894 | 35 | 1|1|2|n (min. 4)|Length in bytes |
| elessair | 0:f269e3021894 | 36 | `0xXX`|`0xXX`|`0x00 0x00`|n bytes|Transmit |
| elessair | 0:f269e3021894 | 37 | `0xXX`|`0xXX`|`0xXX 0xXX`|n bytes|Receive |
| elessair | 0:f269e3021894 | 38 | |
| elessair | 0:f269e3021894 | 39 | |
| elessair | 0:f269e3021894 | 40 | ICMP echo request with four bytes of payload (ping6), as shown in _Table 3-20_. |
| elessair | 0:f269e3021894 | 41 | |
| elessair | 0:f269e3021894 | 42 | **Table 3-20 ICMP echo request** |
| elessair | 0:f269e3021894 | 43 | |
| elessair | 0:f269e3021894 | 44 | Type|Code|Checksum|Payload |
| elessair | 0:f269e3021894 | 45 | ----|----|--------|------- |
| elessair | 0:f269e3021894 | 46 | `0x80`|`0x00`|`0x00 0x00`|`0x00 0x01 0x02 0x03` |
| elessair | 0:f269e3021894 | 47 | |
| elessair | 0:f269e3021894 | 48 | ICMP echo response for the message, as shown in _Table 6-4_. |
| elessair | 0:f269e3021894 | 49 | |
| elessair | 0:f269e3021894 | 50 | **Table 3-21 ICMP echo response** |
| elessair | 0:f269e3021894 | 51 | |
| elessair | 0:f269e3021894 | 52 | Type|Code|Checksum|Payload |
| elessair | 0:f269e3021894 | 53 | ----|----|--------|------- |
| elessair | 0:f269e3021894 | 54 | `0x81`|`0x00`|`0xXX 0xXX`|`0x00 0x01 0x02 0x03` |
| elessair | 0:f269e3021894 | 55 | |
| elessair | 0:f269e3021894 | 56 | ## Receive callback structure |
| elessair | 0:f269e3021894 | 57 | |
| elessair | 0:f269e3021894 | 58 | 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. |
| elessair | 0:f269e3021894 | 59 | |
| elessair | 0:f269e3021894 | 60 | The socket call back structure, `socket_callback_t` is defined as below: |
| elessair | 0:f269e3021894 | 61 | |
| elessair | 0:f269e3021894 | 62 | ``` |
| elessair | 0:f269e3021894 | 63 | typedef struct socket_callback_t { |
| elessair | 0:f269e3021894 | 64 | uint8_t event_type; |
| elessair | 0:f269e3021894 | 65 | int8_t socket_id; |
| elessair | 0:f269e3021894 | 66 | int8_t interface_id; |
| elessair | 0:f269e3021894 | 67 | uint16_t d_len; |
| elessair | 0:f269e3021894 | 68 | uint8_t LINK_LQI; |
| elessair | 0:f269e3021894 | 69 | } socket_callback_t; |
| elessair | 0:f269e3021894 | 70 | ``` |
| elessair | 0:f269e3021894 | 71 | |
| elessair | 0:f269e3021894 | 72 | Member|Description |
| elessair | 0:f269e3021894 | 73 | ------|----------- |
| elessair | 0:f269e3021894 | 74 | `event_type`|Socket event type as provided in Table 3-22. |
| elessair | 0:f269e3021894 | 75 | `socket_id`|The ID of the socket that caused the event. |
| elessair | 0:f269e3021894 | 76 | `interface_id`|The network interface ID. Same as received from `arm_nwk_interface_init`. |
| elessair | 0:f269e3021894 | 77 | `d_len`|The length of data available or sent. |
| elessair | 0:f269e3021894 | 78 | `LINK_LQI`|The Link Quality Indicator value if the interface can provide any. |
| elessair | 0:f269e3021894 | 79 | |
| elessair | 0:f269e3021894 | 80 | **Table 3-22 Supported socket event types** |
| elessair | 0:f269e3021894 | 81 | |
| elessair | 0:f269e3021894 | 82 | Event type|Description |
| elessair | 0:f269e3021894 | 83 | ----------|----------- |
| elessair | 0:f269e3021894 | 84 | `SOCKET_DATA`|Data received. |
| elessair | 0:f269e3021894 | 85 | `SOCKET_BIND_DONE`|TCP connection ready. |
| elessair | 0:f269e3021894 | 86 | `SOCKET_BIND_FAIL`|TCP connection failed. |
| elessair | 0:f269e3021894 | 87 | `SOCKET_BIND_AUTH_FAIL`|TCP connection authentication failed. |
| elessair | 0:f269e3021894 | 88 | `SOCKET_SERVER_CONNECT_TO_CLIENT`|TCP connection state change from listen to establishment. |
| elessair | 0:f269e3021894 | 89 | `SOCKET_TX_FAIL`|Socket data send failed. |
| elessair | 0:f269e3021894 | 90 | `SOCKET_CONNECT_CLOSED`|TCP connection closed. |
| elessair | 0:f269e3021894 | 91 | `SOCKET_CONNECT_FAIL_CLOSED`|TCP connection closed - no ACK received. |
| elessair | 0:f269e3021894 | 92 | `SOCKET_NO_ROUTER`|No route available to destination. |
| elessair | 0:f269e3021894 | 93 | `SOCKET_TX_DONE`|Last socket TX process done, in TCP case whole TCP process is ready. |
| elessair | 0:f269e3021894 | 94 | `SOCKET_NO_RAM `|If no RAM is present. |
| elessair | 0:f269e3021894 | 95 | |
| elessair | 0:f269e3021894 | 96 | An example parsing socket event: |
| elessair | 0:f269e3021894 | 97 | |
| elessair | 0:f269e3021894 | 98 | ``` |
| elessair | 0:f269e3021894 | 99 | #define APP_SOCK_RX_SIZE 250 |
| elessair | 0:f269e3021894 | 100 | |
| elessair | 0:f269e3021894 | 101 | /*Application socket payload buffer used for RX and TX*/ |
| elessair | 0:f269e3021894 | 102 | static uint8_t rx_buffer[APP_SOCK_RX_SIZE]; |
| elessair | 0:f269e3021894 | 103 | |
| elessair | 0:f269e3021894 | 104 | void main_receive |
| elessair | 0:f269e3021894 | 105 | ( |
| elessair | 0:f269e3021894 | 106 | void *cb |
| elessair | 0:f269e3021894 | 107 | ) |
| elessair | 0:f269e3021894 | 108 | { |
| elessair | 0:f269e3021894 | 109 | socket_callback_t *cb_res = cb; |
| elessair | 0:f269e3021894 | 110 | int16_t length; |
| elessair | 0:f269e3021894 | 111 | |
| elessair | 0:f269e3021894 | 112 | if( cb_res->event_type == SOCKET_DATA ) |
| elessair | 0:f269e3021894 | 113 | { |
| elessair | 0:f269e3021894 | 114 | sn_nsdl_addr_s sn_addr_s; |
| elessair | 0:f269e3021894 | 115 | |
| elessair | 0:f269e3021894 | 116 | //Read data from the RX buffer |
| elessair | 0:f269e3021894 | 117 | length = socket_read( cb_res->socket_id, |
| elessair | 0:f269e3021894 | 118 | &app_src, |
| elessair | 0:f269e3021894 | 119 | rx_buffer, |
| elessair | 0:f269e3021894 | 120 | APP_SOCK_RX_SIZE ); |
| elessair | 0:f269e3021894 | 121 | |
| elessair | 0:f269e3021894 | 122 | if( length ) |
| elessair | 0:f269e3021894 | 123 | { |
| elessair | 0:f269e3021894 | 124 | if( cb_res->socket_id == app_udp_socket ) |
| elessair | 0:f269e3021894 | 125 | { |
| elessair | 0:f269e3021894 | 126 | // Handles data received in UDP socket |
| elessair | 0:f269e3021894 | 127 | |
| elessair | 0:f269e3021894 | 128 | sn_nsdl_process_coap(rx_buffer, length, &sn_addr_s); |
| elessair | 0:f269e3021894 | 129 | } |
| elessair | 0:f269e3021894 | 130 | |
| elessair | 0:f269e3021894 | 131 | } |
| elessair | 0:f269e3021894 | 132 | } |
| elessair | 0:f269e3021894 | 133 | } |
| elessair | 0:f269e3021894 | 134 | ``` |
| elessair | 0:f269e3021894 | 135 | |
| elessair | 0:f269e3021894 | 136 | ## Using TCP sockets |
| elessair | 0:f269e3021894 | 137 | |
| elessair | 0:f269e3021894 | 138 | 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. |
| elessair | 0:f269e3021894 | 139 | |
| elessair | 0:f269e3021894 | 140 | 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. |
| elessair | 0:f269e3021894 | 141 | |
| elessair | 0:f269e3021894 | 142 | 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. |
| elessair | 0:f269e3021894 | 143 | |
| elessair | 0:f269e3021894 | 144 | After receiving a successful state event, data can be sent using the `socket_send( )` call. |
| elessair | 0:f269e3021894 | 145 | |
| elessair | 0:f269e3021894 | 146 | The connection can be closed by calling function `socket_close( )`. The 6LoWPAN stack closes 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_free( )`. |
| elessair | 0:f269e3021894 | 147 | |
| elessair | 0:f269e3021894 | 148 | ## Using UDP and ICMP sockets |
| elessair | 0:f269e3021894 | 149 | |
| elessair | 0:f269e3021894 | 150 | 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. |
| elessair | 0:f269e3021894 | 151 | |
| elessair | 0:f269e3021894 | 152 | ## Detailed Socket API usage |
| elessair | 0:f269e3021894 | 153 | |
| elessair | 0:f269e3021894 | 154 | This section describes the socket layer functions in more detail. Each function is presented with example parameters and possible return values. |
| elessair | 0:f269e3021894 | 155 | |
| elessair | 0:f269e3021894 | 156 | ### How to open a socket |
| elessair | 0:f269e3021894 | 157 | |
| elessair | 0:f269e3021894 | 158 | To initialize a socket ready for communication: |
| elessair | 0:f269e3021894 | 159 | |
| elessair | 0:f269e3021894 | 160 | ``` |
| elessair | 0:f269e3021894 | 161 | int8_t socket_open |
| elessair | 0:f269e3021894 | 162 | ( |
| elessair | 0:f269e3021894 | 163 | uint8_t protocol, |
| elessair | 0:f269e3021894 | 164 | uint16_t identifier, |
| elessair | 0:f269e3021894 | 165 | void (*passed_fptr)(void *) |
| elessair | 0:f269e3021894 | 166 | ) |
| elessair | 0:f269e3021894 | 167 | ``` |
| elessair | 0:f269e3021894 | 168 | |
| elessair | 0:f269e3021894 | 169 | Parameter|Description |
| elessair | 0:f269e3021894 | 170 | ---------|----------- |
| elessair | 0:f269e3021894 | 171 | `protocol`|The protocol to be used over this socket and valid values for the argument are:<br>`SOCKET_UDP` UDP: standard communication.<br>`SOCKET_TCP` TCP: standard communication.<br>`SOCKET_ICMP` ICMPv6: used for ping functionality.<br>`SOCKET_RAW` raw IPv6: used for other specialised protocols. |
| elessair | 0:f269e3021894 | 172 | `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()`. |
| elessair | 0:f269e3021894 | 173 | `passed_fptr`|A function pointer to the desired socket receive callback function. |
| elessair | 0:f269e3021894 | 174 | |
| elessair | 0:f269e3021894 | 175 | <dl> |
| elessair | 0:f269e3021894 | 176 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 177 | <dd>0 Socket ID, used as a reference to the specific socket in subsequent calls.</dd> |
| elessair | 0:f269e3021894 | 178 | <dd>-1 No free sockets or invalid protocol.</dd> |
| elessair | 0:f269e3021894 | 179 | </dl> |
| elessair | 0:f269e3021894 | 180 | |
| elessair | 0:f269e3021894 | 181 | ### How to release a socket |
| elessair | 0:f269e3021894 | 182 | |
| elessair | 0:f269e3021894 | 183 | To release a socket: |
| elessair | 0:f269e3021894 | 184 | |
| elessair | 0:f269e3021894 | 185 | `int8_t socket_free( int8_t socket )` |
| elessair | 0:f269e3021894 | 186 | |
| elessair | 0:f269e3021894 | 187 | Parameter|Description |
| elessair | 0:f269e3021894 | 188 | ---------|----------- |
| elessair | 0:f269e3021894 | 189 | `socket`|The socket ID of the socket to be released. |
| elessair | 0:f269e3021894 | 190 | |
| elessair | 0:f269e3021894 | 191 | <dl> |
| elessair | 0:f269e3021894 | 192 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 193 | <dd>0 Socket release successful.</dd> |
| elessair | 0:f269e3021894 | 194 | <dd>-1 Socket release failed. Socket ID invalid or already released.</dd> |
| elessair | 0:f269e3021894 | 195 | </dl> |
| elessair | 0:f269e3021894 | 196 | |
| elessair | 0:f269e3021894 | 197 | ### How to bind a socket |
| elessair | 0:f269e3021894 | 198 | |
| elessair | 0:f269e3021894 | 199 | To bind socket to a port and address: |
| elessair | 0:f269e3021894 | 200 | |
| elessair | 0:f269e3021894 | 201 | ``` |
| elessair | 0:f269e3021894 | 202 | int8_t socket_bind |
| elessair | 0:f269e3021894 | 203 | ( |
| elessair | 0:f269e3021894 | 204 | int8_t socket, |
| elessair | 0:f269e3021894 | 205 | const ns_address_t *address |
| elessair | 0:f269e3021894 | 206 | ) |
| elessair | 0:f269e3021894 | 207 | ``` |
| elessair | 0:f269e3021894 | 208 | |
| elessair | 0:f269e3021894 | 209 | Parameter|Description |
| elessair | 0:f269e3021894 | 210 | ---------|----------- |
| elessair | 0:f269e3021894 | 211 | `socket`|The socket ID returned by `socket_open`. |
| elessair | 0:f269e3021894 | 212 | `address`|Structure that contains port and/or address to be bound to the socket. |
| elessair | 0:f269e3021894 | 213 | |
| elessair | 0:f269e3021894 | 214 | <dl> |
| elessair | 0:f269e3021894 | 215 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 216 | <dd>0 on success.</dd> |
| elessair | 0:f269e3021894 | 217 | <dd>-1 if given address is NULL.</dd> |
| elessair | 0:f269e3021894 | 218 | <dd>-2 if port is already bound to another socket.</dd> |
| elessair | 0:f269e3021894 | 219 | <dd>-4 if socket is already bound.</dd> |
| elessair | 0:f269e3021894 | 220 | <dd>-5 bind is not supported on this type of socket.</dd> |
| elessair | 0:f269e3021894 | 221 | </dl> |
| elessair | 0:f269e3021894 | 222 | |
| elessair | 0:f269e3021894 | 223 | The port and the address can be bound only once. The port can also be bound to the socket with the function `socket_open( )`. |
| elessair | 0:f269e3021894 | 224 | |
| elessair | 0:f269e3021894 | 225 | To bind a local address to a socket based on a destination address and address selection preferences: |
| elessair | 0:f269e3021894 | 226 | |
| elessair | 0:f269e3021894 | 227 | ``` |
| elessair | 0:f269e3021894 | 228 | int8_t socket_bind2addrsel |
| elessair | 0:f269e3021894 | 229 | ( |
| elessair | 0:f269e3021894 | 230 | int8_t socket, |
| elessair | 0:f269e3021894 | 231 | const ns_address_t *dst_address |
| elessair | 0:f269e3021894 | 232 | ) |
| elessair | 0:f269e3021894 | 233 | ``` |
| elessair | 0:f269e3021894 | 234 | |
| elessair | 0:f269e3021894 | 235 | Parameter|Description |
| elessair | 0:f269e3021894 | 236 | ---------|----------- |
| elessair | 0:f269e3021894 | 237 | `socket`|The socket ID returned by `socket_open`. |
| elessair | 0:f269e3021894 | 238 | `dst_address`|Destination address to which the socket wants to communicate. |
| elessair | 0:f269e3021894 | 239 | |
| elessair | 0:f269e3021894 | 240 | <dl> |
| elessair | 0:f269e3021894 | 241 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 242 | <dd>0 on success.</dd> |
| elessair | 0:f269e3021894 | 243 | <dd>-1 if given address is NULL or socket ID is invalid.</dd> |
| elessair | 0:f269e3021894 | 244 | <dd>-2 if memory allocation failed.</dd> |
| elessair | 0:f269e3021894 | 245 | <dd>-3 if socket is already bound to address.</dd> |
| elessair | 0:f269e3021894 | 246 | <dd>-4 if interface cannot be found.</dd> |
| elessair | 0:f269e3021894 | 247 | <dd>-5 if source address selection fails.</dd> |
| elessair | 0:f269e3021894 | 248 | <dd>-6 bind2addrsel is not supported on this type of socket.</dd> |
| elessair | 0:f269e3021894 | 249 | </dl> |
| elessair | 0:f269e3021894 | 250 | |
| elessair | 0:f269e3021894 | 251 | ### How to read data from a socket |
| elessair | 0:f269e3021894 | 252 | |
| elessair | 0:f269e3021894 | 253 | To read received data from a socket: |
| elessair | 0:f269e3021894 | 254 | |
| elessair | 0:f269e3021894 | 255 | ``` |
| elessair | 0:f269e3021894 | 256 | int16_t socket_read |
| elessair | 0:f269e3021894 | 257 | ( |
| elessair | 0:f269e3021894 | 258 | int8_t socket, |
| elessair | 0:f269e3021894 | 259 | ns_address_t *address, |
| elessair | 0:f269e3021894 | 260 | uint8_t *buffer, |
| elessair | 0:f269e3021894 | 261 | uint16_t length |
| elessair | 0:f269e3021894 | 262 | ) |
| elessair | 0:f269e3021894 | 263 | ``` |
| elessair | 0:f269e3021894 | 264 | |
| elessair | 0:f269e3021894 | 265 | Parameter|Description |
| elessair | 0:f269e3021894 | 266 | ---------|----------- |
| elessair | 0:f269e3021894 | 267 | `socket`|The socket ID of the socket to be read. |
| elessair | 0:f269e3021894 | 268 | `address`|A pointer to an address structure containing the source address of the packet (populated by the stack). Can be NULL. |
| elessair | 0:f269e3021894 | 269 | `buffer`|A pointer to a byte array containing the payload of the packet. |
| elessair | 0:f269e3021894 | 270 | `length`|The length of the payload data to be stored in the buffer. |
| elessair | 0:f269e3021894 | 271 | |
| elessair | 0:f269e3021894 | 272 | <dl> |
| elessair | 0:f269e3021894 | 273 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 274 | <dd>> 0 The length of the data copied to the buffer.</dd> |
| elessair | 0:f269e3021894 | 275 | <dd>0 No data is available to read.</dd> |
| elessair | 0:f269e3021894 | 276 | <dd>-1 Invalid input parameters.</dd> |
| elessair | 0:f269e3021894 | 277 | </dl> |
| elessair | 0:f269e3021894 | 278 | |
| elessair | 0:f269e3021894 | 279 | The application receives an event type `SOCKET_DATA` to its receive socket callback when the data is available. The application |
| elessair | 0:f269e3021894 | 280 | must read the data from the callback because the stack frees the data after it has called the receive socket callback. |
| elessair | 0:f269e3021894 | 281 | All data must be read by one call. If data is too long to fit in the supplied buffer the excess bytes are discarded. |
| elessair | 0:f269e3021894 | 282 | |
| elessair | 0:f269e3021894 | 283 | ### How to send data to a socket |
| elessair | 0:f269e3021894 | 284 | |
| elessair | 0:f269e3021894 | 285 | 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_. |
| elessair | 0:f269e3021894 | 286 | |
| elessair | 0:f269e3021894 | 287 | After successfully calling the function, the application must await the TX process to complete. |
| elessair | 0:f269e3021894 | 288 | |
| elessair | 0:f269e3021894 | 289 | **Table 3-23 The two transmit function calls** |
| elessair | 0:f269e3021894 | 290 | |
| elessair | 0:f269e3021894 | 291 | Function|Socket types |
| elessair | 0:f269e3021894 | 292 | --------|------------ |
| elessair | 0:f269e3021894 | 293 | `socket_sendto( )`|UDP, ICMP and RAW |
| elessair | 0:f269e3021894 | 294 | `socket_send( )`|TCP, or UDP if connected |
| elessair | 0:f269e3021894 | 295 | |
| elessair | 0:f269e3021894 | 296 | |
| elessair | 0:f269e3021894 | 297 | _Table 3-24_ describes the possible response events when the outcome of the function call is successful. |
| elessair | 0:f269e3021894 | 298 | |
| elessair | 0:f269e3021894 | 299 | **Table 3-24 The possible response events following a successful function call** |
| elessair | 0:f269e3021894 | 300 | |
| elessair | 0:f269e3021894 | 301 | Response Event|Socket Type|Description |
| elessair | 0:f269e3021894 | 302 | --------------|-----------|----------- |
| elessair | 0:f269e3021894 | 303 | `SOCKET_TX_DONE`|TCP/UDP|UDP link layer TX ready/TCP TX process ready by TCP _Acknowledgement_ (ACK). |
| elessair | 0:f269e3021894 | 304 | `SOCKET_TX_FAIL`|UDP|UDP link layer TX fails. |
| elessair | 0:f269e3021894 | 305 | `SOCKET_CONNECT_FAIL_CLOSED`|TCP|TX process fails and connection closed. |
| elessair | 0:f269e3021894 | 306 | |
| elessair | 0:f269e3021894 | 307 | To transmit data on an unconnected socket: |
| elessair | 0:f269e3021894 | 308 | |
| elessair | 0:f269e3021894 | 309 | ``` |
| elessair | 0:f269e3021894 | 310 | int8_t socket_sendto |
| elessair | 0:f269e3021894 | 311 | ( |
| elessair | 0:f269e3021894 | 312 | int8_t socket, |
| elessair | 0:f269e3021894 | 313 | ns_address_t address, |
| elessair | 0:f269e3021894 | 314 | uint8_t *buffer, |
| elessair | 0:f269e3021894 | 315 | uint16_t length |
| elessair | 0:f269e3021894 | 316 | ) |
| elessair | 0:f269e3021894 | 317 | ``` |
| elessair | 0:f269e3021894 | 318 | |
| elessair | 0:f269e3021894 | 319 | Parameter|Description |
| elessair | 0:f269e3021894 | 320 | ---------|----------- |
| elessair | 0:f269e3021894 | 321 | `socket`|The socket ID to use for transmission. |
| elessair | 0:f269e3021894 | 322 | `address`|A pointer to an address structure containing the destination address of the packet (populated by the application). |
| elessair | 0:f269e3021894 | 323 | `buffer`|A pointer to a byte array containing the payload of the packet. |
| elessair | 0:f269e3021894 | 324 | `length`|The length of the payload data in the buffer. |
| elessair | 0:f269e3021894 | 325 | |
| elessair | 0:f269e3021894 | 326 | |
| elessair | 0:f269e3021894 | 327 | <dl> |
| elessair | 0:f269e3021894 | 328 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 329 | <dd>>0 Data packet accepted by the stack.</dd> |
| elessair | 0:f269e3021894 | 330 | <dd>-1 Fail.</dd> |
| elessair | 0:f269e3021894 | 331 | </dl> |
| elessair | 0:f269e3021894 | 332 | |
| elessair | 0:f269e3021894 | 333 | To send data via a connected socket: |
| elessair | 0:f269e3021894 | 334 | |
| elessair | 0:f269e3021894 | 335 | <span class="notes">**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.</span> |
| elessair | 0:f269e3021894 | 336 | |
| elessair | 0:f269e3021894 | 337 | ``` |
| elessair | 0:f269e3021894 | 338 | int8_t socket_send |
| elessair | 0:f269e3021894 | 339 | ( |
| elessair | 0:f269e3021894 | 340 | int8_t socket, |
| elessair | 0:f269e3021894 | 341 | uint8_t *buffer, |
| elessair | 0:f269e3021894 | 342 | uint16_t length |
| elessair | 0:f269e3021894 | 343 | ) |
| elessair | 0:f269e3021894 | 344 | ``` |
| elessair | 0:f269e3021894 | 345 | |
| elessair | 0:f269e3021894 | 346 | Parameter|Description |
| elessair | 0:f269e3021894 | 347 | ---------|----------- |
| elessair | 0:f269e3021894 | 348 | `socket`|The socket ID to use for transmission. |
| elessair | 0:f269e3021894 | 349 | `buffer`|A pointer to a byte array containing the payload of the packet. |
| elessair | 0:f269e3021894 | 350 | `length`|The length of the payload data in the buffer. |
| elessair | 0:f269e3021894 | 351 | |
| elessair | 0:f269e3021894 | 352 | <dl> |
| elessair | 0:f269e3021894 | 353 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 354 | <dd>>0 Data packet accepted by the stack.</dd> |
| elessair | 0:f269e3021894 | 355 | <dd>-1 Fail.</dd> |
| elessair | 0:f269e3021894 | 356 | </dl> |
| elessair | 0:f269e3021894 | 357 | |
| elessair | 0:f269e3021894 | 358 | ### TCP socket configuration |
| elessair | 0:f269e3021894 | 359 | |
| elessair | 0:f269e3021894 | 360 | The TCP socket configuration API offers three function calls, as shown in _Table 3-25_ and are further described. |
| elessair | 0:f269e3021894 | 361 | |
| elessair | 0:f269e3021894 | 362 | **Table 3-25 The TCP socket configuration functions** |
| elessair | 0:f269e3021894 | 363 | |
| elessair | 0:f269e3021894 | 364 | Function|Description |
| elessair | 0:f269e3021894 | 365 | --------|----------- |
| elessair | 0:f269e3021894 | 366 | `socket_listen()`|Set socket to the listen state. |
| elessair | 0:f269e3021894 | 367 | `socket_connect()`|Connect socket to a host. |
| elessair | 0:f269e3021894 | 368 | `socket_close()`|Close socket connection. |
| elessair | 0:f269e3021894 | 369 | |
| elessair | 0:f269e3021894 | 370 | To set a TCP socket into the listen state: |
| elessair | 0:f269e3021894 | 371 | |
| elessair | 0:f269e3021894 | 372 | ``` |
| elessair | 0:f269e3021894 | 373 | int8_t socket_listen |
| elessair | 0:f269e3021894 | 374 | ( |
| elessair | 0:f269e3021894 | 375 | int8_t socket |
| elessair | 0:f269e3021894 | 376 | |
| elessair | 0:f269e3021894 | 377 | ``` |
| elessair | 0:f269e3021894 | 378 | |
| elessair | 0:f269e3021894 | 379 | Parameter|Description |
| elessair | 0:f269e3021894 | 380 | ---------|----------- |
| elessair | 0:f269e3021894 | 381 | `socket`|The socket ID that is to be set to the listen state. |
| elessair | 0:f269e3021894 | 382 | |
| elessair | 0:f269e3021894 | 383 | <dl> |
| elessair | 0:f269e3021894 | 384 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 385 | <dd>0 Valid request.</dd> |
| elessair | 0:f269e3021894 | 386 | <dd><b>Note:</b> This does not imply that the state of the socket has been successfully changed.</dd> |
| elessair | 0:f269e3021894 | 387 | <dd>-1 Fail.</dd> |
| elessair | 0:f269e3021894 | 388 | </dl> |
| elessair | 0:f269e3021894 | 389 | |
| elessair | 0:f269e3021894 | 390 | To connect a socket to a remote host: |
| elessair | 0:f269e3021894 | 391 | |
| elessair | 0:f269e3021894 | 392 | ``` |
| elessair | 0:f269e3021894 | 393 | int8_t socket_connect |
| elessair | 0:f269e3021894 | 394 | ( |
| elessair | 0:f269e3021894 | 395 | int8_t socket, |
| elessair | 0:f269e3021894 | 396 | ns_address_t *address, |
| elessair | 0:f269e3021894 | 397 | uint8_t randomly_take_src_numbers |
| elessair | 0:f269e3021894 | 398 | ) |
| elessair | 0:f269e3021894 | 399 | ``` |
| elessair | 0:f269e3021894 | 400 | |
| elessair | 0:f269e3021894 | 401 | Parameter|Description |
| elessair | 0:f269e3021894 | 402 | ---------|----------- |
| elessair | 0:f269e3021894 | 403 | `socket`|The socket ID, which is used to connect to the remote host. |
| elessair | 0:f269e3021894 | 404 | `address`|A pointer to an <code>address_t</code> structure that contains the address of the remote host. |
| elessair | 0:f269e3021894 | 405 | `randomly_take_src_numbers`|Value 1 indicates that a randomly selected source port number is used. |
| elessair | 0:f269e3021894 | 406 | |
| elessair | 0:f269e3021894 | 407 | <dl> |
| elessair | 0:f269e3021894 | 408 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 409 | <dd>0 Valid request.</dd> |
| elessair | 0:f269e3021894 | 410 | <dd><b>Note:</b>This does not imply that the state of the socket has been successfully changed.</dd> |
| elessair | 0:f269e3021894 | 411 | <dd>-1 Fail.</dd> |
| elessair | 0:f269e3021894 | 412 | </dl> |
| elessair | 0:f269e3021894 | 413 | |
| elessair | 0:f269e3021894 | 414 | There are two possible responses from the stack for `socket_connect( )`: |
| elessair | 0:f269e3021894 | 415 | |
| elessair | 0:f269e3021894 | 416 | - `SOCKET_BIND_DONE` |
| elessair | 0:f269e3021894 | 417 | - TCP handshake ready. |
| elessair | 0:f269e3021894 | 418 | |
| elessair | 0:f269e3021894 | 419 | - `SOCKET_CONNECT_FAIL_CLOSED` |
| elessair | 0:f269e3021894 | 420 | - TCP handshake fail. |
| elessair | 0:f269e3021894 | 421 | |
| elessair | 0:f269e3021894 | 422 | To close a TCP connection: |
| elessair | 0:f269e3021894 | 423 | |
| elessair | 0:f269e3021894 | 424 | ``` |
| elessair | 0:f269e3021894 | 425 | int8_t socket_close |
| elessair | 0:f269e3021894 | 426 | |
| elessair | 0:f269e3021894 | 427 | int8_t socket, |
| elessair | 0:f269e3021894 | 428 | ns_address_t *address |
| elessair | 0:f269e3021894 | 429 | ) |
| elessair | 0:f269e3021894 | 430 | ``` |
| elessair | 0:f269e3021894 | 431 | |
| elessair | 0:f269e3021894 | 432 | Parameter|Description |
| elessair | 0:f269e3021894 | 433 | ---------|----------- |
| elessair | 0:f269e3021894 | 434 | `socket`|The socket ID of the socket to be disconnected from the remote host. |
| elessair | 0:f269e3021894 | 435 | `address`|The destination client address; a client should use a null pointer for this parameter. |
| elessair | 0:f269e3021894 | 436 | |
| elessair | 0:f269e3021894 | 437 | <dl> |
| elessair | 0:f269e3021894 | 438 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 439 | <dd>0 Valid request.</dd> |
| elessair | 0:f269e3021894 | 440 | <dd><b>Note:</b>This does not imply that the state of the socket has been successfully changed.</dd> |
| elessair | 0:f269e3021894 | 441 | <dd>-1 Fail.</dd> |
| elessair | 0:f269e3021894 | 442 | </dl> |
| elessair | 0:f269e3021894 | 443 | |
| elessair | 0:f269e3021894 | 444 | ### Modifying socket options |
| elessair | 0:f269e3021894 | 445 | |
| elessair | 0:f269e3021894 | 446 | To specify miscellaneous options for a socket: |
| elessair | 0:f269e3021894 | 447 | |
| elessair | 0:f269e3021894 | 448 | ``` |
| elessair | 0:f269e3021894 | 449 | int8_t socket_setsockopt |
| elessair | 0:f269e3021894 | 450 | ( |
| elessair | 0:f269e3021894 | 451 | int8_t socket, |
| elessair | 0:f269e3021894 | 452 | uint8_t level, |
| elessair | 0:f269e3021894 | 453 | uint8_t opt_name, |
| elessair | 0:f269e3021894 | 454 | const void *opt_value, |
| elessair | 0:f269e3021894 | 455 | uint16_t opt_len |
| elessair | 0:f269e3021894 | 456 | ) |
| elessair | 0:f269e3021894 | 457 | ``` |
| elessair | 0:f269e3021894 | 458 | |
| elessair | 0:f269e3021894 | 459 | Parameter|Description |
| elessair | 0:f269e3021894 | 460 | ---------|----------- |
| elessair | 0:f269e3021894 | 461 | `socket`|The socket ID. |
| elessair | 0:f269e3021894 | 462 | `level`|The option level. |
| elessair | 0:f269e3021894 | 463 | `opt_name`|The option name. |
| elessair | 0:f269e3021894 | 464 | `opt_value`|A pointer to the value of the specified option. |
| elessair | 0:f269e3021894 | 465 | `opt_len`|The size of the data pointed to by a value. |
| elessair | 0:f269e3021894 | 466 | |
| elessair | 0:f269e3021894 | 467 | <dl> |
| elessair | 0:f269e3021894 | 468 | <dt>Return value</dt> |
| elessair | 0:f269e3021894 | 469 | <dd>0 Done.</dd> |
| elessair | 0:f269e3021894 | 470 | <dd>-1 Invalid socket ID.</dd> |
| elessair | 0:f269e3021894 | 471 | <dd>-2 Invalid or unsupported option.</dd> |
| elessair | 0:f269e3021894 | 472 | <dd>-3 Invalid option value.</dd> |
| elessair | 0:f269e3021894 | 473 | </dl> |
| elessair | 0:f269e3021894 | 474 | |
| elessair | 0:f269e3021894 | 475 | Each socket has unique control of the following items: |
| elessair | 0:f269e3021894 | 476 | |
| elessair | 0:f269e3021894 | 477 | - IPv6 traffic class, option name: `SOCKET_IPV6_TCLASS` |
| elessair | 0:f269e3021894 | 478 | - Socket source address mode, option name: `SOCKET_IPV6_ADDRESS_SELECT` |
| elessair | 0:f269e3021894 | 479 | |
| elessair | 0:f269e3021894 | 480 | A socket uses a configured setup until the user changes it with a new function call. |
| elessair | 0:f269e3021894 | 481 | |
| elessair | 0:f269e3021894 | 482 | <span class="notes">**Note**: `SOCKET_IPV6_ADDRESS_SELECT` is only supported when the interface bootstrap address mode is `NET_6LOWPAN_MULTI_GP_ADDRESS`.</span> |
| elessair | 0:f269e3021894 | 483 | |
| elessair | 0:f269e3021894 | 484 | #### How to set address mode for a socket |
| elessair | 0:f269e3021894 | 485 | |
| elessair | 0:f269e3021894 | 486 | 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. |
| elessair | 0:f269e3021894 | 487 | |
| elessair | 0:f269e3021894 | 488 | ``` |
| elessair | 0:f269e3021894 | 489 | int8_t set_coap_socket_src_address_mode(int16_t address_mode) |
| elessair | 0:f269e3021894 | 490 | { |
| elessair | 0:f269e3021894 | 491 | |
| elessair | 0:f269e3021894 | 492 | return socket_setsockopt(app_udp_socket,SOCKET_IPPROTO_IPV6, |
| elessair | 0:f269e3021894 | 493 | SOCKET_IPV6_ADDRESS_SELECT, &address_mode),sizeof(address_mode))); |
| elessair | 0:f269e3021894 | 494 | } |
| elessair | 0:f269e3021894 | 495 | ``` |
| elessair | 0:f269e3021894 | 496 | |
| elessair | 0:f269e3021894 | 497 | ### How to set traffic class for a socket |
| elessair | 0:f269e3021894 | 498 | |
| elessair | 0:f269e3021894 | 499 | 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. |
| elessair | 0:f269e3021894 | 500 | |
| elessair | 0:f269e3021894 | 501 | Parameters for Traffic class: |
| elessair | 0:f269e3021894 | 502 | |
| elessair | 0:f269e3021894 | 503 | Parameter|Description |
| elessair | 0:f269e3021894 | 504 | ---------|----------- |
| elessair | 0:f269e3021894 | 505 | `socket`|The socket identified. |
| elessair | 0:f269e3021894 | 506 | `level`|`SOCKET_IPPROTO_IPV6` |
| elessair | 0:f269e3021894 | 507 | `opt_name`|`SOCKET_IPV6_TCLASS` |
| elessair | 0:f269e3021894 | 508 | `opt_value`|A pointer to `int16_t` value. Valid values are from 0 to 255. -1 is for system default. |
| elessair | 0:f269e3021894 | 509 | `opt_len`|The size of `int16_t`, 2 bytes. |
| elessair | 0:f269e3021894 | 510 | |
| elessair | 0:f269e3021894 | 511 | [RFC 4594](https://tools.ietf.org/html/rfc4594) specifies the appropriate traffic class values. The 6LoWPAN stack does not interpret the specified traffic class. It is just passed through. |
| elessair | 0:f269e3021894 | 512 | |
| elessair | 0:f269e3021894 | 513 | ### How to set flow label for a socket |
| elessair | 0:f269e3021894 | 514 | |
| elessair | 0:f269e3021894 | 515 | You can use `socket_setsockopt()` to set the socket flow label. |
| elessair | 0:f269e3021894 | 516 | |
| elessair | 0:f269e3021894 | 517 | Parameters for flow label: |
| elessair | 0:f269e3021894 | 518 | |
| elessair | 0:f269e3021894 | 519 | Parameter|Description |
| elessair | 0:f269e3021894 | 520 | ---------|----------- |
| elessair | 0:f269e3021894 | 521 | `socket`|The socket identified. |
| elessair | 0:f269e3021894 | 522 | `level`|`SOCKET_IPPROTO_IPV6` |
| elessair | 0:f269e3021894 | 523 | `opt_name`|`SOCKET_IPV6_FLOW_LABEL` |
| elessair | 0:f269e3021894 | 524 | `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. |
| elessair | 0:f269e3021894 | 525 | `opt_len`|The size of `int32_t`, 4 bytes. |
| elessair | 0:f269e3021894 | 526 | |
| elessair | 0:f269e3021894 | 527 | The stack auto-generates flow labels on outgoing packets following the guidelines in [RFC 6437](https://tools.ietf.org/html/rfc6437). The stack does not interpret the flow label on received packets, and nor does the socket API report flow label to the application. |
| elessair | 0:f269e3021894 | 528 |