Netconn API
Netconn API is addon on top of existing connection module and allows sending and receiving data with sequential API calls, similar to POSIX socket API.
It can operate in client mode and uses operating system features, such as message queues and semaphore to link non-blocking callback API for connections with sequential API for application thread.
Note
Connection API does not directly allow receiving data with sequential and linear code execution. All is based on connection event system. Netconn adds this functionality as it is implemented on top of regular connection API.
Warning
Netconn API are designed to be called from application threads ONLY. It is not allowed to call any of netconn API functions from within interrupt or callback event functions.
Netconn client
Netconn API client block diagram
Above block diagram shows basic architecture of netconn client application. There is always one application thread (in green) which calls netconn API functions to interact with connection API in synchronous mode.
Every netconn connection uses dedicated structure to handle message queue for data received packet buffers. Each time new packet is received (red block, data received event), reference to it is written to message queue of netconn structure, while application thread reads new entries from the same queue to get packets.
1#include "netconn_client.h"
2#include "lwcell/lwcell.h"
3#include "lwcell/lwcell_network_api.h"
4
5#if LWCELL_CFG_NETCONN
6
7/**
8 * \brief Host and port settings
9 */
10#define NETCONN_HOST "example.com"
11#define NETCONN_PORT 80
12
13/**
14 * \brief Request header to send on successful connection
15 */
16static const char request_header[] = ""
17 "GET / HTTP/1.1\r\n"
18 "Host: " NETCONN_HOST "\r\n"
19 "Connection: close\r\n"
20 "\r\n";
21
22/**
23 * \brief Netconn client thread implementation
24 * \param[in] arg: User argument
25 */
26void
27netconn_client_thread(void const* arg) {
28 lwcellr_t res;
29 lwcell_pbuf_p pbuf;
30 lwcell_netconn_p client;
31 lwcell_sys_sem_t* sem = (void*)arg;
32
33 /* Request attach to network */
34 while (lwcell_network_request_attach() != lwcellOK) {
35 lwcell_delay(1000);
36 }
37
38 /*
39 * First create a new instance of netconn
40 * connection and initialize system message boxes
41 * to accept received packet buffers
42 */
43 if ((client = lwcell_netconn_new(LWCELL_NETCONN_TYPE_TCP)) != NULL) {
44 /*
45 * Connect to external server as client
46 * with custom NETCONN_CONN_HOST and CONN_PORT values
47 *
48 * Function will block thread until we are successfully connected (or not) to server
49 */
50 if ((res = lwcell_netconn_connect(client, NETCONN_HOST, NETCONN_PORT)) == lwcellOK) {
51 printf("Connected to %s\r\n", NETCONN_HOST);
52
53 /* Send data to server */
54 if ((res = lwcell_netconn_write(client, request_header, sizeof(request_header) - 1)) == lwcellOK) {
55 res = lwcell_netconn_flush(client); /* Flush data to output */
56 }
57 if (res == lwcellOK) { /* Were data sent? */
58 printf("Data were successfully sent to server\r\n");
59
60 /*
61 * Since we sent HTTP request,
62 * we are expecting some data from server
63 * or at least forced connection close from remote side
64 */
65 do {
66 /*
67 * Receive single packet of data
68 *
69 * Function will block thread until new packet
70 * is ready to be read from remote side
71 *
72 * After function returns, don't forgot the check value.
73 * Returned status will give you info in case connection
74 * was closed too early from remote side
75 */
76 res = lwcell_netconn_receive(client, &pbuf);
77 if (res
78 == lwcellCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */
79 printf("Connection closed by remote side...\r\n");
80 break;
81 } else if (res == lwcellTIMEOUT) {
82 printf("Netconn timeout while receiving data. You may try multiple readings before deciding to "
83 "close manually\r\n");
84 }
85
86 if (res == lwcellOK && pbuf != NULL) { /* Make sure we have valid packet buffer */
87 /*
88 * At this point read and manipulate
89 * with received buffer and check if you expect more data
90 *
91 * After you are done using it, it is important
92 * you free the memory otherwise memory leaks will appear
93 */
94 printf("Received new data packet of %d bytes\r\n", (int)lwcell_pbuf_length(pbuf, 1));
95 lwcell_pbuf_free_s(&pbuf); /* Free the memory after usage */
96 }
97 } while (1);
98 } else {
99 printf("Error writing data to remote host!\r\n");
100 }
101
102 /*
103 * Check if connection was closed by remote server
104 * and in case it wasn't, close it manually
105 */
106 if (res != lwcellCLOSED) {
107 lwcell_netconn_close(client);
108 }
109 } else {
110 printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT);
111 }
112 lwcell_netconn_delete(client); /* Delete netconn structure */
113 }
114 lwcell_network_request_detach(); /* Detach from network */
115
116 if (lwcell_sys_sem_isvalid(sem)) {
117 lwcell_sys_sem_release(sem);
118 }
119 lwcell_sys_thread_terminate(NULL); /* Terminate current thread */
120}
121
122#endif /* LWCELL_CFG_NETCONN */
Non-blocking receive
By default, netconn API is written to only work in separate application thread, dedicated for network connection processing. Because of that, by default every function is fully blocking. It will wait until result is ready to be used by application.
It is, however, possible to enable timeout feature for receiving data only.
When this feature is enabled, lwcell_netconn_receive() will block for maximal timeout set with
lwcell_netconn_set_receive_timeout() function.
When enabled, if there is no received data for timeout amount of time, function will return with timeout status and application needs to process it accordingly.
Tip
LWCELL_CFG_NETCONN_RECEIVE_TIMEOUT must be set to 1 to use this feature.
- group LWCELL_NETCONN
Network connection.
Defines
-
LWCELL_NETCONN_RECEIVE_NO_WAIT
Receive data with no timeout.
Note
Used with lwcell_netconn_set_receive_timeout function
-
LWCELL_NETCONN_FLAG_FLUSH
Immediate flush after netconn write
Typedefs
-
typedef struct lwcell_netconn *lwcell_netconn_p
Netconn object structure.
Enums
-
enum lwcell_netconn_type_t
Netconn connection type.
Values:
-
enumerator LWCELL_NETCONN_TYPE_TCP = LWCELL_CONN_TYPE_TCP
TCP connection
-
enumerator LWCELL_NETCONN_TYPE_UDP = LWCELL_CONN_TYPE_UDP
UDP connection
-
enumerator LWCELL_NETCONN_TYPE_SSL = LWCELL_CONN_TYPE_SSL
TCP connection over SSL Note: This option is unstable on SIM868 devices due to firmware issues
-
enumerator LWCELL_NETCONN_TYPE_TCP = LWCELL_CONN_TYPE_TCP
Functions
-
lwcell_netconn_p lwcell_netconn_new(lwcell_netconn_type_t type)
Create new netconn connection.
- Parameters
type – [in] Netconn connection type
- Returns
New netconn connection on success,
NULLotherwise
-
lwcellr_t lwcell_netconn_delete(lwcell_netconn_p nc)
Delete netconn connection.
-
lwcellr_t lwcell_netconn_connect(lwcell_netconn_p nc, const char *host, lwcell_port_t port)
Connect to server as client.
-
lwcellr_t lwcell_netconn_receive(lwcell_netconn_p nc, lwcell_pbuf_p *pbuf)
Receive data from connection.
- Parameters
nc – [in] Netconn handle used to receive from
pbuf – [in] Pointer to pointer to save new receive buffer to. When function returns, user must check for valid pbuf value
pbuf != NULL
- Returns
lwcellOK when new data ready,
- Returns
lwcellCLOSED when connection closed by remote side,
- Returns
lwcellTIMEOUT when receive timeout occurs
- Returns
Any other member of lwcellr_t otherwise
-
lwcellr_t lwcell_netconn_close(lwcell_netconn_p nc)
Close a netconn connection.
-
int8_t lwcell_netconn_getconnnum(lwcell_netconn_p nc)
Get connection number used for netconn.
- Parameters
nc – [in] Netconn handle
- Returns
-1on failure, connection number between0and LWCELL_CFG_MAX_CONNS otherwise
-
void lwcell_netconn_set_receive_timeout(lwcell_netconn_p nc, uint32_t timeout)
Set timeout value for receiving data.
When enabled, lwcell_netconn_receive will only block for up to timeout value and will return if no new data within this time
- Parameters
nc – [in] Netconn handle
timeout – [in] Timeout in units of milliseconds. Set to
0to disable timeout feature. Function blocks until data receive or connection closed Set to> 0to set maximum milliseconds to wait before timeout Set to LWCELL_NETCONN_RECEIVE_NO_WAIT to enable non-blocking receive
-
uint32_t lwcell_netconn_get_receive_timeout(lwcell_netconn_p nc)
Get netconn receive timeout value.
- Parameters
nc – [in] Netconn handle
- Returns
Timeout in units of milliseconds. If value is
0, timeout is disabled (wait forever)
-
lwcellr_t lwcell_netconn_write(lwcell_netconn_p nc, const void *data, size_t btw)
Write data to connection output buffers.
Note
This function may only be used on TCP or SSL connections
-
lwcellr_t lwcell_netconn_write_ex(lwcell_netconn_p nc, const void *data, size_t btw, uint16_t flags)
Extended version of lwcell_netconn_write with additional option to set custom flags.
Note
It is recommended to use this for full features support
-
lwcellr_t lwcell_netconn_flush(lwcell_netconn_p nc)
Flush buffered data on netconn TCP/SSL connection.
Note
This function may only be used on TCP/SSL connection
-
lwcellr_t lwcell_netconn_send(lwcell_netconn_p nc, const void *data, size_t btw)
Send data on UDP connection to default IP and port.
-
lwcellr_t lwcell_netconn_sendto(lwcell_netconn_p nc, const lwcell_ip_t *ip, lwcell_port_t port, const void *data, size_t btw)
Send data on UDP connection to specific IP and port.
Note
Use this function in case of UDP type netconn
-
LWCELL_NETCONN_RECEIVE_NO_WAIT