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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | #include "netconn_client.h"
#include "lwgsm/lwgsm.h"
#include "lwgsm/lwgsm_network_api.h"
#if LWGSM_CFG_NETCONN
/**
* \brief Host and port settings
*/
#define NETCONN_HOST "example.com"
#define NETCONN_PORT 80
/**
* \brief Request header to send on successful connection
*/
static const char
request_header[] = ""
"GET / HTTP/1.1\r\n"
"Host: " NETCONN_HOST "\r\n"
"Connection: close\r\n"
"\r\n";
/**
* \brief Netconn client thread implementation
* \param[in] arg: User argument
*/
void
netconn_client_thread(void const* arg) {
lwgsmr_t res;
lwgsm_pbuf_p pbuf;
lwgsm_netconn_p client;
lwgsm_sys_sem_t* sem = (void*)arg;
/* Request attach to network */
while (lwgsm_network_request_attach() != lwgsmOK) {
lwgsm_delay(1000);
}
/*
* First create a new instance of netconn
* connection and initialize system message boxes
* to accept received packet buffers
*/
client = lwgsm_netconn_new(LWGSM_NETCONN_TYPE_TCP);
if (client != NULL) {
/*
* Connect to external server as client
* with custom NETCONN_CONN_HOST and CONN_PORT values
*
* Function will block thread until we are successfully connected (or not) to server
*/
res = lwgsm_netconn_connect(client, NETCONN_HOST, NETCONN_PORT);
if (res == lwgsmOK) { /* Are we successfully connected? */
printf("Connected to " NETCONN_HOST "\r\n");
res = lwgsm_netconn_write(client, request_header, sizeof(request_header) - 1); /* Send data to server */
if (res == lwgsmOK) {
res = lwgsm_netconn_flush(client);/* Flush data to output */
}
if (res == lwgsmOK) { /* Were data sent? */
printf("Data were successfully sent to server\r\n");
/*
* Since we sent HTTP request,
* we are expecting some data from server
* or at least forced connection close from remote side
*/
do {
/*
* Receive single packet of data
*
* Function will block thread until new packet
* is ready to be read from remote side
*
* After function returns, don't forgot the check value.
* Returned status will give you info in case connection
* was closed too early from remote side
*/
res = lwgsm_netconn_receive(client, &pbuf);
if (res == lwgsmCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */
printf("Connection closed by remote side...\r\n");
break;
} else if (res == lwgsmTIMEOUT) {
printf("Netconn timeout while receiving data. You may try multiple readings before deciding to close manually\r\n");
}
if (res == lwgsmOK && pbuf != NULL) { /* Make sure we have valid packet buffer */
/*
* At this point read and manipulate
* with received buffer and check if you expect more data
*
* After you are done using it, it is important
* you free the memory otherwise memory leaks will appear
*/
printf("Received new data packet of %d bytes\r\n", (int)lwgsm_pbuf_length(pbuf, 1));
lwgsm_pbuf_free(pbuf); /* Free the memory after usage */
pbuf = NULL;
}
} while (1);
} else {
printf("Error writing data to remote host!\r\n");
}
/*
* Check if connection was closed by remote server
* and in case it wasn't, close it manually
*/
if (res != lwgsmCLOSED) {
lwgsm_netconn_close(client);
}
} else {
printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT);
}
lwgsm_netconn_delete(client); /* Delete netconn structure */
}
lwgsm_network_request_detach(); /* Detach from network */
if (lwgsm_sys_sem_isvalid(sem)) {
lwgsm_sys_sem_release(sem);
}
lwgsm_sys_thread_terminate(NULL); /* Terminate current thread */
}
#endif /* LWGSM_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, lwgsm_netconn_receive() will block for maximal timeout set with
lwgsm_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
LWGSM_CFG_NETCONN_RECEIVE_TIMEOUT must be set to 1 to use this feature.
-
group
LWGSM_NETCONN Network connection.
Typedefs
-
typedef struct lwgsm_netconn *
lwgsm_netconn_p¶ Netconn object structure.
Enums
Functions
-
lwgsm_netconn_p
lwgsm_netconn_new(lwgsm_netconn_type_t type)¶ Create new netconn connection.
- Return
New netconn connection on success,
NULLotherwise- Parameters
[in] type: Netconn connection type
-
lwgsmr_t
lwgsm_netconn_delete(lwgsm_netconn_p nc)¶ Delete netconn connection.
-
lwgsmr_t
lwgsm_netconn_connect(lwgsm_netconn_p nc, const char *host, lwgsm_port_t port)¶ Connect to server as client.
-
lwgsmr_t
lwgsm_netconn_receive(lwgsm_netconn_p nc, lwgsm_pbuf_p *pbuf)¶ Receive data from connection.
- Return
lwgsmOK when new data ready,
- Return
lwgsmCLOSED when connection closed by remote side,
- Return
lwgsmTIMEOUT when receive timeout occurs
- Return
Any other member of lwgsmr_t otherwise
- Parameters
[in] nc: Netconn handle used to receive from[in] pbuf: Pointer to pointer to save new receive buffer to. When function returns, user must check for valid pbuf valuepbuf != NULL
-
lwgsmr_t
lwgsm_netconn_close(lwgsm_netconn_p nc)¶ Close a netconn connection.
-
int8_t
lwgsm_netconn_getconnnum(lwgsm_netconn_p nc)¶ Get connection number used for netconn.
- Return
-1on failure, connection number between0and LWGSM_CFG_MAX_CONNS otherwise- Parameters
[in] nc: Netconn handle
-
void
lwgsm_netconn_set_receive_timeout(lwgsm_netconn_p nc, uint32_t timeout)¶ Set timeout value for receiving data.
When enabled, lwgsm_netconn_receive will only block for up to timeout value and will return if no new data within this time
- Parameters
[in] nc: Netconn handle[in] timeout: Timeout in units of milliseconds. Set to0to disable timeout for lwgsm_netconn_receive function
-
uint32_t
lwgsm_netconn_get_receive_timeout(lwgsm_netconn_p nc)¶ Get netconn receive timeout value.
- Return
Timeout in units of milliseconds. If value is
0, timeout is disabled (wait forever)- Parameters
[in] nc: Netconn handle
-
lwgsmr_t
lwgsm_netconn_write(lwgsm_netconn_p nc, const void *data, size_t btw)¶ Write data to connection output buffers.
-
lwgsmr_t
lwgsm_netconn_flush(lwgsm_netconn_p nc)¶ Flush buffered data on netconn TCP/SSL connection.
-
lwgsmr_t
lwgsm_netconn_send(lwgsm_netconn_p nc, const void *data, size_t btw)¶ Send data on UDP connection to default IP and port.
-
lwgsmr_t
lwgsm_netconn_sendto(lwgsm_netconn_p nc, const lwgsm_ip_t *ip, lwgsm_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
- Return
lwgsmOK on success, member of lwgsmr_t enumeration otherwise
- Parameters
[in] nc: Netconn handle used to send[in] ip: Pointer to IP address[in] port: Port number used to send data[in] data: Pointer to data to write[in] btw: Number of bytes to write
-
typedef struct lwgsm_netconn *