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
  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

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.

Return

New netconn connection on success, NULL otherwise

Parameters
  • [in] type: Netconn connection type

lwgsmr_t lwgsm_netconn_delete(lwgsm_netconn_p nc)

Delete netconn connection.

Return

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

Parameters
  • [in] nc: Netconn handle

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

Connect to server as client.

Return

lwgsmOK if successfully connected, member of lwgsmr_t otherwise

Parameters
  • [in] nc: Netconn handle

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

  • [in] port: Target port to use

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 value pbuf != NULL

lwgsmr_t lwgsm_netconn_close(lwgsm_netconn_p nc)

Close a netconn connection.

Return

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

Parameters
  • [in] nc: Netconn handle to close

int8_t lwgsm_netconn_getconnnum(lwgsm_netconn_p nc)

Get connection number used for netconn.

Return

-1 on failure, connection number between 0 and 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 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.

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.

Note

This function may only be used on TCP or SSL connections

Return

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

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

  • [in] data: Pointer to data to write

  • [in] btw: Number of bytes to write

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

Return

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

Parameters
  • [in] nc: Netconn handle to flush data

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.

Return

lwgsmOK on success, member of lwgsmr_t enumeration otherwise

Parameters
  • [in] nc: Netconn handle used to send

  • [in] data: Pointer to data to write

  • [in] btw: Number of bytes to write

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