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

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.

Netconn client example
  1#include "netconn_client.h"
  2#include "lwgsm/lwgsm.h"
  3#include "lwgsm/lwgsm_network_api.h"
  4
  5#if LWGSM_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
 17request_header[] = ""
 18                   "GET / HTTP/1.1\r\n"
 19                   "Host: " NETCONN_HOST "\r\n"
 20                   "Connection: close\r\n"
 21                   "\r\n";
 22
 23/**
 24 * \brief           Netconn client thread implementation
 25 * \param[in]       arg: User argument
 26 */
 27void
 28netconn_client_thread(void const* arg) {
 29    lwgsmr_t res;
 30    lwgsm_pbuf_p pbuf;
 31    lwgsm_netconn_p client;
 32    lwgsm_sys_sem_t* sem = (void*)arg;
 33
 34    /* Request attach to network */
 35    while (lwgsm_network_request_attach() != lwgsmOK) {
 36        lwgsm_delay(1000);
 37    }
 38
 39    /*
 40     * First create a new instance of netconn
 41     * connection and initialize system message boxes
 42     * to accept received packet buffers
 43     */
 44    client = lwgsm_netconn_new(LWGSM_NETCONN_TYPE_TCP);
 45    if (client != NULL) {
 46        /*
 47         * Connect to external server as client
 48         * with custom NETCONN_CONN_HOST and CONN_PORT values
 49         *
 50         * Function will block thread until we are successfully connected (or not) to server
 51         */
 52        res = lwgsm_netconn_connect(client, NETCONN_HOST, NETCONN_PORT);
 53        if (res == lwgsmOK) {                     /* Are we successfully connected? */
 54            printf("Connected to " NETCONN_HOST "\r\n");
 55            res = lwgsm_netconn_write(client, request_header, sizeof(request_header) - 1);    /* Send data to server */
 56            if (res == lwgsmOK) {
 57                res = lwgsm_netconn_flush(client);/* Flush data to output */
 58            }
 59            if (res == lwgsmOK) {                 /* Were data sent? */
 60                printf("Data were successfully sent to server\r\n");
 61
 62                /*
 63                 * Since we sent HTTP request,
 64                 * we are expecting some data from server
 65                 * or at least forced connection close from remote side
 66                 */
 67                do {
 68                    /*
 69                     * Receive single packet of data
 70                     *
 71                     * Function will block thread until new packet
 72                     * is ready to be read from remote side
 73                     *
 74                     * After function returns, don't forgot the check value.
 75                     * Returned status will give you info in case connection
 76                     * was closed too early from remote side
 77                     */
 78                    res = lwgsm_netconn_receive(client, &pbuf);
 79                    if (res == lwgsmCLOSED) {     /* Was the connection closed? This can be checked by return status of receive function */
 80                        printf("Connection closed by remote side...\r\n");
 81                        break;
 82                    } else if (res == lwgsmTIMEOUT) {
 83                        printf("Netconn timeout while receiving data. You may try multiple readings before deciding to close manually\r\n");
 84                    }
 85
 86                    if (res == lwgsmOK && 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)lwgsm_pbuf_length(pbuf, 1));
 95                        lwgsm_pbuf_free(pbuf);    /* Free the memory after usage */
 96                        pbuf = NULL;
 97                    }
 98                } while (1);
 99            } else {
100                printf("Error writing data to remote host!\r\n");
101            }
102
103            /*
104             * Check if connection was closed by remote server
105             * and in case it wasn't, close it manually
106             */
107            if (res != lwgsmCLOSED) {
108                lwgsm_netconn_close(client);
109            }
110        } else {
111            printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT);
112        }
113        lwgsm_netconn_delete(client);             /* Delete netconn structure */
114    }
115    lwgsm_network_request_detach();               /* Detach from network */
116
117    if (lwgsm_sys_sem_isvalid(sem)) {
118        lwgsm_sys_sem_release(sem);
119    }
120    lwgsm_sys_thread_terminate(NULL);             /* Terminate current thread */
121}
122
123#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

enum lwgsm_netconn_type_t

Netconn connection type.

Values:

enumerator LWGSM_NETCONN_TYPE_TCP

TCP connection

enumerator LWGSM_NETCONN_TYPE_UDP

UDP connection

enumerator LWGSM_NETCONN_TYPE_SSL

TCP connection over SSL

Functions

lwgsm_netconn_p lwgsm_netconn_new(lwgsm_netconn_type_t type)

Create new netconn connection.

Parameters

type[in] Netconn connection type

Returns

New netconn connection on success, NULL otherwise

lwgsmr_t lwgsm_netconn_delete(lwgsm_netconn_p nc)

Delete netconn connection.

Parameters

nc[in] Netconn handle

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

lwgsmr_t lwgsm_netconn_connect(lwgsm_netconn_p nc, const char *host, lwgsm_port_t port)

Connect to server as client.

Parameters
  • nc[in] Netconn handle

  • host[in] Pointer to host, such as domain name or IP address in string format

  • port[in] Target port to use

Returns

lwgsmOK if successfully connected, member of lwgsmr_t otherwise

lwgsmr_t lwgsm_netconn_receive(lwgsm_netconn_p nc, lwgsm_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

lwgsmOK when new data ready,

Returns

lwgsmCLOSED when connection closed by remote side,

Returns

lwgsmTIMEOUT when receive timeout occurs

Returns

Any other member of lwgsmr_t otherwise

lwgsmr_t lwgsm_netconn_close(lwgsm_netconn_p nc)

Close a netconn connection.

Parameters

nc[in] Netconn handle to close

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

int8_t lwgsm_netconn_getconnnum(lwgsm_netconn_p nc)

Get connection number used for netconn.

Parameters

nc[in] Netconn handle

Returns

-1 on failure, connection number between 0 and LWGSM_CFG_MAX_CONNS otherwise

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
  • nc[in] Netconn handle

  • timeout[in] Timeout in units of milliseconds. Set to 0 to disable timeout for lwgsm_netconn_receive function

uint32_t lwgsm_netconn_get_receive_timeout(lwgsm_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)

lwgsmr_t lwgsm_netconn_write(lwgsm_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

Parameters
  • nc[in] Netconn handle used to write data to

  • data[in] Pointer to data to write

  • btw[in] Number of bytes to write

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

lwgsmr_t lwgsm_netconn_flush(lwgsm_netconn_p nc)

Flush buffered data on netconn TCP/SSL connection.

Note

This function may only be used on TCP/SSL connection

Parameters

nc[in] Netconn handle to flush data

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

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.

Parameters
  • nc[in] Netconn handle used to send

  • data[in] Pointer to data to write

  • btw[in] Number of bytes to write

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

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

Parameters
  • nc[in] Netconn handle used to send

  • ip[in] Pointer to IP address

  • port[in] Port number used to send data

  • data[in] Pointer to data to write

  • btw[in] Number of bytes to write

Returns

lwgsmOK on success, member of lwgsmr_t enumeration otherwise