Application Modules#

This section introduces you to the various network application modules that are included as part of Micrium OS.

Complementary information is also available in the Network section of the Technologies Overview documentation page. The following sections will refer to it when appropriate.

HTTP Client Module#

The Micrium OS HTTP Client can be used to access HTTP servers and perform actions on resources maintained by a server.

In an embedded environment, an HTTP client will rarely be used to display web pages like a web browser does. It will primarily be used to get and update specific data, download and upload files or to interface with web services.

HTTP Client Protocol Recognized Fields

HTTP Client Overview#

Specifications#

  • Complies with the following RFC:

    • RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1

    • RFC 6455 - The WebSocket Protocol

  • Implements the following methods:

    • GET

    • POST

    • PUT

    • DELETE

    • HEAD

Features#

Design#

The HTTP Client module has been designed to suit many different types of HTTP client applications. With the right configuration it can be used with a very low footprint to send a simple HTTP request and wait for the HTTP server's response. Another benefit of its design is that it can also be used to make simultaneous HTTP requests by opening multiple connections which allows for consistent usage of the same API calls.

Memory Usage#

Each HTTP client application can have very different memory needs. For example, some applications will only require one connection whereas others will require more; some applications will prefer to allocate objects on their own stack while others will want to use a memory pool on the heap. Therefore, to conform with all of these different requirements, HTTP Client does not have its own memory module. All the objects required by the HTTP Client MUST be passed by the application. Three HTTP Client Objects must be supplied by the Application: a Connection object , a Request Object and a Response Object . Also, a buffer per connection must be supplied for the transmission/reception operations. Additional objects may be required when some available features are enabled.

It is very important that every object passed by the application to the HTTP Client stack remain valid for the duration of the HTTP transaction or until the connection is closed for the HTTP Client Connection Object.

Internal Task#

To support multiple simultaneous connections, HTTP Client has an internal task. This task also allows the queuing of multiple requests on a given connection. When the HTTP Client Task is present, API calls to HTTP Client's stack can be set to the blocking or non-blocking mode.

For simpler applications and to reduce memory footprint, the internal HTTP Client task can be disabled. In that case, HTTP Client operations will be executed directly in the application task and will always be blocking.

Auto Select Remote IP address#

When the DNS Client that is part of the core network is properly configured, HTTP Client can accept a host name string to connect to the remote server. It will perform the IP address resolution by communicating with a DNS server. If the DNS server sends back IPv4 and IPv6 addresses, the first attempt will be to use the IPv6 address to connect to the remote HTTP server. If this connection fails the IPv4 address will be used instead.

Limitations#

  • Only supports HTTP v1.1.

  • HTTP range requests are not supported.

HTTP Client Example Applications#

This section describes the examples that are related to the HTTP Client module of Micrium OS.

HTTP Client Initialization Example#

Description#

This is a generic example that shows how to initialize the HTTP client module. It accomplishes the following tasks:

  • Initialize the HTTP client module

  • Create a RAM disk for file exchange:

    • Store a file (index.html) to be sent to a server

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the HTTP Client module correctly:

#define

Description

EX_HTTP_CLIENT_INIT_AVAIL

Lets the upper example layer know that the HTTP Client Initialization example is present and must be called by other examples.

Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org"

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_Init()

Initialize the HTTP Client stack for the example application.

Notes#

None.

HTTP Client GET Request Examples#

Description#

This is a generic example that shows how to send GET request. It accomplishes the following tasks:

  • Set connection option

  • Open an HTTP connection

  • Send GET request

  • Close HTTP Connection

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org "

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client_files.c

/examples/net/http/client/ex_http_client_files.h

/examples/net/http/client/ex_http_client_hooks.c

/examples/net/http/client/ex_http_client_hooks.h

/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_ReqSendGet_NoTask()

Send a GET request synchronously, i.e., returns only when the transaction is completed.

Ex_HTTP_Client_ReqSendGet()

Send a GET request asynchronously. Show the callback system to be notified when the transaction is completed.

Notes#

None.

HTTP Client POST Request Examples#

Description#

This is a generic example that shows how to send POST request. It accomplishes the following tasks:

  • Set connection option

  • Open an HTTP connection

  • Send POST request

  • Close HTTP Connection

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org "

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client_files.c

/examples/net/http/client/ex_http_client_files.h

/examples/net/http/client/ex_http_client_hooks.c

/examples/net/http/client/ex_http_client_hooks.h

/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_ReqSendPost()

Send a POST request with a pre-formatted form as body.

Ex_HTTP_Client_ReqSendAppForm()

Send an Application type form.

Ex_HTTP_Client_ReqSendMultipartForm()

Send a multipart type form.

Notes#

None.

HTTP Client PUT Request Examples#

Description#

This is a generic example that shows how to send PUT request. It accomplishes the following tasks:

  • Set connection option

  • Open an HTTP connection

  • Send PUT request

  • Close HTTP Connection

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org "

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client_files.c

/examples/net/http/client/ex_http_client_files.h

/examples/net/http/client/ex_http_client_hooks.c

/examples/net/http/client/ex_http_client_hooks.h

/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_ReqSendPut()

Send PUT request.

Notes#

None.

HTTP Client Persistent Connection Examples#

Description#

This is a generic example that shows how to send multiple GET request on the same connection. It accomplishes the following tasks:

  • Set connection option

  • Open an HTTP connection

  • Send GET request #1

  • Send GET request #2

  • Close HTTP Connection

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org "

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client_files.c

/examples/net/http/client/ex_http_client_files.h

/examples/net/http/client/ex_http_client_hooks.c

/examples/net/http/client/ex_http_client_hooks.h

/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_PersistentConn()

Send multiple requests on same connection.

Notes#

None.

HTTP Client Multi-connection Examples#

Description#

This is a generic example that shows how to open multiple connections and how to send requests in parallel. It accomplishes the following tasks:

  • Set connection #1 option

  • Set connection #2 option

  • Open an HTTP connection #1

  • Open an HTTP connection #2

  • Send GET request #1

  • Send GET request #2

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_HTTP_CLIENT_RAMDISK_SEC_SIZE

512 u

Specify the sector size of the RAM disk

EX_HTTP_CLIENT_RAMDISK_SEC_NBR

60 u

Specify the number of sector for the RAM disk

EX_HTTP_CLIENT_FILE_RAM_MEDIA_NAME

"ram_httpc"

Specify the RAM media name

EX_HTTP_CLIENT_FILE_VOL_NAME

"ram_httpc"

Specify the RAM volume name

EX_HTTP_CLIENT_WRK_DIR

EX_HTTP_CLIENT_FILE_VOL_NAME

Specify the working directory used by the example

EX_HTTP_CLIENT_FILE_NAME

"index.html"

Specify the name of the internal file.

EX_HTTP_CLIENT_CLIENT_HOSTNAME

"httpbin.org "

Specify the server host name used by the client

EX_HTTP_CLIENT_CONN_NBR_MAX

5 u

Specify the maximum of active connection

EX_HTTP_CLIENT_REQ_NBR_MAX

5 u

Specify the maximum of requests

EX_HTTP_CLIENT_CONN_BUF_SIZE

512 u

Specify the connection buffer size

EX_HTTP_CLIENT_CFG_QUERY_STR_NBR_MAX

6 u

Specify the maximum number of query string

EX_HTTP_CLIENT_CFG_QUERY_STR_KEY_LEN_MAX

20 u

Specify the maximum of query string key length

EX_HTTP_CLIENT_CFG_QUERY_STR_VAL_LEN_MAX

50 u

Specify the maximum of query string value length

EX_HTTP_CLIENT_CFG_HDR_NBR_MAX

6 u

Specify the maximum of header object

EX_HTTP_CLIENT_CFG_HDR_VAL_LEN_MAX

100 u

Specify the maximum of header value length

EX_HTTP_CLIENT_CFG_FORM_BUF_SIZE

256 u

Specify the form buffer size.

EX_HTTP_CLIENT_CFG_FORM_FIELD_NBR_MAX

10 u

Specify the maximum number of form's field

EX_HTTP_CLIENT_CFG_FORM_FIELD_KEY_LEN_MAX

100 u

Specify the maximum of form key length

EX_HTTP_CLIENT_CFG_FORM_FIELD_VAL_LEN_MAX

200 u

Specify the maximum of form value length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_NAME_LEN_MAX

100 u

Specify the maximum of multipart name length

EX_HTTP_CLIENT_CFG_FORM_MULTIPART_FILENAME_LEN_MAX

100 u

Specify the maximum of multipart filename length

Location#
/examples/net/http/client/ex_http_client_files.c

/examples/net/http/client/ex_http_client_files.h

/examples/net/http/client/ex_http_client_hooks.c

/examples/net/http/client/ex_http_client_hooks.h

/examples/net/http/client/ex_http_client.c

/examples/net/http/client/ex_http_client.h
API#

API

Description

Ex_HTTP_Client_MultiConn()

Open multiple Connections to send HTTP requests in parallel.

Notes#

None.

HTTP Client Configuration#

In order to address your application's needs, the HTTP Client module must be properly configured. There are two groups of configuration parameters:

HTTP Client Compile-Time Configurations#

Micrium OS HTTP Client is configurable at compile time via several #defines located in http_client_cfg.h file. HTTP Client module uses #defines when possible, because they allow code and data sizes to be scaled at compile time based on enabled features. This allows the Read-Only Memory (ROM) and Random-Access Memory (RAM) footprints of the HTTP Client module to be adjusted based on application requirements.

It is recommended that the configuration process begins with the default configuration values which in the next sections will be shown in bold.

Task Configuration#

HTTP Client module has an internal task that can be enabled or disabled. Using this internal task allows for simultaneous connection processing and using the API in a non-blocking mode.

Table - HTTPc Task Configuration#

Constant

Description

Possible Values

HTTPc_CFG_MODE_ASYNC_TASK_EN

Enables/Disables the internal asynchronous task.When ENABLED, the internal task can accept simultaneous connections and can queue requests. API functions can be called with the non-blocking flag.When DISABLED, the API functions will always be blocking.

DEF_ENABLED or DEF_DISABLED

HTTPc_CFG_MODE_BLOCK_EN

Enables/Disables the blocking option when the internal task is active.When the internal task is enabled, API functions can also be blocking but only if this configuration is enabled.

DEF_ENABLED or DEF_DISABLED

Persistent Connection Configuration#
Table - HTTPc Persistent Connection Configuration#

Constant

Description

Possible Values

HTTPc_CFG_PERSISTENT_EN

Enables/Disables the Persistent Connection Feature.

DEF_ENABLED or DEF_DISABLED

Chunked Transfer Encoding Configuration#
Table - HTTPc Chunked Transfer Encoding Configuration#

Constant

Description

Possible Values

HTTPc_CFG_CHUNK_TX_EN

Enables/Disables the Chunked Transfer Encoding feature for transmission

DEF_ENABLED or DEF_DISABLED

Query String Configuration#
Table - HTTPc Query String Configuration#

Constant

Description

Possible Values

HTTPc_CFG_QUERY_STR_EN

Enables/Disables the Query String Feature.

DEF_ENABLED or DEF_DISABLED

Header Field Configuration#
Table - HTTPc Header Field Configuration#

Constant

Description

Possible Values

HTTPc_CFG_HDR_RX_EN

Enables/Disables the addition of header fields to HTTP Requests when transmitting.

DEF_ENABLED or DEF_DISABLED

HTTPc_CFG_HDR_TX_EN

Enables/Disables the copy and processing of header fields for HTTP Responses received.

DEF_ENABLED or DEF_DISABLED

Form Submission Configuration#
Table - HTTPc Form Submission Configuration#

Constant

Description

Possible Values

HTTPc_CFG_FORM_EN

Enables/Disables the HTTP Form Submission Feature.

DEF_ENABLED or DEF_DISABLED

User Data Configuration#
Table - HTTPc User Data Configuration#

Constant

Description

Possible Values

HTTPc_CFG_USER_DATA_EN

Enables/Disables the addition of a void pointer in the HTTPc_CONN_OBJ and HTTPc_REQ_OBJ objects.The additional void pointer can be used by the upper application to store an application data pointer relative to the object.

DEF_ENABLED or DEF_DISABLED

WebSocket Configuration#
Table - HTTPc WebSocket Configuration#

Constant

Description

Possible Values

HTTPc_CFG_WEBSOCKET_EN

Enables/Disables the WebSocket Feature.

DEF_ENABLED or DEF_DISABLED

The WebSocket feature requires HTTPc_CFG_MODE_ASYNC_TASK_EN to be set to DEF_ENABLED.

HTTP Client Run-Time Application Specific Configurations#

This section defines the configurations related to HTTP Client but that are specified at run-time, during the initialization process.

Initialization#

Initializing the HTTP Client module is done by calling the function HTTPc_Init(). This function takes no configuration argument. Unless you override an optional configuration before calling the function HTTPc_Init(), the default configurations will be used.

Optional configurations#

This section describes the configurations that are optional. If you do not set them in your application, the default configurations will apply.

The default values can be retrieved via the structure HTTPc_InitCfgDflt.

Note that these configurations must be set before you call the function HTTPc_Init().

Table - HTTP Client Optional Configurations#

Configurations

Description

Type

Function to call

Default

Field from default configuration structure

Task's stack

The HTTP client module can use a task depending on the compile-time configuration. This configuration allows you to set the stack pointer and the stack size (in quantity of elements).

CPU_INT32Uvoid *

HTTPc_ConfigureTaskStk()

A stack of 768 elements allocated on Common 's memory segment.

.StkSizeElements.StkPtr

Memory segment

This module allocates some control data. You can specify the memory segment from where such data should be allocated.

MEM_SEG *

HTTPc_ConfigureMemSeg()

General-purpose heap .

.MemSegPtr

Quantity parameters

The HTTP client task use a message queue. You can overwrite the maximum element in the message pool.

HTTPc_QTY_CFG

HTTPc_ConfigureQty()

Unlimited queue size.

.QtyCfg

Connection parameters

The HTTP client allows to configure the connection timeouts.

HTTPc_CONN_CFG

HTTPc_ConfigureConnParam()

Timeout of 30 milliseconds for connection timeout and 30 seconds for inactivity.

.ConnCfg

Post-Init Configurations#

This section describes the configurations that can be set at any time during execution after you called the function HTTPc_Init().

These configurations are optional. If you do not set them in your application, the default configurations will apply.

Table - HTTP Client Post-init Configurations#

Configurations

Description

Type

Function to call

Default

Task priority

The HTTP client module will create a task that handles the HTTP requests. You can change the priority of the created task at any time.

RTOS_TASK_PRIO

HTTPc_TaskPrioSet()

See Appendix A - Internal Tasks .

Task Delay

If the HTTP client module uses a task, you can change the delay inside this task to allow a period of time for other tasks to run.

CPU_INT08U

HTTPc_TaskDlySet()

1u

HTTP Client Connection Configurations#

Table - HTTPc_CONN_CFG configuration structure in the HTTP Client Connection Configurations page describes each configuration field available in this configuration structure.

Table - HTTPc_CONN_CFG configuration structure#

Field

Description

.ConnConnectTimeout_ms

Connection connect timeout, in milliseconds.

.ConnInactivityTimeout_s

Connection inactivity timeout, in seconds.

HTTP Client Quantity Configurations#

Table - HTTPc_QTY_CFG configuration structure in the HTTP Client Quantity Configurations page describes each configuration field available in this configuration structure.

Table - HTTPc_QTY_CFG configuration structure#

Field

Description

.MsgQ_Size

Maximum size of the message queue.

HTTP Client Programming Guide#

This Section regroups topics to help developing a custom HTTP client application with the MIcrium OS HTTP Client module. Examples are include in many sub-sections.

HTTP Client Control Structure#

The HTTP Client module offers many structures that the application can use to create objects to interact with the API.

All the HTTP Client Objects required by the application must be allocated by the application and passed to the HTTP Client API.

All objects or strings passed to the HTTP Client API MUST be persistent and unmodified for the duration of the HTTP Transaction for Request-oriented parameters and objects; or until the HTTP connection is closed for Connection-oriented parameters and objects.

HTTP Client Connection (HTTPc_CONN_OBJ)#

This structure is the main one used by the HTTP Client module. It contains all parameters relative to an HTTP connection (server port number, server address, server host name, etc.) and also many internal parameters for the HTTP connection and HTTP transaction processing.

Each configurable parameter SHOULD be set up with the function HTTPc_ConnSetParam(). The list of available parameters for a connection can be viewed here .

The members of an HTTP Client object should never be directly tampered with at any time. To ensure this, the HTTPc_CONN_OBJ structure's members have all been declared constant with the const keyword and the suffix _reserved has been added.

Listing - HTTPc_CONN Structure#
struct httpc_conn_obj {
                                                                  /* --------- CONNECTION PARAMETERS --------- */
  const  NET_SOCK_ID                SockID_reserved;              /* Connection's Socket ID.                   */
  const  HTTPc_FLAGS                SockFlags_reserved;           /* Connection's Socket flags.                */
#ifdef NET_SECURE_MODULE_EN
  const  NET_APP_SOCK_SECURE_CFG    SockSecureCfg_reserved;       /* Connection's Socket Secure Cfg.           */
#endif
  const  CPU_INT16U                 ConnectTimeout_ms_reserved;   /* Connection Connect Timeout.               */
  const  CPU_INT16U                 InactivityTimeout_s_reserved; /* Connection Inactivity Timeout.            */
  const  NET_PORT_NBR               ServerPort_reserved;
  const  NET_SOCK_ADDR              ServerSockAddr_reserved;      /* Server socket address.                    */
  const  CPU_CHAR                  *HostNamePtr_reserved;         /* Pointer to HTTP server hostname string.   */
  const  CPU_INT16U                 HostNameLen_reserved;
  const  HTTPc_CONN_STATE           State_reserved;               /* Connection State.                         */
  const  HTTPc_FLAGS                Flags_reserved;               /* Set of flags related to HTTP connection.  */
  const  HTTPc_CONN_CLOSE_STATUS    CloseStatus_reserved;         /* Status of connection closed.              */
  const  HTTPc_ERR                  ErrCode_reserved;             /* Error code of connection.                 */
#ifdef HTTPc_TASK_MODULE_EN
  const  HTTPc_CONNECT_CALLBACK     OnConnect_reserved;           /* Connection Connect callback function.     */
  const  HTTPc_CONN_CLOSE_CALLBACK  OnClose_reserved;             /* Connection Close callback function.       */
  const  HTTPc_CONN_ERR_CALLBACK    OnErr_reserved;               /* Connection Error callback function.       */
#endif
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
  const  KAL_SEM_HANDLE             ConnectSignal_reserved;       /* HTTP Socket Connect Done Signal.          */
  const  KAL_SEM_HANDLE             TransDoneSignal_reserved;     /* HTTP Transaction Done Signal.             */
  const  KAL_SEM_HANDLE             CloseSignal_reserved;         /* HTTP Socket Close Done Signal.            */
#endif
                                                                  /* ----------- REQUEST PARAMETERS ---------- */
  const  HTTPc_REQ                 *ReqListHeadPtr_reserved;      /* Head of the Request list.                 */
  const  HTTPc_REQ                 *ReqListEndPtr_reserved;       /* End of the Request list.                  */
  const  HTTPc_FLAGS                ReqFlags_reserved;            /* Set of flags related to the HTTP request. */
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
  const  CPU_INT16U                 ReqQueryStrTxIx_reserved;     /* Tbl index of the transmitted strings.     */
  const  HTTPc_KEY_VAL             *ReqQueryStrTempPtr_reserved;  /* Temporary Query String to Tx.             */
#endif
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
  const  CPU_INT08U                 ReqHdrTxIx_reserved;          /* Index in Req hdr table to Tx headers.     */
  const  HTTP_HDR                  *ReqHdrTempPtr_reserved;       /* Temporary Header field to Tx.             */
#endif
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
  const  CPU_INT16U                 ReqFormDataTxIx_reserved;     /* Index in form table to Tx form fields.    */
#endif
  const  CPU_INT16U                 ReqDataOffset_reserved;       /* Offset in Request Data Pointer to Tx data */
                                                                  /* ----------- RESPONSE PARAMETERS --------- */
  const  HTTPc_FLAGS                RespFlags_reserved;           /* Set of flags related to the HTTP response.*/
                                                                  /* ------ CONNECTION BUFFER PARAMETERS ----- */
  const  void                      *TxDataPtr_reserved;           /* Pointer to data to transmit.              */
  const  CPU_CHAR                  *BufPtr_reserved;              /* Pointer to conn buffer.                   */
  const  CPU_INT16U                 BufLen_reserved;              /* Conn buffer length.                       */
  const  CPU_CHAR                  *RxBufPtr_reserved;            /* Pointer to Buffer where to Rx data.       */
  const  CPU_INT16U                 RxDataLenRem_reserved;        /* Remaining data in the RX buffer.          */
  const  CPU_INT32U                 RxDataLen_reserved;           /* Data length received.                     */
  const  CPU_CHAR                  *TxBufPtr_reserved;            /* Pointer to Buffer where to Tx data.       */
  const  CPU_INT16U                 TxDataLen_reserved;           /* Length of data to Tx.                     */
                                                                  /* ------- CONNECTION LIST PARAMETERS ------ */
  const  HTTPc_CONN                *NextPtr_reserved;             /* Pointer to next connection.               */
#if (HTTPc_CFG_USER_DATA_EN == DEF_ENABLED)
                                                                  /* ---------- USER DATA PARAMETER ---------- */
         void                      *UserDataPtr;
#endif
};
HTTP Client Request (HTTPc_REQ_OBJ)#

This structure regroups parameters and flags related to the configuration of an HTTP request.

Each configurable parameter SHOULD be set up with the function HTTPc_ReqSetParam(). The list of available parameters for a connection can be viewed here .

The members of an HTTP Request object should never be directly tempered with at any time. To ensure this, the HTTPc_REQ_OBJ structure's members have all been declared constant with the const keyword and the suffix _reserved has been added.

Listing - HTTPc_REQ Structure#
struct httpc_req_obj {
  const  HTTPc_FLAGS                Flags_reserved;
  const  HTTPc_FLAGS                HdrFlags_reserved;
  const  HTTP_METHOD                Method_reserved;
  const  CPU_CHAR                  *ResourcePathPtr_reserved;
  const  CPU_INT16U                 ResourcePathLen_reserved;
  const  HTTP_CONTENT_TYPE          ContentType_reserved;
  const  CPU_INT32U                 ContentLen_reserved;
  const  void                      *DataPtr_reserved;
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
  const  HTTPc_KEY_VAL             *QueryStrTbl_reserved;
  const  CPU_INT16U                 QueryStrNbr_reserved;
  const  HTTPc_REQ_QUERY_STR_HOOK   OnQueryStrTx_reserved;
#endif
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
  const  HTTP_HDR                  *HdrTbl_reserved;
  const  CPU_INT16U                 HdrNbr_reserved;
  const  HTTPc_REQ_HDR_HOOK         OnHdrTx_reserved;
#endif
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
  const  HTTPc_FORM_TBL_FIELD      *FormFieldTbl_reserved;
  const  CPU_INT16U                 FormFieldNbr_reserved;
#endif
#if (HTTPc_CFG_CHUNK_TX_EN == DEF_ENABLED)
  const  HTTPc_REQ_BODY_HOOK        OnBodyChunkTx_reserved;
#endif
#if (HTTPc_CFG_HDR_RX_EN == DEF_ENABLED)
  const  HTTPc_RESP_HDR_HOOK        OnHdrRx_reserved;         /* Resp Hdr Hook fnct to choose which hdr to keep*/
#endif
  const  HTTPc_RESP_BODY_HOOK       OnBodyRx_reserved;        /* Resp Body Hook fnct to pass Rx data to app.   */
#ifdef HTTPc_TASK_MODULE_EN
  const  HTTPc_COMPLETE_CALLBACK    OnTransComplete_reserved; /* Response received callback function.          */
  const  HTTPc_TRANS_ERR_CALLBACK   OnErr_reserved;           /* Transaction Error callback function.          */
#endif
  const  HTTPc_CONN                *ConnPtr_reserved;         /* Pointer to Connection Object.                 */
  const  HTTPc_RESP                *RespPtr_reserved;         /* Pointer to Conn Response Object.              */
  const  HTTPc_REQ                 *NextPtr_reserved;
#if (HTTPc_CFG_USER_DATA_EN == DEF_ENABLED)
         void                      *UserDataPtr;
#endif
};
HTTP Client Response (HTTPc_RESP_OBJ)#

This structure will be filled by the HTTP Client core with the data received in the HTTP response; except for the body part that is retrieved by the application with the hook function On Response Body .

Listing - HTTPc_RESP Structure#
struct httpc_resp_obj {
           HTTP_PROTOCOL_VER          ProtocolVer;             /* HTTP version received in response message.   */
           HTTP_STATUS_CODE           StatusCode;              /* Status code received in response.            */
    const  CPU_CHAR                  *ReasonPhrasePtr;         /* Pointer to received reason phrase.           */
           HTTP_CONTENT_TYPE          ContentType;             /* Content type received in response.           */
           CPU_INT32U                 ContentLen;              /* Content length received in response if any.  */
}
HTTP Client Key-Value Pair (HTTPc_KEY_VAL)#

Key-Value Pair Objects can be used with the HTTP Query String feature and the HTTP Form feature.

The structure's object allows for storing the pointer to an application's Key string and the pointer to its Value string's equivalent key. The string's length must also be saved in the object.

Listing - HTTPc_KEY_VAL Structure#
struct  httpc_key_val {
    CPU_CHAR       *KeyPtr;    /* Pointer to Key String.   */
    CPU_INT16U      KeyLen;    /* Length of Key String.    */
    CPU_CHAR       *ValPtr;    /* Pointer to Value String. */
    CPU_INT16U      ValLen;    /* Length of Value String.  */
};
HTTP Client Extended Key-Value Pair (HTTPc_KEY_VAL_EXT)#

Extended Key-Value Pair Objects can be used with the HTTP Form feature. More specifically, with a multipart type form.

Extended Key-Value Pair Objects are very similar to the Key-Value Pair Objects except that the value pointer is replaced by a hook function that will allow the application to directly copy the value into the HTTP Client buffer.

Listing - HTTPc_KEY_VAL_EXT Structure#
struct  httpc_key_val_ext {
    CPU_CHAR                *KeyPtr;     /* Pointer to Key String.                 */
    CPU_INT16U               KeyLen;     /* Length of Key String.                  */
    HTTPc_KEY_VAL_EXT_HOOK   OnValTx;    /* Pointer to Hook Function to set Value. */
    CPU_INT32U               ValLen;     /* Length of the Value String.            */
};
HTTP Client Multipart File (HTTPc_MULTIPART_FILE)#

Multipart File Objects can be used with the HTTP Form feature. More specifically, with a multipart type form.

The structure's object allows it to store a pointer to the strings file name, the HTTP Content Type of the file and the hook function pointer that will be used to read the file into the transmit buffer.

Listing - HTTPc_MULTIPART_FILE Structure#
struct  http_multipart_file {
    CPU_CHAR                   *NamePtr;        /* Pointer to Name of form field.                    */
    CPU_INT16U                  NameLen;        /* Length of the form field's name.                  */
    CPU_CHAR                   *FileNamePtr;    /* Pointer to File Name String.                      */
    CPU_INT16U                  FileNameLen;    /* Length of the File Name String.                   */
    CPU_INT32U                  FileLen;        /* File Length.                                      */
    HTTP_CONTENT_TYPE           ContentType;    /* HTTP Content Type of the file.                    */
    HTTPc_MULTIPART_FILE_HOOK   OnFileTx;       /* Pointer to Hook Function to Transmit file's data. */
};
HTTP Client Header (HTTPc_HDR)#

This structure is used by the application to add Header Fields to an HTTP request.

Listing - HTTP_HDR Structure#
struct  httpc_hdr {
    HTTP_HDR_FIELD      HdrField;    /* HTTP Header Field Type.        */
    CPU_CHAR           *ValPtr;      /* Pointer to Header Field Value. */
    CPU_INT16U          ValLen;      /* Length of the value.           */
};

HTTP Client Connection Object Setup#

Connection's Parameters#

HTTP Client provides the function HTTPc_ConnSetParam() to configure parameters related to the HTTP Client Connection object . The function takes as argument the type of parameter and the pointer to the parameter. The below parameter's types are available:

Table - HTTPc Connection's Parameters#

Parameter Type

Description

HTTPc_PARAM_TYPE_SERVER_PORT

Sets a specific port for the remote HTTP server.By default, the port is set to 80 or to 443 when the Secure module is used.

HTTPc_PARAM_TYPE_PERSISTENT

Enables the persistent connection mode.The HTTP client will not close the connection at the end of a transaction and will also notify the HTTP server to do the same. The HTTP server must also support persistent connections for the mode to be functional. Enabling this feature on the HTTP client is no guaranty that a persistent connection with the server will be established but that a best effort will be made.

HTTPc_PARAM_TYPE_CONNECT_TIMEOUT

Sets the Connect Timeout of the connection.This value represents the time allowed for the connection process to complete.

HTTPc_PARAM_TYPE_INACTIVITY_TIMEOUT

Sets the Inactivity Timeout of the connectionThis value represents the time of inactivity allowed on a connection before it is automatically closed.

HTTPc_PARAM_TYPE_SECURE_COMMON_NAME

Sets the Common Name linked to the HTTP server's SSL Certificate.The Common Name is associated with the SSL Certificate of a web server. The host + domain name is commonly used for the Common Name, ex: "www.example.com " or "example.com ". When the HTTP client attempts a secure connection, by default the host name will be used as Common Name. You can use this parameter to specify a different Common Name for a secure connection.

HTTPc_PARAM_TYPE_SECURE_TRUST_CALLBACK

Sets the callback function to notify the application when a secure connection with a server was made to ensure that server certificate is trustworthy.This parameter is mandatory if a secure connection to the server is desired. Therefore, when this parameter is set up, the connection with the server will be automatically a secure one.

HTTPc_PARAM_TYPE_CONN_CONNECT_CALLBACK

Sets the callback function to notify the application when a connection attempt with the HTTP server is completed.This parameter is mandatory when the HTTPc_CFG_MODE_ASYNC_TASK_EN configuration is enabled and when the function HTTPc_ConnOpen() is called in the none-blocking mode.

HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK

Sets the callback function to notify the application when an HTTP connection was closed.A connection can be closed at any moment by the HTTP server, or by the client when an unexpected error occurred. A connection will also be closed after any transaction when the persistent mode is not enabled.This parameter is mandatory when the HTTPc_CFG_MODE_ASYNC_TASK_EN configuration is enabled.

Example#
Listing - HTTP Client Connection#
CPU_BOOLEAN  HTTPcApp_ConnPrepare (HTTPc_CONN_OBJ  *p_conn)
{
  CPU_BOOLEAN  persistent;
  RTOS_ERR     err;

                            /* ---------------- INIT NEW CONNECTION --------------- */
    HTTPc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* ----------------- SET SERVER PORT ------------------ */
    port = 8080;
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_SERVER_PORT,
                      &port,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                            /* --------------- SET PERSISTENT MODE ---------------- */
    persistent = DEF_YES;
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_PERSISTENT,
                      &persistent,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                            /* --------------- SET CONN'S CALLBACKS --------------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CONNECT_CALLBACK,
                      &AppHTTPc_ConnConnectCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                      &AppHTTPc_ConnCloseCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

  return (DEF_OK);
}

HTTP Client Request Object Setup#

Request's Parameters#

HTTP Client provides the function HTTPc_ReqSetParam() to configure parameters related to the HTTP Request. The function takes as argument the type of parameter and the pointer to the parameter. The below parameter's types are available:

Table - HTTPc Request's Parameters#

Parameter Type

Description

HTTPc_PARAM_TYPE_REQ_QUERY_STR_TBL

Sets the Request's Query String Table.

HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK

Sets the Request's Query String Hook Function.

HTTPc_PARAM_TYPE_REQ_HDR_TBL

Sets the Request's Header Table.

HTTPc_PARAM_TYPE_REQ_HDR_HOOK

Sets the Request's Header Hook Function.

HTTPc_PARAM_TYPE_REQ_FORM_TBL

Sets the Request's Form Table.

HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE

Sets the Request's Body Content Type.

HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN

Sets the Request's Body Content Length.

HTTPc_PARAM_TYPE_REQ_BODY_HOOK

Sets the Request's Hook Function for retrieving the data body.

HTTPc_PARAM_TYPE_RESP_HDR_HOOK

Sets the Response's Header Hook Function.

HTTPc_PARAM_TYPE_RESP_BODY_HOOK

Sets the Response's Hook Function for the Body received.

HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK

Sets the HTTP Transaction Complete Callback to notify the application that the Transaction is completed.This parameter is mandatory when the HTTPc_CFG_MODE_ASYNC_TASK_EN configuration is enabled.

HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK

Sets the HTTP Transaction Error Callback to notify the application when an unexpected error occurred with an HTTP Transaction.This parameter is mandatory when the HTTPc_CFG_MODE_ASYNC_TASK_EN configuration is enabled.

Example#
Listing - Request Setup Example Code#
CPU_BOOLEAN  HTTPcApp_ReqPrepare (HTTPc_CONN_OBJ  *p_req)
{
  RTOS_ERR  err;

                                    /* ------------- INIT NEW REQUEST ------------ */
    HTTPc_ReqClr(p_req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* -------- SET STRING QUERY PARAMETERS ------ */
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK,
                     &HTTPcApp_ReqQueryStrHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                                /* ------ SET REQUEST ADDITIONAL HEADERS ----- */
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_HDR_HOOK,
                     &HTTPcApp_ReqHdrHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* -------- SET REQ/RESP HOOK FUNCTIONS ------ */
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_RESP_HDR_HOOK,
                     &HTTPcApp_RespHdrHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_RESP_BODY_HOOK,
                     &HTTPcApp_RespBodyHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                                /* ----- SET REQ/RESP CALLBACK FUNCTIONS ----- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK,
                     &HTTPcApp_TransDoneCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                     &HTTPcApp_TransErrCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

  return (DEF_OK);
}

HTTP Client Open Secure Connection with SSL-TSL#

Requirements#

To open a secure HTTP connection with the HTTP Client module, the below requirements are needed:

  • A network security module (such as Mocana - NanoSSL) is required.

  • The Micrium OS Network core stack needs to be configured accordingly (see section Transport Layer Security Configuration ).

  • The client side needs to install certificate authorities to authenticate the identity of each public key certificate sent by servers.

Refer to section Secure Sockets (TLS or SSL) for an example on how to use the Network module to open a secure socket for a client application.

HTTP Client parameters#

HTTP Client offers two parameters to configure the secure connection:

  • HTTPc_PARAM_TYPE_SECURE_COMMON_NAME

  • HTTPc_PARAM_TYPE_SECURE_TRUST_CALLBACK

The first parameter is optional and gives the option to specify the Common Name linked to the Secure Certificate to identify it with the certificate authorities. If this parameter is not set the server host name will be used.

The second parameter is mandatory to open a secure connection and therefore when this parameter is specified, the HTTP Client stack will assume that the connection to open must be secured. The parameter specified the hook function used by the secure module to ask the upper application to verify and validate the public key certificate send by the server.

Both parameters must be configured with the function HTTPc_ConnSetParam().

Example#
Listing - Secure Connection Example Code#
HTTPc_CONN_OBJ  conn;

/*
*********************************************************************************************************
*                                       HTTPcEx_ConnPrepare()
*
* Description : Example function to prepare the HTTPc Connection.
*
* Argument(s) : p_conn  Pointer to HTTPc Connection object to set up.
*
* Return(s)   : DEF_YES, if Connection preparation successful.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ConnPrepare (HTTPc_CONN_OBJ  *p_conn)
{
  RTOS_ERR  err;

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ----------- SET CONN'S CALLBACKS ---------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CONNECT_CALLBACK,
                      &HTTPcEx_ConnConnectCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                      &HTTPcEx_ConnCloseCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ----- SET CONNECTION SECURE PARAMETERS ---- */
  HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_SECURE_TRUST_CALLBACK
                      &HTTPcEx_ConnSecureCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                       HTTPcEx_ConnCloseCallback()
*
* Description : Example Callback Function to validate public key from server.
*
* Argument(s) : p_cert_dn   Pointer to certificate distinguished name.
*
*               reason      Reason why certificate is not trusted:
*                               NET_SOCK_SECURE_UNTRUSTED_BY_CA
*                               NET_SOCK_SECURE_EXPIRE_DATE
*                               NET_SOCK_SECURE_INVALID_DATE
*                               NET_SOCK_SECURE_SELF_SIGNED
*
* Return(s)   : DEF_YES, if certificate is valid.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ConnCloseCallback (void                              *p_cert_dn,
                                        NET_SOCK_SECURE_UNTRUSTED_REASON   reason)
{
    return (DEF_YES);
}

HTTP Client Add Additional Header fields to an HTTP Request#

HTTP Client supports the addition of header fields to an HTTP request:

  • The preprocessor macro HTTPc_CFG_HDR_TX_EN must be set to DEF_ENABLED.

  • HTTPc_HDR objects must be used to set up headed fields to add.

  • Two methods are offered by the HTTP Client stack to add header fields:

    • Passing a header fields table to to the HTTP Client stack.

    • Using a hook function that will ask the application for each header field to add to the request.

Some header fields are taken care of by the HTTP Client module and must therefore not be added by the application :

  • Host

  • Content-Type

  • Content-Length

  • Transfer-Encoding

  • Connection

Using a Header Fields Table#

With the first option, before sending the HTTP request, the application can prepare a table of HTTPc_HDR objects that the HTTP Client will include in the request. The API function HTTPc_ReqSetParam() must be used with the parameter type HTTPc_PARAM_TYPE_REQ_HDR_TBL to pass out the table to the HTTP Client stack.

Listing - Adding Header Fields with a Table Example Code#
#define  HTTPc_CFG_HDR_NBR_MAX       10
#define  HTTPc_CFG_HDR_VAL_LEN_MAX  100

HTTPc_HDR      HTTPc_ReqHdrTbl[HTTPc_CFG_HDR_NBR_MAX];
CPU_CHAR       HTTPc_ReqHdrValTbl[HTTPc_CFG_HDR_NBR_MAX][HTTPc_CFG_HDR_VAL_LEN_MAX];

/*
*********************************************************************************************************
*                                           HTTPc_ReqPrepareHdr()
*
* Description : Prepare the HTTP header table.
*
* Argument(s) : p_tbl    Variable that will received the pointer to header table.
*
* Return(s)   : Number of Header fields in the table.
*********************************************************************************************************
*/
static  CPU_INT08U  HTTPc_ReqPrepareHdr (HTTPc_KEY_VAL  **p_tbl)
{
  HTTPc_HDR  *p_hdr;

    p_hdr           = &HTTPc_ReqHdrTbl[0];
    p_hdr->ValPtr   = &HTTPc_ReqHdrValTbl[0][0];
    p_hdr->HdrField =  HTTP_HDR_FIELD_ACCEPT;

    Str_Copy_N(p_hdr->ValPtr, "text/*", HTTPc_CFG_HDR_VAL_LEN_MAX);

    p_hdr->ValLen = Str_Len_N(p_hdr->ValPtr, HTTPc_CFG_HDR_VAL_LEN_MAX);

   *p_ext_hdr_tbl = &HTTPc_ReqHdrTbl[0];

    return (1);
}

/*
*********************************************************************************************************
*                                           HTTPc_ReqPrepare()
*
* Description : Prepare the HTTP request to send.
*
* Argument(s) : p_req    Pointer to the HTTP Request object to configure.
*
* Return(s)   : DEF_OK,   if the request was configured successfully.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqPrepare (HTTPc_REQ_OBJ  *p_req)
{
    HTTPc_PARAM_TBL   tbl_obj;
    HTTPc_HDR        *p_hdr_tbl;
    CPU_INT08U        hdr_nbr;
    HTTPc_ERR         err;

                                                                /* ---------- SET HEADER FIELDS DATA --------- */
    hdr_nbr = HTTPc_ReqPrepareHdr(&p_hdr_tbl);
    if (hdr_nbr <= 0) {
        return (DEF_FAIL);
    }

                                                                /* -------- SET HEADER FIELDS PARAMETER ------ */
    tbl_obj.EntryNbr = hdr_nbr;
    tbl_obj.TblPtr   = (void *)p_hdr_tbl;
    HTTPc_ReqSetParam(p_req, HTTPc_PARAM_TYPE_REQ_HDR_TBL, &tbl_obj, &err);
    if (err != HTTPc_ERR_NONE) {
        return (DEF_FAIL);
    }

    ...  /* TODO other operations on request if necessary. */

    return (DEF_OK);
Using a Hook Function#

The Second option is to set up a hook function. The hook function will be called by the HTTP Client core to add a Header Field to the request. The hook function will be called until it return DEF_YES to notified the HTTP Client stack that all the fields have been added. The API function HTTPc_ReqSetParam() must be used with the parameter type HTTPc_PARAM_TYPE_REQ_HDR_HOOK to pass out hook function pointer to the HTTP Client stack.

Listing - Adding Header Fields with a Hook Example Code#
#define  HTTPc_CFG_HDR_NBR_MAX       10
#define  HTTPc_CFG_HDR_VAL_LEN_MAX  100

CPU_INT08U     HTTPc_ReqHdrIx;
HTTPc_HDR      HTTPc_ReqHdrTbl[HTTPc_CFG_HDR_NBR_MAX];
CPU_CHAR       HTTPc_ReqHdrValTbl[HTTPc_CFG_HDR_NBR_MAX][HTTPc_CFG_HDR_VAL_LEN_MAX];

/*
*********************************************************************************************************
*                                           HTTPc_ReqPrepare()
*
* Description : Prepare the HTTP request to send.
*
* Argument(s) : p_req    Pointer to the HTTP Request object to configure.
*
* Return(s)   : DEF_OK,   if the request was configured successfully.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqPrepare (HTTPc_REQ_OBJ  *p_req)
{
    HTTPc_ERR       err;

                                                                /* -------- SET STRING QUERY PARAMETER ------- */
    HTTPc_ReqSetParam(p_req, HTTPc_PARAM_TYPE_REQ_HDR_HOOK, &HTTPc_ReqHdrHook, &err);
    if (err != HTTPc_ERR_NONE) {
        return (DEF_FAIL);
    }

    p_req->UserDataPtr = (void *)&HTTPc_ReqHdrIx;

    ...  /* TODO other operations on request if necessary. */

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                           HTTPc_ReqHdrHook()
*
* Description : Hook function to retrieve the header fields to include in the HTTP request.
*
* Argument(s) : p_conn   Pointer to the HTTP Connection object.
*
*               p_req    Pointer to the HTTP Request object.
*
*               p_hdr    Variable that will received the pointer to the Header field object.
*
* Return(s)   : DEF_YES, if all the header fields to include have been passed.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqHdrHook (HTTPc_CONN_OBJ   *p_conn,
                                       HTTPc_REQ_OBJ    *p_req,
                                       HTTPc_HDR       **p_hdr)
{
    HTTPc_HDR       *p_hdr_item;
    CPU_INT08U       index;

    index = *(CPU_INT08U)p_req->UserDataPtr;

    switch(index) {
        case 0:
             p_hdr_item           = &HTTPc_ReqHdrTbl[0];
             p_hdr_item->ValPtr   = &HTTPc_ReqHdrValTbl[0][0];
             p_hdr_item->HdrField =  HTTP_HDR_FIELD_ACCEPT;
            (void)Str_Copy_N(p_hdr_item->ValPtr, "text/*", HTTPc_CFG_HDR_VAL_LEN_MAX);
             p_hdr_item->ValLen = Str_Len_N(p_hdr_item->ValPtr, HTTPc_CFG_HDR_VAL_LEN_MAX);
            *p_hdr = p_hdr_item;
             index++;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_NO);

        case 1:
             p_hdr_item           = &HTTPc_ReqHdrTbl[1];
             p_hdr_item->ValPtr   = &HTTPc_ReqHdrValTbl[1][0];
             p_hdr_item->HdrField =  HTTP_HDR_FIELD_DATE;
            (void)Str_Copy_N(p_hdr_item->ValPtr, "Thursday, 21-Aug-14 02:15:31 GMT", HTTPc_CFG_HDR_VAL_LEN_MAX);
             p_hdr_item->ValLen = Str_Len_N(p_hdr_item->ValPtr, HTTPc_CFG_HDR_VAL_LEN_MAX);
            *p_hd = p_hdr_item;
             index = 0;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_YES);

        default:
            *p_hdr = DEF_NULL;
             index = 0;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_YES);
    }
}

HTTP Client Request's Body Standard Transfer#

The POST and PUT methods can be used to transfer data to the HTTP server. The data is included in the body part of the HTTP request.

Additional HTTP header fields must be included when a body is present. The content type of the data must be specified with the Content-Type header field, and for a standard transfer, the length of the data must be specified with the Content-Length header field. Those headers will be added automatically by the HTTP Client stack after the required parameters are configured.

The function HTTPc_ReqSetParam() must be used to configure the additional parameters necessary when data must be transmitted the standard way. Three parameters must be set up :

  • HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE

  • HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN

  • HTTPc_PARAM_TYPE_REQ_BODY_HOOK

The first parameter sets the content-type of the data, the second the length of the data, and the third sets the hook function that will be used by the HTTP Client module to retrieve the data.

Example#

Since all the API function are in blocking mode in the example below, the HTTPc objects and string can be allocated on the application stack without problems.

The example below implements a function to send a PUT request :

  • An HTTP Connection is set up

  • An HTTP request is configured with the three body parameters: content-type, content-length, and hook function.

  • The Connection is open.

  • The request is sent.

Listing - Standard Body Transfer Function Example Code#
CPU_CHAR  index_html[1024];

/*
*********************************************************************************************************
*                                      HTTPcEx_ReqSendPUT_Standard()
*
* Description : Example function to send a HTTP PUT request with the standard transfer (not chunked).
*
* Argument(s) : none.
*
* Return(s)   : DEF_YES, is request sent successfully.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendPUT_Standard (void)
{
    HTTPc_CONN_OBJ     conn;
    HTTPc_REQ_OBJ      req;
    HTTPc_RESP_OBJ     resp;
    CPU_CHAR           buf[512];
    HTTPc_FLAGS        flags;
    HTTP_CONTENT_TYPE  content_type;
    CPU_SIZE_T         content_len;
    CPU_SIZE_T         str_len;
    CPU_BOOLEAN        result;
    RTOS_ERR           err;

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(&conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ---------- SET CONNECTION PARAM ----------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(&conn,
                        HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       &HTTPcEx_ConnCloseCallback,
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* -------------- INIT NEW REQUEST------------ */
    HTTPc_ReqClr(&req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ------- SET REQUEST BODY PARAMETERS ------- */
    content_type = HTTP_CONTENT_TYPE_HTML;
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE,
                      &content_type,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    content_len = STATIC_INDEX_HTML_LEN;
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN,
                      &content_len,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_HOOK,
                      &HTTPcEx_ReqBodyHook,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* -------- SET TRANSACTION CALLBACKS -------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                      &HTTPcEx_TransErrCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- OPEN CONNECTION ------------- */
    str_len = Str_Len("www.example.com");
    flags   = HTTPc_FLAG_NONE;
    result  = HTTPc_ConnOpen(&conn,
                             &buf,
                              APP_HTTPc_CFG_BUF_SIZE,
                             "www.example.com",
                              str_len,
                              flags,
                             &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

                                                                /* ------------ SEND HTTP REQUEST ------------ */
    str_len = Str_Len("/index.html");
    flags   = HTTPc_FLAG_NONE;
    result  = HTTPc_ReqSend(&conn,
                            &req,
                            &resp,
                             HTTP_METHOD_PUT,
                            "/index.html",
                             str_len,
                             flags,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

The example below is a first implementation of the hook function to retrieve the request body data from the application. In this example, the data is retrieved from an existing application buffer (index_html) and the hook function only set up the data pointer and the length of the data.

Listing - Request Body Hook Function Example Code #1#
/*
*********************************************************************************************************
*                                      HTTPcEx_ReqBodyHook()
*
* Description : Example Hook function to transfer data in request with the standard transfer.
*
*               This function let you the choice to set the pointer to the application data (with p_data)
*               that the HTTP Client stack will take care of transferring; or to directly copy the data
*               in the HTTP transmit buffer (with p_buf).
*
* Argument(s) : p_conn      Pointer to the current HTTPc Connection object.
*
*               p_req       Pointer to the current HTTPc Request object.
*
*               p_data      Pointer to the application data.
*
*               p_buf       Pointer to the HTTP buffer.
*
*               buf_len     Buffer's length.
*
*               p_data_len  Variable that will return the data length passed by the application.
*
* Return(s)   : DEF_YES, if all data as been passed.
*               DEF_NO,  if data still remaining to be passed by the application.
*********************************************************************************************************
*/

static  CPU_BOOLEAN  HTTPcEx_ReqBodyHook (HTTPc_CONN_OBJ   *p_conn,
                                          HTTPc_REQ_OBJ    *p_req,
                                          void            **p_data,
                                          CPU_CHAR         *p_buf,
                                          CPU_INT16U        buf_len,
                                          CPU_INT16U       *p_data_len)
{
  CPU_INT16U  size;
    CPU_INT16U  str_len;

   *p_data = &index_html[0];

    str_len = Str_Len(&index_html[0]);
    Str_Copy_N(p_buf, &index_html[0], str_len);

   *p_data_len = str_len;

    return (DEF_YES);
}

The example below is a second implementation of the hook function to retrieve the request body data from the application. In this example, the data is retrieved from a file that is accessed using Micrium OS File System and directly copied into the HTTP transmit buffer.

Listing - Request Body Hook Function Example Code #2#
static  CPU_BOOLEAN  HTTPcEx_ReqBodyHook (HTTPc_CONN_OBJ   *p_conn,
                                          HTTPc_REQ_OBJ    *p_req,
                                          void            **p_data,
                                          CPU_CHAR         *p_buf,
                                          CPU_INT16U        buf_len,
                                          CPU_INT16U       *p_data_len)
{
    CPU_BOOLEAN     finish;
    CPU_SIZE_T      file_rem;
    CPU_SIZE_T      size;
    CPU_SIZE_T      size_rd;
    FS_FILE_HANDLE  file_handle;
    FS_ENTRY_INFO   file_info;
    FS_FILE_SIZE    file_pos;
    RTOS_ERR        err;

   *p_data = DEF_NULL;

    file_handle = FSFile_Open(FSWrkDir_NullHandle,
                             "ram0/index.html",
                              FS_FILE_ACCESS_MODE_RD,
                             &err);
    if (err.Code != RTOS_ERR_NONE) {
        // TODO: Handle error.

       *p_data_len = 0u;
        finish     = DEF_YES;
        return (finish);
    }

    FSFile_Query(file_handle,
                &file_info,
                &err);
    if (err.Code != RTOS_ERR_NONE) {
        // TODO: Handle error.

       *p_data_len = 0;
        finish     = DEF_YES;
        goto exit_close;
    }

    file_pos = FSFile_PosGet(file_handle,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        // TODO: Handle error.

       *p_data_len = 0;
        finish     = DEF_YES;
        goto exit_close;
    }

    file_rem = file_info.Size - file_pos;
    if (file_rem <= 0) {
       *p_data_len = 0;
        finish     = DEF_YES;
        goto exit_close;
    }

    size = DEF_MIN(file_rem, buf_len);

    size_rd = FSFile_Rd(file_handle,
                        p_buf,
                        size,
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        // TODO: Handle error.

       *p_data_len = 0u;
        finish     = DEF_YES;
        goto exit_close;
    }

   *p_data_len = size_rd;
    finish     = DEF_NO;

exit_close:
    FSFile_Close(file_handle, &err);
    if (err.Code != RTOS_ERR_NONE) {
        // TODO: Handle error.
    }

    return (finish);
}

HTTP Client Chunked Transfer Encoding#

The POST and PUT methods can be used to transfer data to the HTTP server. The data is included in the body part of the HTTP request.

When the size of the data to transmit is unknown before starting the HTTP request, the Chunked Transfer Encoding can be used. It will split the data into chunks of known size and will send an empty chunk to advertise the end of the data.

Additional HTTP header fields must be included when a body is present. The content type of the data must be specified with the Content-Type header field and for the Chunked Transfer encoding the Transfer-Encoding header field must be specified. Those headers will be added automatically by the HTTP Client module after the required parameters are configured. For more details, refer to section Chunked Transfer Encoding.

The function HTTPc_ReqSetParam() must be used to configure the additional parameters necessary when data is transmitted in chunks. Three parameters must be set up :

  • HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE

  • HTTPc_PARAM_TYPE_REQ_BODY_CHUNK

  • HTTPc_PARAM_TYPE_REQ_BODY_HOOK

The first parameter is to set the content-type of the data, the second is a Boolean to enable the Chunked Transfer Encoding and the third is to set the hook function that will be used by the HTTP Client module to retrieve the data.

Example#

Since all the API functions are in blocking mode in the example below, the HTTPc objects and string can be allocated on the application stack without problems.

The example below implements a function to send a PUT request :

  • An HTTP Connection is configured.

  • An HTTP request is configured with the three body parameters: content-type, chunk enabled and hook function.

  • The Connection is open.

  • The request is sent.

Listing - Chunked Transfer Encoding Example Code#
/*
*********************************************************************************************************
*                                      HTTPcEx_ReqSendPUT_Chunked()
*
* Description : Example function to send a HTTP PUT request with the Chunked Transfer Encoding.
*
* Argument(s) : none.
*
* Return(s)   : DEF_YES, is request sent successfully.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendPUT_Chunked (void)
{
    CPU_BOOLEAN        result;
    CPU_BOOLEAN        chunk_en;
    CPU_CHAR           buf[512];
    CPU_SIZE_T         str_len;
    HTTPc_CONN_OBJ     conn;
    HTTPc_REQ_OBJ      req;
    HTTPc_RESP_OBJ     resp;
    HTTP_CONTENT_TYPE  content_type;
    RTOS_ERR           err;

                                                                   /* ---------- INIT NEW CONNECTION --------- */
    HTTPc_ConnClr(&conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                   /* -------- SET CONNECTION PARAM ---------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(&conn,
                        HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       &HTTPcEx_ConnCloseCallback,
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                   /* ----- SET REQUEST BODY PARAMETERS ------ */
    content_type = HTTP_CONTENT_TYPE_JSON;
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE,
                      &content_type,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    chunk_en = DEF_YES;
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_CHUNK,
                      &chunk_en,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_REQ_BODY_HOOK,
                      &HTTPcEx_ReqBodyHook,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                      &HTTPcEx_TransErrCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                   /* ----------- OPEN CONNECTION ------------ */
    str_len = Str_Len("www.example.com");
    result  = HTTPc_ConnOpen(&conn,
                             &buf,
                              APP_HTTPc_CFG_BUF_SIZE,
                             "www.example.com",
                              str_len,
                              HTTPc_FLAG_NONE,
                             &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

                                                                   /* ---------- SEND HTTP REQUEST ----------- */
    str_len = Str_Len("/");
    result  = HTTPc_ReqSend(&conn,
                            &req,
                            &resp,
                             HTTP_METHOD_PUT,
                            "/",
                             str_len,
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

For examples on the On Request Body hook function, refer to section Request's Body Standard Transfer since the hook function is used regardless of the transfer mode.

HTTP Client Query String#

A Query String is a set of Key-Value pairs or single values added at the end of the request's URL after a question mark character "?". Each field of the Query is separated by the "&" character. For more details, see section Query String .

The HTTP Client module supports the addition of a Query String to an HTTP request:

  1. The preprocessor macro HTTPc_CFG_QUERY_STR_EN must be set to DEF_ENABLED.

  2. HTTPc_KEY_VAL type's objects must be used to setup a Query String field. When the field is a single string and not a pair of key-value, the pointer to the value can be left blank and only the pointer to the key will be used.

  3. Two methods are offered by the HTTP Client module to add Query String:

  • Passing a Key-Value Pairs' Table to the HTTP Client stack.

  • Using a hook function that will ask the application for each Key-Value Pair.

Using a Key-Value Pairs' Table#

For the first option, before sending the HTTP request, the application can prepare a table of HTTPc_KEY_VAL objects that the HTTP Client will include in the Query String. The API function HTTPc_ReqSetParam() must be used with the parameter type HTTPc_PARAM_TYPE_REQ_QUERY_STR_TBL to pass out the table to the HTTP Client stack.

Listing - Adding a Query String with Table Example Code#
#define  HTTPc_CFG_QUERY_STR_NBR_MAX       10
#define  HTTPc_CFG_QUERY_STR_KEY_LEN_MAX   50
#define  HTTPc_CFG_QUERY_STR_VAL_LEN_MAX  100

HTTPc_KEY_VAL  HTTPc_ReqQueryStrTbl[HTTPc_CFG_QUERY_STR_NBR_MAX];
CPU_CHAR       HTTPc_ReqQueryStrKeyTbl[HTTPc_CFG_QUERY_STR_NBR_MAX][HTTPc_CFG_QUERY_STR_KEY_LEN_MAX];
CPU_CHAR       HTTPc_ReqQueryStrValTbl[HTTPc_CFG_QUERY_STR_NBR_MAX][HTTPc_CFG_QUERY_STR_VAL_LEN_MAX];

/*
*********************************************************************************************************
*                                         HTTPc_ReqPrepareQueryStr()
*
* Description : Prepare the Query String Table.
*
* Argument(s) : p_tbl    Variable that will received the pointer to the Query String table.
*
* Return(s)   : Number of fields in the Query String table.
*********************************************************************************************************
*/
static  CPU_INT08U  HTTPc_ReqPrepareQueryStr (HTTPc_KEY_VAL  **p_tbl)
{
    HTTPc_KEY_VAL  *p_key_val;

                                                                /* ------------- SET FIRST QUERY ------------- */
    p_key_val         = &HTTPc_ReqQueryStrTbl[0];
    p_key_val->KeyPtr = &HTTPc_ReqQueryStrKeyTbl[0][0];
    p_key_val->ValPtr = &HTTPc_ReqQueryStrValTbl[0][0];

   (void)Str_Copy_N(p_key_val->KeyPtr, "name", HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
   (void)Str_Copy_N(p_key_val->ValPtr, "Jonh", HTTPc_CFG_QUERY_STR_VAL_LEN_MAX);

    p_key_val->KeyLen = Str_Len_N(p_key_val->KeyPtr, HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
    p_key_val->ValLen = Str_Len_N(p_key_val->ValPtr, HTTPc_CFG_QUERY_STR_VAL_LEN_MAX);

                                                                /* ------------ SET SECOND QUERY ------------- */
    p_key_val         = &HTTPc_ReqQueryStrTbl[1];
    p_key_val->KeyPtr = &HTTPc_ReqQueryStrKeyTbl[1][0];
    p_key_val->ValPtr =  DEF_NULL;

   (void)Str_Copy_N(p_key_val->KeyPtr, "active", HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);

    p_key_val->KeyLen = Str_Len_N(p_key_val->KeyPtr, HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);

   *p_tbl = &HTTPc_ReqQueryStrTbl[0];

    return (2);
}

/*
*********************************************************************************************************
*                                           HTTPc_ReqPrepare()
*
* Description : Prepare the HTTP request to send.
*
* Argument(s) : p_req    Pointer to the HTTP Request object to configure.
*
* Return(s)   : DEF_OK,   if the request was configured successfully.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqPrepare (HTTPc_REQ_OBJ  *p_req)
{
    HTTPc_PARAM_TBL   tbl_obj;
    HTTPc_KEY_VAL    *p_query_str_tbl;
    CPU_INT08U        query_nbr;
    RTOS_ERR          err;

                                                                /* -------- SET STRING QUERY DATA ------------ */
    query_nbr = HTTPc_ReqPrepareQueryStr(&p_query_str_tbl);
    if (query_nbr <= 0) {
        return (DEF_FAIL);
    }

                                                                /* ------ SET STRING QUERY PARAMETERS -------- */
    tbl_obj.EntryNbr = query_nbr;
    tbl_obj.TblPtr   = (void *)p_query_str_tbl;
    HTTPc_ReqSetParam(p_req, HTTPc_PARAM_TYPE_REQ_QUERY_STR_TBL, &tbl_obj, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    ...  /* TODO other operations on request if necessary. */

    return (DEF_OK);
}
Using a Hook Function#

The Second option is to set up a hook function. The hook function will be called by the HTTP Client module to add a field to the Query String. The hook function will be called until it returns DEF_YES to notified the HTTP Client module that all the fields have been added. The API function HTTPc_ReqSetParam() must be used with the parameter type HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK to pass out hook function pointer to the HTTP Client module.

Listing - Adding Query String with a Hook Example Code#
#define  HTTPc_CFG_QUERY_STR_NBR_MAX       10
#define  HTTPc_CFG_QUERY_STR_KEY_LEN_MAX   50
#define  HTTPc_CFG_QUERY_STR_VAL_LEN_MAX  100

CPU_INT08U     HTTPc_ReqQueryStrIx;
HTTPc_KEY_VAL  HTTPc_ReqQueryStrTbl[HTTPc_CFG_QUERY_STR_NBR_MAX];
CPU_CHAR       HTTPc_ReqQueryStrKeyTbl[HTTPc_CFG_QUERY_STR_NBR_MAX][HTTPc_CFG_QUERY_STR_KEY_LEN_MAX];
CPU_CHAR       HTTPc_ReqQueryStrValTbl[HTTPc_CFG_QUERY_STR_NBR_MAX][HTTPc_CFG_QUERY_STR_VAL_LEN_MAX];

/*
*********************************************************************************************************
*                                           HTTPc_ReqPrepare()
*
* Description : Prepare the HTTP request to send.
*
* Argument(s) : p_req    Pointer to the HTTP Request object to configure.
*
* Return(s)   : DEF_OK,   if the request was configured successfully.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqPrepare (HTTPc_REQ_OBJ  *p_req)
{
    RTOS_ERR  err;

                                                                /* -------- SET STRING QUERY PARAMETER ------- */
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK,
                     &HTTPc_ReqQueryStrHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    p_req->UserDataPtr = (void *)&HTTPc_ReqQueryStrIx;

    ...  /* TODO other operations on request if necessary. */

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                         HTTPc_ReqQueryStrHook()
*
* Description : Hook function to retrieve the data of the Query String.
*
* Argument(s) : p_conn     Pointer to the HTTP Connection object.
*
*               p_req      Pointer to the HTTP Request object.
*
*               p_key_val  Variable that will receive the pointer to the Key-Val object.
*
* Return(s)   : DEF_YES, if all the fields of the Query String have been passed.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/
static  CPU_BOOLEAN  HTTPc_ReqQueryStrHook (HTTPc_CONN_OBJ   *p_conn,
                                            HTTPc_REQ_OBJ    *p_req,
                                            HTTPc_KEY_VAL   **p_key_val)
{
    HTTPc_KEY_VAL  *p_kvp;
    CPU_INT08U      index;

    index = *(CPU_INT08U)p_req->UserDataPtr;

    switch(index) {
        case 0:
             p_kvp         = &HTTPc_ReqQueryStrTbl[0];
             p_kvp->KeyPtr = &HTTPc_ReqQueryStrKeyTbl[0][0];
             p_kvp->ValPtr = &HTTPc_ReqQueryStrValTbl[0][0];
            (void)Str_Copy_N(p_kvp->KeyPtr, "name", HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
            (void)Str_Copy_N(p_kvp->ValPtr, "Jonh", HTTPc_CFG_QUERY_STR_VAL_LEN_MAX);
             p_kvp->KeyLen = Str_Len_N(p_kvp->KeyPtr, HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
             p_kvp->ValLen = Str_Len_N(p_kvp->ValPtr, HTTPc_CFG_QUERY_STR_VAL_LEN_MAX);
            *p_key_val = p_kvp;
             index++;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_NO);

        case 1:
             p_kvp         = &HTTPc_ReqQueryStrTbl[1];
             p_kvp->KeyPtr = &HTTPc_ReqQueryStrKeyTbl[1][0];
             p_kvp->ValPtr =  DEF_NULL;
            (void)Str_Copy_N(p_kvp->KeyPtr, "active", HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
             p_kvp->KeyLen = Str_Len_N(p_kvp->KeyPtr, HTTPc_CFG_QUERY_STR_KEY_LEN_MAX);
            *p_key_val = p_kvp;
             index = 0;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_YES);

        default:
            *p_key_val = DEF_NULL;
             index = 0;
            *(CPU_INT08U)p_req->UserDataPtr = index;
             return (DEF_YES);
    }
}

HTTP Client Form Submission#

HTTP Client offers several structures and API functions to simplify the formatting and transmission of Forms for the development of an HTTP Client application.

For more details on HTTP Forms, see section Form .

Form Field Types#

HTTP Client offers three types of form field. Each type is associated with a structure that the application can used to create objects:

  • Key-Value Pair : Simple pair of key and value strings. Can be used with the Application type form and the Multipart type form.

  • Extended Key-Value Pair : Key-Value pair where the string value is not specified but a hook function is to allow the HTTP Client stack to retrieve the value when the form is formatted. Can be used with the Multipart type form only.

  • Multipart File : Use to upload file to an HTTP server inside a Multipart type form. Can be used with the Multipart type form only.

Form API#

The application should incorporate all the form fields into a table using the API functions offered below :

  • HTTPc_FormAddKeyVal() to add a simple Key-Value pair object to a form table.

  • HTTPc_FormAddKeyValExt() to add a Extended Key-Value pair object to a form table.

  • HTTPc_FormAddFile() to add a Multipart File object to a form table.

Once the form fields' table is created, two possibilities are offered.

The first option is valid only if the table contains simple Key-Value pairs and consists of formatting the form on the application side with one of the API functions below:

  • HTTPc_FormAppFmt() to format the table into an Application-type form.

  • HTTPc_FormMultipartFmt() to format the table into a Multipart-type form.

Afterwards the application can transmit the formatted form like any other body types.

The second option is to pass the form fields table to the HTTP Client module so that the formatting can be done internally by the HTTP Client core. This option allows you to have a different form field type in the table. The HTTP Client module will take care of calling the hook functions to recover data from the application for extended Key-Value pair object and Multipart File objects.

The form fields table can be passed to the HTTP Client module by calling the HTTPc_ReqSetParam() function will the parameter type HTTPc_PARAM_TYPE_REQ_FORM_TBL and the macro configuration HTTPc_CFG_FORM_EN must be set to DEF_ENABLED.

Examples#
Example #1: Application Type Form with the form formatting on the application side#
Listing - Form Submission Example Code #1#
#define  HTTP_SERVER_HOSTNAME             "www.example.com"
#define  HTTPc_EX_CFG_CONN_BUF_SIZE         512
#define  HTTPc_EX_CFG_FORM_FIELD_NBR_MAX     10
#define  HTTPc_EX_CFG_FORM_BUF_SIZE        4096
#define  HTTPc_EX_CFG_KEY_LEN_MAX            50
#define  HTTPc_EX_CFG_VAL_LEN_MAX           100

HTTPc_CONN_OBJ        HTTPcEx_Conn;
CPU_CHAR              HTTPcEx_ConnBuf[HTTPc_CFG_CONN_BUF_SIZE];
HTTPc_REQ_OBJ         HTTPcEx_Req;
HTTPc_RESP_OBJ        HTTPcEx_Resp;
HTTPc_FORM_TBL_FIELD  HTTPcEx_ReqFormTbl[HTTPc_EX_CFG_FORM_FIELD_NBR_MAX];
CPU_CHAR              HTTPcEx_FormBufTbl[HTTPc_EX_CFG_FORM_BUF_SIZE];
HTTPc_KEY_VAL         HTTPcEx_KeyVal_Tbl[HTTPc_EX_CFG_FORM_FIELD_NBR_MAX];
CPU_CHAR              HTTPcEx_KeyVal_KeyTbl[HTTPc_EX_CFG_FORM_FIELD_NBR_MAX][HTTPc_EX_CFG_KEY_LEN_MAX];
CPU_CHAR              HTTPcEx_KeyVal_ValTbl[HTTPc_EX_CFG_FORM_FIELD_NBR_MAX][HTTPc_EX_CFG_VAL_LEN_MAX];

/*
*********************************************************************************************************
*                                      HTTPcEx_ReqSendFormApp()
*
* Description : Example function to send an HTTP POST request containing an Application type form.
*
* Argument(s) : None.
*
* Return(s)   : DEF_OK,   if the HTTP transaction was successful.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendFormApp (void)
{
    HTTPc_CONN_OBJ        *p_conn;
    HTTPc_REQ_OBJ         *p_req;
    HTTPc_RESP_OBJ        *p_resp;
    CPU_CHAR              *p_buf;
    CPU_CHAR              *p_data;
    HTTPc_FORM_TBL_FIELD  *p_form_tbl;
    CPU_INT08U             form_nbr;
    CPU_INT16U             content_len;
    RTOS_ERR               err;

    p_conn = &HTTPcEx_ConnTbl[0];
    p_req  = &HTTPcEx_ReqTbl[0];
    p_resp = &HTTPcEx_RespTbl[0];
    p_buf  = &HTTPcEx_BufTbl[0][0];

                                                                /* ------------- SET FORM TO SEND ------------ */
    form_nbr = HTTPcEx_ReqPrepareFormApp(&p_form_tbl);
    if (form_nbr <= 0) {
        return (DEF_FAIL);
    }

    p_data      = &HTTPcEx_FormBufTbl[0];
    content_len = HTTPc_FormMultipartFmt(p_data,
                                         APP_HTTPc_CFG_FORM_BUF_SIZE,
                                         p_form_tbl,
                                         form_nbr,
                                        &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                                /* ----------- SET CONN'S CALLBACKS ---------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                      &HTTPcEx_ConnCloseCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- INIT NEW REQUEST ------------ */
    HTTPc_ReqClr(p_req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ------- SET REQUEST BODY PARAMETERS ------- */
    content_type = HTTP_CONTENT_TYPE_MULTIPART_FORM;
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE,
                     &content_type,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN,
                     &content_len,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_REQ_BODY_HOOK,
                     &HTTPcEx_ReqBodyHook,
                     &err);
    if (err != HTTPc_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ----------- SET REQ'S CALLBACKS ----------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                     &HTTPcEx_TransErrCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                               /* ------------- OPEN CONNECTION ------------- */
    str_len = Str_Len(HTTP_SERVER_HOSTNAME);
    result  = HTTPc_ConnOpen(p_conn,
                             p_buf,
                             HTTPc_EX_CFG_BUF_SIZE,
                             HTTP_SERVER_HOSTNAME,
                             str_len,
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("Connection to server succeeded.\n\r");
    } else {
        printf("Connection to server failed.\n\r");
    }

                                                                /* ------------ SEND HTTP REQUEST ------------ */
    str_len = Str_Len("/form");
    result  = HTTPc_ReqSend(p_conn,
                            p_req,
                            p_resp,
                            HTTP_METHOD_POST,
                            "/form",
                            str_len,
                            HTTPc_FLAG_NONE,
                           &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("%s\n\r", p_resp->ReasonPhrasePtr);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                       HTTPcEx_ReqPrepareFormApp()
*
* Description : Example function to prepare the form table for an application type form
*
* Argument(s) : p_form_tbl  Variable that will received the pointer to the form table.
*
* Return(s)   : Number of fields in the table.
*********************************************************************************************************
*/

static  CPU_INT08U  HTTPcEx_ReqPrepareFormApp (HTTPc_FORM_TBL_FIELD  **p_form_tbl)
{
    HTTPc_FORM_TBL_FIELD  *p_tbl;
    HTTPc_KEY_VAL         *p_kvp;
    RTOS_ERR               err;

    p_tbl = &HTTPcEx_ReqFormTbl[0];
                                                                /* ---------- ADD FIRST FORM FIELD ----------- */
    p_kvp          = &HTTPcEx_KeyVal_Tbl[0];
    p_kvp->KeyPtr  = &HTTPcEx_KeyVal_KeyTbl[0][0];
    p_kvp->ValPtr  = &HTTPcEx_KeyVal_ValTbl[0][0];
    p_kvp->KeyLen  = Str_Len("Name");
    p_kvp->ValLen  = Str_Len("John Smith");
   (void)Str_Copy_N(p_kvp->KeyPtr, "Name",       p_kvp->KeyLen);
   (void)Str_Copy_N(p_kvp->ValPtr, "Jonh Smith", p_kvp->ValLen);
    HTTPc_FormAddKeyVal(p_tbl, p_kvp, &err);

                                                                /* ---------- ADD SECOND FORM FIELD ---------- */
    p_tbl++;
    p_kvp++;
    p_kvp->KeyPtr    = &HTTPcEx_KeyVal_KeyTbl[1][0];
    p_kvp->ValPtr    = &HTTPcEx_KeyVal_ValTbl[1][0];
    p_kvp->KeyLen = Str_Len("Book");
    p_kvp->ValLen = Str_Len("Implementing IPv6 Second Edition");
   (void)Str_Copy_N(p_kvp->KeyPtr, "Book",                             p_kvp->KeyLen);
   (void)Str_Copy_N(p_kvp->ValPtr, "Implementing IPv6 Second Edition", p_kvp->ValLen);
    HTTPc_FormAddKeyVal(p_tbl, p_kvp, &err);

   *p_form_tbl = &HTTPcEx_ReqFormTbl[0];

    return (2);
}

HTTP Client Persistent Connection#

Persistent Connection allows you to send multiple HTTP requests one after another on the same opened connection before closing it. For more details, refer to section Persistent Connection .

Example#

In this example, two HTTP requests are queued on an HTTP Connection before the client closes the connection.

The function HTTPc_ReqSend() is called with the flag HTTPc_FLAG_REQ_NO_BLOCK, so the function is not blocking and will return before the transaction completes. Therefore the On Transaction Complete hook must be set to retrieve the HTTP response.

Listing - Persistent Connection Example Code#
#define  HTTP_SERVER_HOSTNAME                            "www.example.com"

#define  HTTPc_EX_CFG_CONN_NBR_MAX                        5u
#define  HTTPc_EX_CFG_REQ_NBR_MAX                         5u
#define  HTTPc_EX_CFG_BUF_SIZE                          512u

HTTPc_CONN_OBJ  HTTPcEx_ConnTbl[HTTPc_EX_CFG_CONN_NBR_MAX];
HTTPc_REQ_OBJ   HTTPcEx_ReqTbl[HTTPc_EX_CFG_REQ_NBR_MAX];
HTTPc_RESP_OBJ  HTTPcEx_RespTbl[HTTPc_EX_CFG_REQ_NBR_MAX];
CPU_CHAR        HTTPcEx_BufTbl[HTTPc_EX_CFG_CONN_NBR_MAX][HTTPc_EX_CFG_BUF_SIZE ];

CPU_BOOLEAN     close_conn = DEF_NO;
CPU_BOOLEAN     req1_done = DEF_NO;
CPU_BOOLEAN     req2_done = DEF_NO;

/*
*********************************************************************************************************
*                                         HTTPcEx_ReqSendGET()
*
* Description : Example function to Send Requests on persistent connection.
*
* Argument(s) : None.
*
* Return(s)   : DEF_YES, if request successfully sent.
*               DEF_NO,  otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendGET (void)
{
    HTTPc_CONN_OBJ  *p_conn;
    HTTPc_REQ_OBJ   *p_req1;
    HTTPc_REQ_OBJ   *p_req2;
    HTTPc_RESP_OBJ  *p_resp1;
    HTTPc_RESP_OBJ  *p_resp2;
    CPU_CHAR        *p_buf;
    CPU_BOOLEAN      persistent;
    CPU_BOOLEAN      result;
    RTOS_ERR         err;

    p_conn  = &HTTPcEx_ConnTbl[0];
    p_buf   = &HTTPcEx_BufTbl[0][0];
    p_req1  = &HTTPcEx_ReqTbl[0];
    p_req2  = &HTTPcEx_ReqTbl[1];
    p_resp1 = &HTTPcEx_RespTbl[0];
    p_resp2 = &HTTPcEx_RespTbl[1];

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ----------- SET PERSISTENT MODE ----------- */
    persistent = DEF_YES;
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_PERSISTENT,
                      &persistent,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ---------- SET CONN'S CALLBACKS ----------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                      &HTTPcEx_ConnCloseCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------ INIT NEW REQUESTS ------------ */
    HTTPc_ReqClr(p_req1, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqClr(p_req2, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ---- SET REQ/RESP CALLBACK FUNCTIONS ------ */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(p_req1,
                      HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK,
                     &HTTPcEx_TransDoneCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req2,
                      HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK,
                     &HTTPcEx_TransDoneCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req1,
                      HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                     &HTTPcEx_TransErrCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req2,
                      HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                     &HTTPcEx_TransErrCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------ OPEN CONNECTION -------------- */
    str_len = Str_Len(HTTP_SERVER_HOSTNAME);
    result  = HTTPc_ConnOpen(p_conn,
                             p_buf,
                             HTTPc_EX_CFG_BUF_SIZE,
                             HTTP_SERVER_HOSTNAME,
                             str_len,
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("Connection to server succeeded.\n\r");
    } else {
        printf("Connection to server failed.\n\r");
    }

                                                                /* ----------- SEND HTTP REQUESTS ------------ */
    str_len = Str_Len("//");
    result  = HTTPc_ReqSend(p_conn,
                            p_req1,
                            p_resp1,
                            HTTP_METHOD_GET,
                            "//",
                            str_len,
                            HTTPc_FLAG_REQ_NO_BLOCK,
                           &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    (void)HTTPc_ReqSend(p_conn,
                        p_req2,
                        p_resp2,
                        HTTP_METHOD_GET,
                       "//",
                        str_len,
                        HTTPc_FLAG_REQ_NO_BLOCK,
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    while (close_conn == DEF_NO)
    {
        /* Do OS delay. */
    };

                                                                /* --------- CLOSE HTTP CONNECTION ----------- */
    close_conn = DEF_NO;
    HTTPc_ConnClose(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                         HTTPcEx_TransDoneCallback()
*
* Description : Example callback function to be notified when an HTTP transaction is completed.
*
* Argument(s) : p_conn_obj   Pointer to current HTTPc Connection object.
*
*               p_req_obj    Pointer to current HTTPc Request object.
*
*               p_resp_obj   Pointer to current HTTPc Response object.
*
*               status       Status of the HTTP transaction:
*                                DEF_OK,   transaction succeeded.
*                                DEF_FAIL, transaction failed.
*
* Return(s)   : None.
*********************************************************************************************************
*/

void  HTTPcEx_TransDoneCallback (HTTPc_CONN_OBJ  *p_conn_obj,
                                 HTTPc_REQ_OBJ   *p_req_obj,
                                 HTTPc_RESP_OBJ  *p_resp_obj,
                                 CPU_BOOLEAN      status)
{
    HTTPc_REQ_OBJ      *p_req1;
    HTTPc_REQ_OBJ      *p_req2;

    p_req1  = &HTTPcEx_ReqTbl[0];
    p_req2  = &HTTPcEx_ReqTbl[1];

    if (p_req_obj == p_req1) {
        if (status == DEF_OK) {
            printf("Transaction #1: %s\n\r", p_resp_obj->ReasonPhrasePtr);
        } else {
            printf("Transaction #1 failed\n\r");
        }
        req1_done = DEF_YES;
     } else if (p_req_obj == p_req2) {
        if (status == DEF_OK) {
            printf("Transaction #2: %s\n\r", p_resp_obj->ReasonPhrasePtr);
        } else {
            printf("Transaction #2 failed\n\r");
        }
        req2_done = DEF_YES;
    } else {
        printf("Unexpected error.\n\r");
    }

    close_conn = req1_done & req2_done;
}

HTTP Client Retrieve HTTP Response Data#

The HTTPc Response object will be filled by the HTTP Client stack with the fields below received in the HTTP response:

  • The Server HTTP version

  • Status Code

  • Reason phrase

  • Content type (if body present)

  • Content Length (if body present)

If the function HTTPc_ReqSend() was called in the blocking mode and the function returned with no errors, then the HTTPc Response object can be read by the application after the function call. Otherwise, the application must wait until the On Transaction Complete function is called by the HTTP Client stack to read the HTTPc Response object.

Two hook functions allow the application to retrieve more data from the HTTP response :

The first hook allows the application to retrieve header fields contained in the HTTP response. If the hook function is set via the function HTTPc_ReqSetParam() with the parameter type HTTPc_PARAM_TYPE_RESP_HDR_HOOK, the hook will be called by the HTTP Client module for each header field parsed and recognized by the stack. The application as therefore the liberty to copy the data received on its side inside the hook function.

The second hook allows the application to retrieve the data contained in the HTTP response body. If the hook function is set via the function HTTPc_ReqSetParam() with the parameter type HTTPc_PARAM_TYPE_RESP_BODY_HOOK, the hook will be called by the HTTP Client module for each piece of data received until all is received.

Examples#
Blocking Mode#

In the first example below, the function HTTPc_ReqSend() is called in blocking mode. Therefore, the HTTPc Response object can be read just after the function call.

Listing - Retrieve HTTP Response Data Example Code #1#
#define  HTTP_SERVER_HOSTNAME   "www.example.com"
#define  HTTPc_EX_CFG_BUF_SIZE   1024

/*
*********************************************************************************************************
*                                         HTTPcEx_ReqSendGET()
*
* Description : Example function to send a GET request and retrieve HTTP response.
*
* Argument(s) : None.
*
* Return(s)   : DEF_OK,   if HTTP transaction was successful.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendGET (void)
{
    HTTPc_CONN_OBJ   conn;
    HTTPc_REQ_OBJ    req;
    HTTPc_RESP_OBJ   resp;
    CPU_CHAR         buf[HTTPc_EX_CFG_BUF_SIZE];
    HTTPc_FLAGS      flags;
    CPU_SIZE_T       str_len;
    CPU_BOOLEAN      result;
    RTOS_ERR         err;

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(&conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ----------- SET CONN'S CALLBACKS ---------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(&conn,
                        HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       &HTTPcEx_ConnCloseCallback,
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- INIT NEW REQUEST ------------ */
    HTTPc_ReqClr(&req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* --------- SET TRANS HOOK FUNCTIONS -------- */
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_RESP_HDR_HOOK,
                      &HTTPcEx_RespHdrHook,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_RESP_BODY_HOOK,
                      &HTTPcEx_RespBodyHook,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ------ SET TRANS CALLBACK FUNCTIONS ------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(&req,
                       HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                      &HTTPcEx_TransErrCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- OPEN CONNECTION ------------- */
    str_len = Str_Len(HTTP_SERVER_HOSTNAME);
    result  = HTTPc_ConnOpen(&conn,
                             &buf,
                              HTTPc_EX_CFG_BUF_SIZE,
                              HTTP_SERVER_HOSTNAME,
                              str_len,
                              HTTPc_FLAG_NONE,
                             &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("Connection to server succeeded.\n\r");
    } else {
        printf("Connection to server failed.\n\r");
    }

                                                                /* ------------ SEND HTTP REQUEST ------------ */
    str_len = Str_Len("/");
    result  = HTTPc_ReqSend(&conn,
                            &req,
                            &resp,
                             HTTP_METHOD_GET,
                            "/",
                             str_len,
                             HTTPc_FLAG_NONE,
                           &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("%s\n\r", resp.ReasonPhrasePtr);
    }

    return (DEF_OK);
}
No-Blocking Mode#

In this second example, the function HTTPc_ReqSend() is called in non-blocking mode. Therefore, the HTTPc Response object can be read once the On Transaction Complete function is called.

Listing - Retrieve HTTP Response Data Example Code #2#
#define  HTTP_SERVER_HOSTNAME   "www.example.com"
#define  HTTPc_EX_CFG_BUF_SIZE   1024

HTTPc_CONN_OBJ  HTTPcEx_Conn;
HTTPc_REQ_OBJ   HTTPcEx_Req;
HTTPc_RESP_OBJ  HTTPcEx_Resp;
CPU_CHAR        HTTPcEx_ConnBuf[HTTPc_EX_CFG_BUF_SIZE];

/*
*********************************************************************************************************
*                                         HTTPcEx_ReqSendGET()
*
* Description : Example function to send a GET request and retrieve HTTP response.
*
* Argument(s) : None.
*
* Return(s)   : DEF_OK,   if HTTP transaction was successful.
*               DEF_FAIL, otherwise.
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcEx_ReqSendGET (void)
{
    HTTPc_CONN_OBJ   *p_conn;
    HTTPc_REQ_OBJ    *p_req;
    HTTPc_RESP_OBJ   *p_resp;
    CPU_CHAR         *p_buf;
    CPU_SIZE_T        str_len;
    CPU_BOOLEAN       result;
    HTTPc_ERR         err;

    p_conn = &HTTPcEx_Conn;
    p_req  = &HTTPcEx_Req;
    p_resp = &HTTPcEx_Resp;
    p_buf  = &HTTPcEx_ConnBuf[0];

                                                                /* ------------ INIT NEW CONNECTION ---------- */
    HTTPc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ----------- SET CONN'S CALLBACKS ---------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ConnSetParam(p_conn,
                       HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                      &HTTPcEx_ConnCloseCallback,
                      &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- INIT NEW REQUEST ------------ */
    HTTPc_ReqClr(p_req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* --------- SET TRANS HOOK FUNCTIONS -------- */
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_RESP_HDR_HOOK,
                     &HTTPcEx_RespHdrHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_RESP_BODY_HOOK,
                     &HTTPcEx_RespBodyHook,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

                                                                /* ------ SET TRANS CALLBACK FUNCTIONS ------- */
#if (HTTPc_CFG_MODE_ASYNC_TASK_EN == DEF_ENABLED)
    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK,
                     &HTTPcEx_TransDoneCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    HTTPc_ReqSetParam(p_req,
                      HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK,
                     &HTTPcEx_TransErrCallback,
                     &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif

                                                                /* ------------- OPEN CONNECTION ------------- */
    str_len = Str_Len(HTTP_SERVER_HOSTNAME);
    result  = HTTPc_ConnOpen(p_conn,
                             p_buf,
                             HTTPc_EX_CFG_BUF_SIZE,
                             HTTP_SERVER_HOSTNAME,
                             str_len,
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    if (result == DEF_OK) {
        printf("Connection to server succeeded.\n\r");
    } else {
        printf("Connection to server failed.\n\r");
    }

                                                                /* ------------ SEND HTTP REQUEST ------------ */
    str_len = Str_Len("/");
    result  = HTTPc_ReqSend(p_conn,
                            p_req,
                            p_resp,
                            HTTP_METHOD_GET,
                           "/",
                            str_len,
                            HTTPc_FLAG_REQ_NO_BLOCK,
                           &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                      HTTPcEx_TransDoneCallback()
*
* Description : Example callback function to be notified when an HTTP transaction was completed.
*
*               Once this callback is called, the HTTPc Response object is ready to be read by the application
*               if no error occurred.
*
* Argument(s) : p_conn     Pointer to current HTTPc Connection object.
*
*               p_req      Pointer to current HTTPc Request object.
*
*               p_resp     Pointer to current HTTPc Response object.
*
*               status     DEF_OK, if transaction was complete successfully.
*                          DEF_NO, otherwise.
*
* Return(s)   : None.
*********************************************************************************************************
*/

static  void  HTTPcEx_TransDoneCallback(HTTPc_CONN_OBJ    *p_conn,
                                        HTTPc_REQ_OBJ     *p_req,
                                        HTTPc_RESP_OBJ    *p_resp,
                                        CPU_BOOLEAN        status)
{
    if (status == DEF_OK) {
        printf("Transaction response status: %s\n\r", p_resp->ReasonPhrasePtr);
    } else {
        printf("Transaction failed\n\r");
    }
}
Response Header and Body Hook Functions#

The example code below is an implementation of the On Response Header hook function and the On Response Body hook function.

Listing - Response Hook Functions Example Code#
#define  HTTPc_EX_CFG_HDR_VAL_BUF_LEN  100

CPU_CHAR  HTTPcEx_HdrValBuf[HTTPc_EX_CFG_HDR_VAL_BUF_LEN];

/*
*********************************************************************************************************
*                                         HTTPcEx_RespHdrHook()
*
* Description : Example hook function to retrieve Header Fields received in the HTTP response.
*
* Argument(s) : p_conn      Pointer to current HTTPc Connection object.
*
*               p_req       Pointer to current HTTPc Request object.
*
*               hdr_field   Header field type received.
*
*               p_hdr_val   Pointer to Header field value string received.
*
*               val_len     Length of value string.
*
* Return(s)   : None.
*********************************************************************************************************
*/

static  void  HTTPcEx_RespHdrHook(HTTPc_CONN_OBJ    *p_conn,
                                  HTTPc_REQ_OBJ     *p_req,
                                  HTTP_HDR_FIELD     hdr_field,
                                  CPU_CHAR          *p_hdr_val,
                                  CPU_INT16U         val_len)
{
    CPU_CHAR    *p_buf;
    CPU_INT16U   len;

    p_buf = &HTTPcEx_HdrValBuf[0];

    switch (hdr_field) {
        case HTTP_HDR_FIELD_DATE:
        case HTTP_HDR_FIELD_SERVER:
             len = DEF_MIN((HTTPc_EX_CFG_HDR_VAL_BUF_LEN - 1), val_len);
             Mem_Copy(p_buf, p_hdr_val, len);
             p_buf += len;
            *p_buf  = '\0';
             break;

        default:
             break;
    }
}

/*
*********************************************************************************************************
*                                         HTTPcEx_RespBodyHook()
*
* Description : Example hook function to retrieve body data.
*
*               In this example, a html file is received and is copied into a file.
*
* Argument(s) : p_conn        Pointer to current HTTPc Connection object.
*
*               p_req         Pointer to current HTTPc Request object.
*
*               content_type  Content type of the body received in the HTTP response.
*
*               p_data        Pointer to the data piece received.
*
*               data_len      Length of data piece received.
*
*               last_chunk    DEF_YES, if this represent the last piece of the data body to receive.
*                             DEF_NO,  if data still remains to be received.
*
* Return(s)   : None.
*********************************************************************************************************
*/

static  void  HTTPcEx_RespBodyHook (HTTPc_CONN_OBJ     *p_conn,
                                    HTTPc_REQ_OBJ      *p_req,
                                    HTTP_CONTENT_TYPE   content_type,
                                    void               *p_data,
                                    CPU_INT32U          data_len,
                                    CPU_BOOLEAN         last_chunk)
{
    FS_FILE_HANDLE  file_handle;
    CPU_SIZE_T      size_wr;
    CPU_SIZE_T      size_wr_tot;
    CPU_BOOLEAN     is_open;
    RTOS_ERR        err;

    file_handle = FSFile_Open(FSWrkDir_NullHandle,
                             "ram0/index.html",
                             (FS_FILE_ACCESS_MODE_WR | FS_FILE_ACCESS_MODE_CREATE | FS_FILE_ACCESS_MODE_APPEND),
                             &err);
    if (err.Code != RTOS_ERR_NONE) {
        return;
    }

    switch (content_type) {
        case HTTP_CONTENT_TYPE_HTML:
             if (p_data != DEF_NULL) {
                 size_wr     = 0u;
                 size_wr_tot = 0u;
                 while (size_wr < data_len) {
                     size_wr = FSFile_Wr(file_handle,
                                         p_data,
                                         data_len,
                                        &err);
                     if (err.Code != RTOS_ERR_NONE) {
                         return;
                     }
                     size_wr_tot += size_wr;
                 }
             }
             break;

        case HTTP_CONTENT_TYPE_OCTET_STREAM:
        case HTTP_CONTENT_TYPE_PDF:
        case HTTP_CONTENT_TYPE_ZIP:
        case HTTP_CONTENT_TYPE_GIF:
        case HTTP_CONTENT_TYPE_JPEG:
        case HTTP_CONTENT_TYPE_PNG:
        case HTTP_CONTENT_TYPE_JS:
        case HTTP_CONTENT_TYPE_PLAIN:
        case HTTP_CONTENT_TYPE_CSS:
        case HTTP_CONTENT_TYPE_JSON:
        default:
             break;
    }

    FSFile_Close(file_handle, &err);
}

HTTP Client WebSocket#

WebSocket allows to create a full duplex communication channel over a single TCP/HTTP connection and enables streams of structured messages. It use simple and efficient headers to describe those messages which offer a better solution when it come to send small data at higher rate. For more details, refer to section WebSocket .

This section regroups topics to help developing a custom WebSocket application with the HTTP Client module. Examples are include in many sub-sections.

HTTP Client Upgrading an HTTP Connection#

Because it uses many HTTP functionalities for opening handshake, the WebSocket protocol has been integrated has part of Micrium OS HTTP Client module. Furthermore, all the HTTP Client request features, such as query string, are available during the opening handshake request. Here are the usual steps to upgrade a HTTP connection to WebSocket:

  1. First, create a HTTPc Connection to the desired server using HTTPc_ConnOpen(). If successful, it will return a valid HTTPc_CONN_OBJ object that can be used for the next request.

  2. Before sending an Upgrade Request to the server, an HTTPc_WEBSOCK_OBJ object may be configured by using HTTPc_WebSockSetParam() function. Note that WebSocket Message Reception is done through hook functions that are configured in HTTPc_WEBSOCK_OBJ object passed during the WebSocket Upgrade.

  3. Because the WebSocket opening handshake is essentially a specific HTTP Request with specific headers, HTTPc_WebSockUpgrade() function is available to simplify the connection upgrade. It will automatically set the mandatory headers and validates the response from the server. Because it also uses a HTTPc_REQ_OBJ object, you can use all the features available during a normal HTTP Request.

  4. Finally, when the opening handshake is successful, the connection that has been established in step 1 has now upgraded to WebSocket and is no more related to HTTP. At this point, HTTPc_WebSockSend() can be used for WebSocket Message Transmission and the WebSocket Message Reception will be processed through the RX hook configured in HTTPc_WEBSOCK_OBJ.

Related Hooks#

Name

Description

Object

Parameter Type

On Open

Called when a WebSocket Upgrade is successful.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_OPEN

On Close

Called when a connection that has been successfully upgraded close.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_CLOSE

Example#

The following example simply shows how to upgrade an HTTP connection to Websocket. As you can see below, it will first open an HTTP connection to the remote server and then upgrade it. Note that there's no Message Reception mechanism configured in this example.

Listing - Upgrading an HTTP Connection#
#include <rtos/net/include/http_client.h>

/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/
#define  HTTPc_EXAMPLE_URI              "server.example.com"
#define  HTTPc_EXAMPLE_RESSOURCE        "/echo"
#define  HTTPc_EXAMPLE_CONN_BUF_LEN     1024

/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

static  HTTPc_CONN_OBJ         HTTPcExample_Conn;
static  CPU_CHAR               HTTPcExample_ConnBuf[HTTPc_EXAMPLE_CONN_BUF_LEN];
static  HTTPc_REQ_OBJ          HTTPcExample_Req;
static  HTTPc_RESP_OBJ         HTTPcExample_Resp;
static  HTTPc_WEBSOCK_OBJ      HTTPcExample_WebSock;

/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static void  HTTPcExample_ConnOnClose    (HTTPc_CONN_OBJ              *p_conn,
                                          HTTPc_CONN_CLOSE_STATUS      close_status,
                                          HTTPc_ERR                    err);

static void  HTTPcExample_WebSockOnOpen  (HTTPc_CONN_OBJ              *p_conn);

static void  HTTPcExample_WebSockOnClose (HTTPc_CONN_OBJ              *p_conn,
                                          HTTPc_WEBSOCK_CLOSE_CODE     close_code,
                                          HTTPc_WEBSOCK_CLOSE_REASON  *p_reason) ;

/*
*********************************************************************************************************
*                                               EXAMPLE
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcExample_OpenWebSocket (void)
{
    CPU_BOOLEAN  result;
    RTOS_ERR     err;
                                                            /* ----------- INIT NEW CONNECTION & REQUEST ----- */
                                                            /* Always Clear the object.                        */
    HTTPc_ConnClr(&HTTPcExample_Conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_ReqClr(&HTTPcExample_Req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_WebSockClr(&HTTPcExample_WebSock, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                            /* ------------- SET ON CONNECTION CLOSE --------- */
                                                            /* This callback is always required.               */
    HTTPc_ConnSetParam(        &HTTPcExample_Conn,
                                HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       (void *) HTTPcExample_ConnOnClose,
                               &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                            /* ----------------- OPEN CONNECTION ------------- */
    result = HTTPc_ConnOpen(&HTTPcExample_Conn,
                             HTTPcExample_ConnBuf,
                             HTTPc_EXAMPLE_CONN_BUF_LEN,
                             HTTPc_EXAMPLE_URI,
                             sizeof(HTTPc_EXAMPLE_URI),
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                            /* --------------- SET WEBSOCK ON OPEN ----------- */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_OPEN,
                          (void *) HTTPcExample_WebSockOnOpen,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                            /* --------------- SET WEBSOCK ON CLOSE ---------- */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_CLOSE,
                          (void *) HTTPcExample_WebSockOnClose,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                            /* ------- UPGRADE HTTP CONNECTION TO WEBSOCKET -- */
    result = HTTPc_WebSockUpgrade(&HTTPcExample_Conn,
                                  &HTTPcExample_Req,
                                  &HTTPcExample_Resp,
                                  &HTTPcExample_WebSock,
                                   HTTPc_EXAMPLE_RESSOURCE,
                                   sizeof(HTTPc_EXAMPLE_RESSOURCE),
                                   HTTPc_FLAG_NONE,
                                  &err);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                      CONNECTION ON CLOSE CALLBACK
*********************************************************************************************************
*/

static void  HTTPcExample_ConnOnClose (HTTPc_CONN_OBJ           *p_conn,
                                       HTTPc_CONN_CLOSE_STATUS   close_status,
                                       RTOS_ERR                  err)
{
                                                            /* Called  when a connection closes.               */
}

/*
*********************************************************************************************************
*                                        WEBSOCK ON OPEN CALLBACK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnOpen (HTTPc_CONN_OBJ           *p_conn)
{
                                                            /* Called  when a WebSocket Upgrade is successful. */
}

/*
*********************************************************************************************************
*                                        WEBSOCK ON CLOSE CALLBACK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnClose (HTTPc_CONN_OBJ              *p_conn,
                                          HTTPc_WEBSOCK_CLOSE_CODE     close_code,
                                          HTTPc_WEBSOCK_CLOSE_REASON  *p_reason)
{
                                                            /* Called when a WebSocket Connection has closed.  */
}
HTTP Client Message reception#

In the WebSocket Protocol, data is exchanged using sequences of frame to form WebSocket Messages. The user doesn't need to know how the WebSocket data framing works since the HTTP Client WebSocket module manages it internally. The HTTP Client WebSocket API simplifies the application development by using the concept of message which can be summarized by its Type, Payload Length and Contents.

WebSocket Messages can have 5 different types divided in 2 groups.

Control Message

  • Close

  • Ping

  • Pong

Data Message

  • Text

  • Binary

Control Message#

Control messages are intended to be used for protocol-level signaling. Note that their payload length cannot exceed 125 bytes and they cannot be fragmented (only one frame per message).

Since control messages are protocol related, they are managed directly by the WebSocket Module which provides hook to notify the application.

Message Type

WebSocket Module Behavior

Close

When a Close message is received from the remote server, the WebSocket module will start the closing handshake. Once it's done, successfully or not, it will call the hook On Close

Ping

When a Ping message is received from the remote server, the WebSocket module will reply the correct Pong message. The application won't be notify.

Pong

When a Pong message is received from the remote server, the WebSocket module will simply call the hook On Pong .

Data Messages#

Data messages are intended to transport information. Their length can vary from 0 to 2^64 and can be fragmented. They can be divided in two type.

Message Type

Text

The content must respected UTF-8 standard.

Binary

The content is not restricted.

Note that the HTTP Client WebSocket module doesn't validate UTF-8 and must be done by the user application if necessary.

The reception of any Data Messages are done through hooks that are configured in the HTTPc_WEBSOCK_OBJ and that must be set before the connection upgrade request ( HTTPc_WebSockUpgrade() ).

Name

Description

Object

Parameter Type

On Message Reception Initialization

Called at the beginning of the WebSocket Data Type message reception.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_INIT

On Message RX Data

Called each time a chunk of the message is received is available.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_DATA

On Message RX Complete

Called when the Data message is completely received.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_COMPLETE

Note that only one Data Message is processed at a time.

Data Message Reception Mode#

The hooks described in the previous section can be use in many different ways. However, those can be group in two different mode.

Normal mode#

Normal Mode uses all of the three Data Message Reception hooks. It allow the user to be notify every time a message payload chunk is available with the On Message RX Data hook. Thus, the application can parse a message during its reception without having to copying it all in a buffer.

This mode is useful when the memory footprints is critical and the message length can be long or undefined.

Normal Mode Example

Auto mode#

Auto Mode only use two hooks. During On Message Reception Initialization , it is possible to set a pointer to the buffer where the message payload must be set. If the application do so, the message will be automatically copied to the specified buffer. Once the message is completely received, On Message RX Complete hook will be called and data will be available is the buffer previously set.

This mode is useful for simpler application which the message length received from other endpoint are small and size-limited

Auto Mode Example

HTTP Client Auto Mode Example#

This example shows how to open a WebSocket with Data message Reception hooks configured in Auto Mode.

Listing - HTTP Client Auto Mode#
/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/

#define  HTTPc_EXAMPLE_URI              "server.example.com"
#define  HTTPc_EXAMPLE_RESSOURCE        "/echo"
#define  HTTPc_EXAMPLE_CONN_BUF_LEN     1024
#define  HTTPc_EXAMPLE_MSG_MAX_LEN      512

/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

static  HTTPc_CONN_OBJ         HTTPcExample_Conn;
static  CPU_CHAR               HTTPcExample_ConnBuf[HTTPc_EXAMPLE_CONN_BUF_LEN];
static  HTTPc_REQ_OBJ          HTTPcExample_Req;
static  HTTPc_RESP_OBJ         HTTPcExample_Resp;
static  HTTPc_WEBSOCK_OBJ      HTTPcExample_WebSock;
static  CPU_CHAR               HTTPcExample_RxBuf[HTTPc_EXAMPLE_MSG_MAX_LEN];

/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static void        HTTPcExample_ConnOnClose            (HTTPc_CONN_OBJ            *p_conn,
                                                        HTTPc_CONN_CLOSE_STATUS    close_status,
                                                        HTTPc_ERR                  err);

static void        HTTPcExample_WebSockOnMsgRxInit     (HTTPc_CONN_OBJ            *p_conn,
                                                        HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                                        CPU_INT32U                 msg_len,
                                                        void                     **p_data);

static void        HTTPcExample_WebSockOnMsgRxComplete (HTTPc_CONN_OBJ            *p_conn);

/*
*********************************************************************************************************
*                                               EXAMPLE
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcExample_OpenWebSocket (void)
{
    CPU_BOOLEAN  result;
    RTOS_ERR     err;
                                                       /* ----------- INIT NEW CONNECTION & REQUEST ---------- */
                                                       /* Always Clear the object.                             */
    HTTPc_ConnClr(&HTTPcExample_Conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_ReqClr(&HTTPcExample_Req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_WebSockClr(&HTTPcExample_WebSock, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ------------- SET ON CONNECTION CLOSE -------------- */
                                                       /* This callback is always required.                    */
    HTTPc_ConnSetParam(        &HTTPcExample_Conn,
                                HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       (void *) HTTPcExample_ConnOnClose,
                               &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ----------------- OPEN CONNECTION ------------------ */
    result = HTTPc_ConnOpen(&HTTPcExample_Conn,
                             HTTPcExample_ConnBuf,
                             HTTPc_EXAMPLE_CONN_BUF_LEN,
                             HTTPc_EXAMPLE_URI,
                             sizeof(HTTPc_EXAMPLE_URI),
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ----------- SET WEBSOCK HOOKS/CALLBACKS ------------ */
                                                       /* Set OnMsgRxInit hooks.                               */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_INIT,
                          (void *) HTTPcExample_WebSockOnMsgRxInit,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* Set OnMsgRxComplete hooks.                           */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_COMPLETE,
                          (void *) HTTPcExample_WebSockOnMsgRxComplete,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ------- UPGRADE HTTP CONNECTION TO WEBSOCKET ------- */
    result = HTTPc_WebSockUpgrade(&HTTPcExample_Conn,
                                  &HTTPcExample_Req,
                                  &HTTPcExample_Resp,
                                  &HTTPcExample_WebSock,
                                   HTTPc_EXAMPLE_RESSOURCE,
                                   sizeof(HTTPc_EXAMPLE_RESSOURCE),
                                   HTTPc_FLAG_NONE,
                                  &err);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }
    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                      CONNECTION ON CLOSE CALLBACK
*********************************************************************************************************
*/

static void  HTTPcExample_ConnOnClose (HTTPc_CONN_OBJ           *p_conn,
                                       HTTPc_CONN_CLOSE_STATUS   close_status,
                                       HTTPc_ERR                 err)
{
                                                       /* Called  when a connection close.                     */
}

/*
*********************************************************************************************************
*                                    WEBSOCK ON MSG RX INIT HOOK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnMsgRxInit (HTTPc_CONN_OBJ            *p_conn,
                                              HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                              CPU_INT32U                 msg_len,
                                              void                     **p_data)
{
                                                       /* Validate that we have enough space in the buffer...  */
                                                       /* ...to get all the message.                           */
    if (msg_len <= HTTPc_EXAMPLE_MSG_MAX_LEN) {
        *p_data = HTTPcExample_RxBuf;                  /* Set the pointer where the message data must be set.  */
    }
}

/*
*********************************************************************************************************
*                                   WEBSOCK ON MSG RX COMPLETE HOOK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnMsgRxComplete (HTTPc_CONN_OBJ *p_conn)
{
                                                       /* Once the message is completely received...           */
                                                       /* ...Do Something.                                     */
}
HTTP Client Normal Mode Example#

This example show how to open a WebSocket with Data message Reception hooks configured in Normal Mode.

Listing - HTTP Client Normal Mode#
#include <rtos/net/include/http_client.h>

/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/

#define  HTTPc_EXAMPLE_URI              "server.example.com"
#define  HTTPc_EXAMPLE_RESSOURCE        "/echo"
#define  HTTPc_EXAMPLE_CONN_BUF_LEN     1024
#define  HTTPc_EXAMPLE_MSG_MAX_LEN      512

/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

static  HTTPc_CONN_OBJ         HTTPcExample_Conn;
static  CPU_CHAR               HTTPcExample_ConnBuf[HTTPc_EXAMPLE_CONN_BUF_LEN];
static  HTTPc_REQ_OBJ          HTTPcExample_Req;
static  HTTPc_RESP_OBJ         HTTPcExample_Resp;
static  HTTPc_WEBSOCK_OBJ      HTTPcExample_WebSock;

static  CPU_CHAR               HTTPcExample_RxBuf[HTTPc_EXAMPLE_MSG_MAX_LEN];
static  CPU_INT32U             HTTPcExample_RxMsgLenToGet ;

/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static void        HTTPcExample_ConnOnClose            (HTTPc_CONN_OBJ            *p_conn,
                                                        HTTPc_CONN_CLOSE_STATUS    close_status,
                                                        HTTPc_ERR                  err);

static void        HTTPcExample_WebSockOnMsgRxInit     (HTTPc_CONN_OBJ            *p_conn,
                                                        HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                                        CPU_INT32U                 msg_len,
                                                        void                     **p_data);

static CPU_INT32U  HTTPcExample_WebSockOnMsgRxData     (HTTPc_CONN_OBJ            *p_conn,
                                                        HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                                        void                      *p_data,
                                                        CPU_INT16U                 data_len);

static void        HTTPcExample_WebSockOnMsgRxComplete (HTTPc_CONN_OBJ            *p_conn);

/*
*********************************************************************************************************
*                                               EXAMPLE
*********************************************************************************************************
*/

CPU_BOOLEAN  HTTPcExample_OpenWebSocket (void)
{
    CPU_BOOLEAN  result;
    RTOS_ERR     err;
                                                       /* ----------- INIT NEW CONNECTION & REQUEST ---------- */
                                                       /* Always Clear the object.                             */
    HTTPc_ConnClr(&HTTPcExample_Conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_ReqClr(&HTTPcExample_Req, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
    HTTPc_WebSockClr(&HTTPcExample_WebSock, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ------------- SET ON CONNECTION CLOSE -------------- */
                                                       /* This callback is always required.                    */
    HTTPc_ConnSetParam(        &HTTPcExample_Conn,
                                HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK,
                       (void *) HTTPcExample_ConnOnClose,
                               &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ----------------- OPEN CONNECTION ------------------ */
    result = HTTPc_ConnOpen(&HTTPcExample_Conn,
                             HTTPcExample_ConnBuf,
                             HTTPc_EXAMPLE_CONN_BUF_LEN,
                             HTTPc_EXAMPLE_URI,
                             sizeof(HTTPc_EXAMPLE_URI),
                             HTTPc_FLAG_NONE,
                            &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ----------- SET WEBSOCK HOOKS/CALLBACKS ------------ */
                                                       /* Set OnMsgRxInit hooks.                               */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_INIT,
                          (void *) HTTPcExample_WebSockOnMsgRxInit,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* Set OnMsgRxData hooks.                               */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_DATA,
                          (void *) HTTPcExample_WebSockOnMsgRxData,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* Set OnMsgRxComplete hooks.                           */
    HTTPc_WebSockSetParam(        &HTTPcExample_WebSock,
                                   HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_COMPLETE,
                          (void *) HTTPcExample_WebSockOnMsgRxComplete,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                       /* ------- UPGRADE HTTP CONNECTION TO WEBSOCKET ------- */
    result = HTTPc_WebSockUpgrade(&HTTPcExample_Conn,
                                  &HTTPcExample_Req,
                                  &HTTPcExample_Resp,
                                  &HTTPcExample_WebSock,
                                   HTTPc_EXAMPLE_RESSOURCE,
                                   sizeof(HTTPc_EXAMPLE_RESSOURCE),
                                   HTTPc_FLAG_NONE,
                                  &err);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }
    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                      CONNECTION ON CLOSE CALLBACK
*********************************************************************************************************
*/

static void  HTTPcExample_ConnOnClose (HTTPc_CONN_OBJ           *p_conn,
                                       HTTPc_CONN_CLOSE_STATUS   close_status,
                                       HTTPc_ERR                 err)
{
                                                       /* Called  when a connection close.                     */
}

/*
*********************************************************************************************************
*                                    WEBSOCK ON MSG RX INIT HOOK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnMsgRxInit (HTTPc_CONN_OBJ            *p_conn,
                                              HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                              CPU_INT32U                 msg_len,
                                              void                     **p_data)
{
                                                       /* Validate that we have enough space in the buffer...  */
                                                       /* ...to get all the message.                           */
    if (msg_len <= HTTPc_EXAMPLE_MSG_MAX_LEN) {
        HTTPcExample_RxMsgLenToGet = msg_len;
    } else {
        HTTPcExample_RxMsgLenToGet = 0u;
    }
}

/*
*********************************************************************************************************
*                                    WEBSOCK ON MSG RX DATA HOOK
*********************************************************************************************************
*/

static CPU_INT32U  HTTPcExample_WebSockOnMsgRxData (HTTPc_CONN_OBJ            *p_conn,
                                                    HTTPc_WEBSOCK_MSG_TYPE     msg_type,
                                                    void                      *p_data,
                                                    CPU_INT16U                 data_len)
{
    CPU_INT16U  data_len_used;

    data_len_used = 0u;

    if (HTTPcExample_RxMsgLenToGet != 0u) {
        if (HTTPcExample_RxMsgLenToGet == data_len) {
                                                       /* In this example, wait to have all the message...     */
                                                       /* ...before copying it in the reception buffer.        */
            Mem_Copy(HTTPcExample_RxBuf, p_data, data_len);
            HTTPcExample_RxMsgLenToGet = 0u;
            data_len_used              = data_len;
        }
    }

    return (data_len_used);                            /* Return that number of bytes used.                    */
}

/*
*********************************************************************************************************
*                                   WEBSOCK ON MSG _RX COMLETE HOOK
*********************************************************************************************************
*/

static void  HTTPcExample_WebSockOnMsgRxComplete (HTTPc_CONN_OBJ  *p_conn)
{
                                                       /* Once the message is completely received...           */
                                                       /* ...Do Something.                                     */

}
HTTP Client Sending Message#

The user can send a WebSocket message with HTTPc_WebSockSend() function and a properly initialized HTTPc_WEBSOCK_MSG_OBJ. To set the type, the payload content and length of a message, it is possible to either configure it with HTTPc_WebSockSend() parameters or with hooks configured for each message.

For message transmission, it's possible to send all the message type available :

  • HTTPc_WEBSOCK_MSG_TYPE_TXT

  • HTTPc_WEBSOCK_MSG_TYPE_BIN

  • HTTPc_WEBSOCK_MSG_TYPE_CLOSE

  • HTTPc_WEBSOCK_MSG_TYPE_PING

  • HTTPc_WEBSOCK_MSG_TYPE_PONG

Here a list of the available Transmission hooks.

Name

Description

Object

Parameter Type

On Message TX Initialization

Called when the message is ready to be sent.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_TX_INIT

On Message TX Data

Called to set the internal connection buffer of a data chunk of a message to send.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_TX_DATA

On Message TX Complete

Called when the message is completely transmitted.

HTTPc_WEBSOCK_OBJ

HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_TX_COMPLETE

Transmission Mode#

The hooks described in the previous section can be use in many different ways. However, those can be group in three different mode.

Mode

Buffer used

Message Length

On Message TX Initialization

On Message TX Data

On Message TX Complete

Normal

External data buffer set when HTTPc_WebSockSend() is called.

Defined at the beginning when HTTPc_WebSockSend() is called.

Not Used

Not Used

Optional

Hooks

Internal Connection data buffer is used to construct message to transmit.

Defined either when HTTPc_WebSockSend() is called or with On Message TX Initialization hook.

Optional

Used

Optional

Dynamic

Internal Connection data buffer is used to construct message to transmit.

Defined either when HTTPc_WebSockSend() is called or with On Message TX Initialization hook and must be HTTPc_WEBSOCK_TX_MSG_LEN_NOT_DEFINED.

Optional

Used

Optional

Normal Mode#

Normal mode only uses only HTTPc_WebSockSend() and doesn't require a hook. The application must provide a pointer to the message payload data and its length that will be used during the transmission.

This mode is simple to use and suitable for a non-complex application.

Hook Mode#

Hook mode allows you to use directly the connection buffer to send a message using hooks.

  • The application must provide the length of the message at the beginning either with HTTPc_WebSockSend() or with the On Message TX Initialization hook.

  • Then, On Message TX Data is called and provide the application a pointer to the internal connection buffer and the available length.

  • Once the application has set the buffer, it must return the total number of bytes used in this buffer.

  • On Message TX Data is called until the message is completely sent, thus the length set at the beginning matches the total length sent.

This mode allows you to save memory space by using directly the connection buffer. However, the message length must be known at the beginning.

Dynamic Mode#

Dynamic mode use the message fragmentation mechanism that the WebSocket protocol provides to transfer message. It allows to send a message without knowing the total message and to use directly the connection buffer to construct the message to send, thereby reducing the memory footprints.

To use this mode, two points are important:

  • The length of the message must be set to HTTPc_WEBSOCK_TX_MSG_LEN_NOT_DEFINED. It possible to either set it during HTTPc_WebSockSend() is called or using the On Message TX Initialization hook.

  • Then, On Message TX Data is called and provide the application a pointer to the internal connection buffer and the available length.

  • Each time the On Message TX Data is called, the application must set the buffer and return the numbers of bytes to be sent.

  • To complete the message, 0 value must be returned from this function.

This mode helps saving memory space by using directly the connection buffer to construct messages and allows to start the data transmission without knowing the total message length.

Note that it is not possible to send Control Message (Close, Ping or Pong) in Dynamic Mode. Those messages must be sent either in Hook Mode or Normal Mode.

Non-Blocking Option#

An non-blocking option is available when HTTPc_WebSockSend() is called by using the flag HTTPc_FLAG_WEBSOCK_NO_BLOCK. If used, On Message TX Complete hook must be set. It allows to queue message without having to wait the completion of each message transmission.

HTTP Client Closing a Connection#

WebSockets can be closed properly by sending a Close Message. Close Messages have a special format which the first 2 bytes is the close code defined by the standard. The rest of the data concatenated is usually defined by the user for debug purpose. When the other end receive the close message, it should reply with the exact same message. However, it is possible that endpoints don't agree on the value of the close code, but the connection will be closed when both have received and transmitted a Close Messages.

Closing messages are sent in the same way that other message are sent using HTTPc_WebSockSend() (see Sending Message ). Note that Control message payload length cannot exceed 125 bytes and cannot be sent in Dynamic Mode. Once the closing handshake is done, the WebSocket Module will notify the application if the On Close hook is properly set.

Finally, HTTPc_WebSockFmtCloseMsg() allows the user to properly format a Close Message into a buffer before sending it.

HTTP Client Protocol Recognized Fields#

This section regroups lists of all the HTTP fields recognized by Micrium OS HTTP Client module.

HTTP Versions#

HTTP Version

Micrium Type

0.9

HTTP_PROTOCOL_VER_0_9

1.0

HTTP_PROTOCOL_VER_1_0

1.1

HTTP_PROTOCOL_VER_1_1

HTTP Methods#

HTTP Method

Micrium Type

CONNECT

HTTP_METHOD_CONNECT

DELETE

HTTP_METHOD_DELETE

GET

HTTP_METHOD_GET

HEAD

HTTP_METHOD_HEAD

OPTIONS

HTTP_METHOD_OPTIONS

POST

HTTP_METHOD_POST

PUT

HTTP_METHOD_PUT

TRACE

HTTP_METHOD_TRACE

Those are the methods recognized by the HTTP Server and Client stacks. It doesn't mean that all those methods are supported.

HTTP Header Fields#

Header Field Type

Micrium Type

Content-Type

HTTP_HDR_FIELD_CONTENT_TYPE

Content-Length

HTTP_HDR_FIELD_CONTENT_LEN

Content-Disposition

HTTP_HDR_FILED_CONTENT_DISPOSITION

Host

HTTP_HDR_FIELD_HOST

Location

HTTP_HDR_FIELD_LOCATION

Connection

HTTP_HDR_FIELD_CONN

Transfer-Encoding

HTTP_HDR_FIELD_TRANSFER_ENCODING

Accept

HTTP_HDR_FIELD_ACCEPT

Accept-Charset

HTTP_HDR_FIELD_ACCEPT_CHARSET

Accept-Encoding

HTTP_HDR_FIELD_ACCEPT_ENCODING

Accept-Language

HTTP_HDR_FIELD_ACCEPT_LANGUAGE

Accept-Ranges

HTTP_HDR_FIELD_ACCEPT_RANGES

Age

HTTP_HDR_FIELD_AGE

Allow

HTTP_HDR_FIELD_ALLOW

Authorization

HTTP_HDR_FIELD_AUTHORIZATION

Content-Encoding

HTTP_HDR_FIELD_CONTENT_ENCODING

Content-Language

HTTP_HDR_FIELD_CONTENT_LANGUAGE

Content-Location

HTTP_HDR_FIELD_CONTENT_LOCATION

Content-MD5

HTTP_HDR_FIELD_CONTENT_MD5

Content-Range

HTTP_HDR_FIELD_CONTENT_RANGE

Cookie

HTTP_HDR_FIELD_COOKIE

Cookie2

HTTP_HDR_FIELD_COOKIE2

Date

HTTP_HDR_FIELD_DATE

ETag

HTTP_HDR_FEILD_ETAG

Expect

HTTP_HDR_FIELD_EXPECT

Expires

HTTP_HDR_FIELD_EXPIRES

From

HTTP_HDR_FIELD_FROM

If-Modified-Since

HTTP_HDR_FIELD_IF_MODIFIED_SINCE

If-Match

HTTP_HDR_FIELD_IF_MATCH

If-None-Match

HTTP_HDR_FIELD_IF_NONE_MATCH

If-Range

HTTP_HDR_FIELD_IF_RANGE

If-Unmodified-Since

HTTP_HDR_FIELD_IF_UNMODIFIED_SINCE

Last-Modified

HTTP_HDR_FIELD_LAST_MODIFIED

Range

HTTP_HDR_FIELD_RANGE

Referrer

HTTP_HDR_FIELD_REFERER

Retry-After

HTTP_HDR_FIELD_RETRY_AFTER

Server

HTTP_HDR_FIELD_SERVER

Set-Cookie

HTTP_HDR_FIELD_SET_COOKIE

Set-Cookie2

HTTP_HDR_FIELD_SET_COOKIE2

TE

HTTP_HDR_FIELD_TE

Trailer

HTTP_HDR_FIELD_TRAILER

Upgrade

HTTP_HDR_FIELD_UPGRATE

User-Agent

HTTP_HDR_FIELD_USER_AGENT

Vary

HTTP_HDR_FIELD_VARY

Via

HTTP_HDR_FIELD_VIA

Warning

HTTP_HDR_FIELD_WARNING

WWW-Authenticate

HTTP_HDR_FIELD_WWW_AUTHENTICATE

If a header is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

HTTP Content Types#

MIME Content Type

File Extension

Micrium Type

text/html

.html

HTTP_CONTENT_TYPE_HTML

application/octet-stream

.bin

HTTP_CONTENT_TYPE_OCTET_STREAM

application/pdf

.pdf

HTTP_CONTENT_TYPE_PDF

application/zip

.zip

HTTP_CONTENT_TYPE_ZIP

image/gif

.gif

HTTP_CONTENT_TYPE_GIF

image/jpeg

.jpeg, .jpg

HTTP_CONTENT_TYPE_JPEG

image/png

.png

HTTP_CONTENT_TYPE_PNG

application/javascript

.js

HTTP_CONTENT_TYPE_JS

text/plain

.txt

HTTP_CONTENT_TYPE_PLAIN

text/css

.css

HTTP_CONTENT_TYPE_CSS

application/json

.json

HTTP_CONTENT_TYPE_JSON

application/x-www-form-urlencoded

-

HTTP_CONTENT_TYPE_APP_FORM

multipart/form-data

-

HTTP_CONTENT_TYPE_MULTIPART_FORM

If a Content Type is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

HTTP Status Codes#

HTTP Status Code

Micrium Type

200

HTTP_STATUS_OK

201

HTTP_STATUS_CREATED

202

HTTP_STATUS_ACCEPTED

204

HTTP_STATUS_NO_CONTENT

205

HTTP_STATUS_RESET_CONTENT

301

HTTP_STATUS_MOVED_PERMANENTLY

302

HTTP_STATUS_FOUND

303

HTTP_STATUS_SEE_OTHER

304

HTTP_STATUS_NOT_MODIFIED

305

HTTP_STATUS_USE_PROXY

307

HTTP_STATUS_TEMPORARY_REDIRECT

400

HTTP_STATUS_BAD_REQUEST

401

HTTP_STATUS_UNAUTHORIZED

403

HTTP_STATUS_FORBIDDEN

404

HTTP_STATUS_NOT_FOUND

405

HTTP_STATUS_METHOD_NOT_ALLOWED

406

HTTP_STATUS_NOT_ACCEPTABLE

408

HTTP_STATUS_REQUEST_TIMEOUT

409

HTTP_STATUS_CONFLICT

410

HTTP_STATUS_GONE

411

HTTP_STATUS_LENGTH_REQUIRED

412

HTTP_STATUS_PRECONDITION_FAILED

413

HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE

414

HTTP_STATUS_REQUEST_URI_TOO_LONG

415

HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE

416

HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE

417

HTTP_STATUS_EXPECTATION_FAILED

500

HTTP_STATUS_INTERNAL_SERVER_ERR

501

HTTP_STATUS_NOT_IMPLEMENTED

503

HTTP_STATUS_SERVICE_UNAVAILABLE

505

HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED

If a Status Code is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

HTTP Server Module#

The Micrium HTTP Server can be used in the more traditional way, meaning used to store web pages and web resources that can be fetched through Web Browsers. In that view, HTTP Server is compliant with all the available browsers (Firefox, Chrome, Safari, etc.) for computer systems.

HTTP Server can also be used in a more web service style, i.e., to fetch, modify and create web resources that are not necessarily files.

HTTP Server Overview#

Specifications#

  • Complies with the following RFC:

    • RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1

  • Implemented methods:

    • GET

    • POST

    • PUT

    • DELETE

    • HEAD

Features#

  • Scalable to contain only required features and minimize memory footprint.

  • Add-on modules are also given to enhance and simplify the development of your HTTP server application.

  • Supports file storage via Micrium OS File System or can be used via a "Static File System" which is provided inside the HTTP Server source code. The server can also be used without any File System.

  • Supports multiple instances, i.e., it’s possible to launch many web server on different TCP ports. This allows, for example, to have a part of a web application without security and another part with SSL/TLS security.

  • Supports up to 255 connections simultaneously (using only one task).

  • Allows application programmers to define “hook” functions, which are called by the HTTP Server stack when processing a request.

  • Provides many (optional) built-in statistics and error counters that can be used for debugging or for logging usage statistics.

  • Allows to specify a working directory for each HTTP server instance (Only when Micrium OS File System is used as a File System).

  • Supports secure Web Servers (HTTPs).

  • Supports persistent connections .

  • Supports HTTP REST .

  • Supports Dynamic Token Replacement in web pages and text files.

  • Supports HTTP Query String

  • Supports reception of HTTP headers in requests and addition of HTTP headers in responses.

  • Supports application and multipart forms .

  • Supports chunked transfer encoding in transmission.

Limitations#

HTTP Server Example Applications#

This section describes the examples that are related to the HTTP Server module of Micrium OS.

HTTP Server Initialization Example#

Description#

This is a generic example that shows how to initialize the HTTP Server module. It accomplishes the following tasks:

  • Initialize the HTTP Server module

  • Create a RAM disk for file exchange

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the HTTP Server module correctly:

#define

Description

EX_HTTP_SERVER_INIT_AVAIL

Lets the upper example layer know that the HTTP Server Initialization example is present and must be called by other examples.

Location#
/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
API#

API

Description

Ex_HTTP_Server_Init()

Initialize the HTTP Server stack for the example application.

Notes#

None.

Simple Server That Uses No File System#

Description#

This is a simple HTTP server example that demonstrates how to create a web page server without the use of a File System (Micrium OS File System or HTTP static FS).

The web server simply displays a "Hello World!" message on the web page once it is loaded.

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_no_fs.c

/examples/net/http/server/ex_http_server_hooks.c

/examples/net/http/server/ex_http_server_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
API#

API

Description

Ex_HTTP_Server_InstanceCreateNoFS()

Initializes and starts a basic web server instance.

Basic Server That Uses the HTTP Static File System#

Description#

This is a basic HTTP server example that demonstrates how to create a web page server using the HTTP server static file system.

The web server displays some web pages and a form once it is loaded.

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_basic_static_fs.c

/examples/net/http/server/ex_http_server_hooks.c

/examples/net/http/server/ex_http_server_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h

The content of the folder /examples/net/http/server/files

API#

API

Description

Ex_HTTP_Server_InstanceCreateStaticFS()

Initializes and starts a basic web server instance. Retrieves files from the built-in static file system.

Basic Server That Uses Micrium OS File System#

Description#

This is a basic HTTP server example that demonstrates how to create a web page server. The functionalities are similar to the "Basic Server that Uses the HTTP static File System" example. However, the web pages are retrieved using Micrium OS File System.

The web server displays some web pages and a form once it is loaded.

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_basic_fs.c

/examples/net/http/server/ex_http_server_hooks.c

/examples/net/http/server/ex_http_server_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
  • The content of the folder /examples/net/http/server/files

API#

API

Description

Ex_HTTP_Server_InstanceCreateBasic()

Initializes and starts a basic web server instance. Retrieves files from the Micrium OS file system.

Server That Handles REST Requests#

Description#

This is a simple HTTP server example that demonstrates how to handle REST requests. It uses the HTTP static file system to store the web pages.

The web server displays some web pages and a form once it is loaded. It also offers a form that allows adding entries to a database via REST requests.

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_rest.c

/examples/net/http/server/ex_http_server_rest_hooks.c

/examples/net/http/server/ex_http_server_rest_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
  • The content of the folder /examples/net/http/server/files

API#

API

Description

Ex_HTTP_Server_InstanceCreateREST()

Initialize HTTPs REST Example application.

Server That Handles Webpages, REST Requests and Authentication Support#

Description#

This is an HTTP server example that demonstrates how to handle web pages, RESTrequestsand authentication in a single instance. It requires the use of the Control Layer. It uses the HTTP static file system to store the web pages.

The web server displays some web pages and a form once it is loaded. It also offers a form that allows adding entries to a database via REST requests.

Note that you will have to login first before accessing the pages. The example will create the following user accounts:

Username

admin

user0

user1

Password

password

<empty>

user1

Rights

Manager of HTTP user access right

HTTP user

HTTP user

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_ctrl_layer.c

/examples/net/http/server/ex_http_server_hooks.c

/examples/net/http/server/ex_http_server_hooks.h

/examples/net/http/server/ex_http_server_rest_hooks.c

/examples/net/http/server/ex_http_server_rest_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
  • The content of the folder /examples/net/http/server/files

API#

API

Description

Ex_HTTP_Server_InstanceCreateCtrlLayer()

Initialize HTTPs REST Example application.

Basic Secure Server That Uses SSL-TLS and the HTTP Static File System#

Description#

This is a basic HTTP server example that demonstrates how to create asecurewebserverusingSSL-TLS and the HTTP server static file system.

The web server displays some web pages and a form once it is loaded.

Configuration#

None.

Location#
/examples/net/http/server/ex_http_server_ssl_tls_static_fs.c

/examples/net/http/server/ex_http_server_hooks.c

/examples/net/http/server/ex_http_server_hooks.h

/examples/net/http/server/ex_http_server_init.c

/examples/net/http/server/ex_http_server.h
  • The content of the folder /examples/net/http/server/files

API#

API

Description

Ex_HTTP_Server_InstanceCreateSecure()

Initialize HTTPs REST Example application.

Notes#

None

HTTP Server Configuration#

In order to address your application's needs, the HTTP Server module must be properly configured. There are three groups of configuration parameters:

HTTP Server Compile-time Configuration#

The HTTP Server module is configurable at compile time via several #defines located in http_server_cfg.h file. It uses #defines when possible, because they allow code and data sizes to be scaled at compile time based on enabled features. This allows the Read-Only Memory (ROM) and Random-Access Memory (RAM) footprints of the HTTP Server to be adjusted based on application requirements.

It is recommended that the configuration process begins with the default configuration values which in the next sections will be shown in bold.

Debug Configuration#

A fair amount of code in the HTTP Server module has been included to simplify debugging. There are several configuration constants used to aid debugging.

Table - Argument Checking and Debug Configuration#

Constant

Description

Possible Values

HTTPs_CFG_DBG_INFO_EN

Enable/disable HTTP Server debug information: Internal constants assigned to global variables.

DEF_ENABLED or DEF_DISABLED

Counter Configuration#

The HTTP Server contains code that increments counters to keep track of statistics such as the number of request received, the number of connection processed, etc. Also, the HTTP Server module contains counters that are incremented when error conditions are detected. The following constants enable or disable HTTP counters.

Table - Counter Configuration#

Constant

Description

Possible Values

HTTPs_CFG_CTR_STAT_EN

Determines whether the code and data space used to keep track of statistics will be included.

DEF_ENABLED or DEF_DISABLED

HTTPs_CFG_CTR_ERR_EN

Determines whether the code and data space used to keep track of errors will be included.

DEF_ENABLED or DEF_DISABLED

File System Configuration#

The HTTP Server can be used with a standard file system like Micrium OS File System.

Table - File System Configuration#

Constant

Description

Possible Values

HTTPs_CFG_FS_PRESENT_EN

Determines whether or not a File System is present and must be used with HTTP server.

DEF_DISABLED or DEF_ENABLED

Persistent Connection Configuration#

The HTTP Server supports persistent connection when HTTP protocol version 1.1 is used.

The configuration related to Persistent Connection must also be enabled in the run-time configuration of each server instance for which this feature is desired. See section Instance Configuration for more details.

See section Persistent Connection for more details on HTTP Persistent Connection.

Table - Persistent Connection Configuration#

Constant

Description

Possible Values

HTTPs_CFG_PERSISTENT_CONN_EN

Determines whether the code and data used to support the persistent connection feature will be included.

DEF_DISABLED or DEF_ENABLED

Header Field Configuration#

The HTTP Server contains code that allow the upper application to receive header field received in the request message and add header field to be transmitted with the response message.

The header parameters must also be defined in the run-time configuration of each server instance for which this feature is wished. See section Instance Configuration and HTTP Header Configuration for more details.

See section Headers for more details on HTTP header fields concept.

Table - Header Field Configuration#

Constant

Description

Possible Values

HTTPs_CFG_HDR_RX_EN

Determines whether the code and data space used to support additional header field in request will be included.

DEF_ENABLED or DEF_DISABLED

HTTPs_CFG_HDR_TX_EN

Determines whether the code and data space used to support additional header field in response will be included.

DEF_ENABLED or DEF_DISABLED

Query String Configuration#

The HTTP Server contains code to allow the parsing and saving of Query String received in HTTP requests.

To enable this feature for a specific server instance, the parameter associated with the Query String must also be enabled in the the run-time configuration of the instance. See section Instance Configuration and Query String Configuration for more details on the configuration.

See section Query String for additional details on the HTTP Query String concept.

Table - Query String Configuration#

Constant

Description

Possibles Values

HTTPs_CFG_QUERY_STR_EN

Determines whether the code and data space used to support Query String in HTTP request will be included.

DEF_ENABLED or DEF_DISABLED

Form Submission Configuration#

The HTTP Server can support the reception of HTML forms using the HTTP POST method. The HTTP Server module is designed to manage different type of form encoding and also to upload files from an HTML form.

To enable this feature for a specific server instance, the parameter associated with the Form feature must also be enabled in the the run-time configuration of the instance. See section Instance Configuration and HTTP Form Configuration for more details on the configuration.

See section Form for additional details on the HTML Form concept.

Table - Dynamic Content Configuration#

Constant

Description

Possible Values

HTTPs_CFG_FORM_EN

Determines whether the code and data space used to support forms submission will be included. If the server does not host form, this feature should be disabled in order to speed up processing. If this feature is set as disabled all other Form's configurations are automatically disabled.

DEF_ENABLED or DEF_DISABLED

HTTPs_CFG_FORM_MULTIPART_EN

Determines whether the code and data space used to support forms submission with “multipart/form-data” encoding will be included.

DEF_ENABLED or DEF_DISABLED

Token Replacement Configuration#

A considerable amount of code in the HTTP Server has been included to parse, replace and transmit HTML document with dynamic content using token replacement and the HTTP Chunked Transfer encoding.

To enable this feature for a specific server instance, the parameter associated with the Token feature must also be enabled in the the run-time configuration of the instance. See section Instance Configuration and Token Configuration for more details on the configuration.

Table - Dynamic Content Configuration#

Constant

Description

Possible Values

HTTPs_CFG_TOKEN_PARSE_EN

Determines whether the code and data space used to support the parsing of the tokens found in HTML files for dynamic content will be included. If the server does not host dynamic content, the feature should be disabled in order to speed up processing.

DEF_DISABLED or DEF_ENABLED

Proxy Configuration#

The HTTP Server module can be accessed even if it is located behind a proxy.

Table - Proxy Configuration#

Constant

Description

Possible Values

HTTPs_CFG_ABSOLUTE_URI_EN

Determines whether the code and data space used to support header field for absolute URI.

DEF_ENABLED or DEF_DISABLED

HTTP Server Compile-Time Configuration for Static File System#

HTTP Server's static file system is configurable at compile time via three #defines located in http_server_fs_port_static_cfg.h file. The HTTP Server module uses #defines when possible, because they allow code and data sizes to be scaled at compile time based on enabled features. This allows the Read-Only Memory (ROM) and Random-Access Memory (RAM) footprints of the HTTP Server to be adjusted based on application requirements.

It is recommended that the configuration process begins with the default configuration values which in the next sections will be shown in bold.

These configurations are necessary only if you use the static file system in your application.

Constant

Description

Possible Values

HTTPs_FS_CFG_NBR_FILES

This value defines the maximum number of files the static file system could manage.

1 or more. Default is 15.

HTTPs_FS_CFG_NBR_DIRS

This value defines the maximum number of directories the static file system could manage.

1 or more. Default is 1.

HTTPs_FS_CFG_MAX_FILE_NAME_LEN

This value defines the maximum file name length.

1 or more. Default is 256.

HTTP Server Run-Time Application Specific Configuration#

This section defines the configurations related to the HTTP Server module but that are specified at run-time, during the initialization process.

Initialization#

Initializing the HTTP Server module is done by calling the function HTTPs_Init(). This function takes no configuration argument. Unless you override an optional configuration before calling the function HTTPs_Init(), the default configurations will be used.

Optional Configurations#

This section describes the configurations that are optional. If you do not set them in your application, the default configurations will apply.

The default values can be retrieved via the structure HTTPs_InitCfgDflt.

Note that these configurations must be set before you call the function HTTPs_Init().

Table - HTTP Server Optional Configurations#

Configurations

Description

Type

Function to call

Default

Field from default configuration structure

Memory segment

This module allocates some control data. You can specify the memory segment from where such data should be allocated.

MEM_SEG*

HTTPs_ConfigureMemSeg()

General-purpose heap .

.MemSegPtr

Post-Init Configurations#

This section describes the configurations that can be set at any time during execution AFTER you called the function HTTPs_Init().

These configurations are optional. If you do not set them in your application, the default configurations will apply.

Table - HTTP Server Post-init Configurations#

Configurations

Description

Type

Function to call

Default

HTTP server instance task priority

Each HTTP server instance created via the function HTTPs_InstanceInit() will create a task. You can change the priority of the created task at any time..

RTOS_TASK_PRIO

HTTPs_InstanceTaskPrioSet()

N/A

HTTP Server Instance Configuration#

This section defines the configurations related to the HTTP Server module that are specified at run-time and that are specific to each added HTTP server instance.

To add a HTTP server instance, call the HTTPs_InstanceInit() function. This function requires two configurations arguments (described below).

p_cfg#

p_cfg is a pointer to a configuration structure of type HTTPs_CFG. The HTTP Server instance configuration is based on a large structure that contains different configuration sections with many parameter settings. This section should provide you an in-depth understanding of all instance parameter configuration. You will also discover which settings to modify in order to enhance the functionalities and the performances. Refer to the configuration field description section for further details. The HTTPs_CFG object must be passed to the HTTPs_InstanceInit() API function during the initialization of the HTTP server instance.

Task#
Table - Task Configuration#

Structure Field

Type

Description

Possible Values

.OS_TaskDly_ms

CPU_INT32U

Configure instance task delay in integer millisecondsThe web server can delay his task periodically to allow another task with lower priority to run.

MUST be >= 0

Listen Socket#
Table - Listen Socket Configuration#

Structure Field

Type

Description

Possible Values

.SockSel

HTTPs_SOCK_SEL

Configure socket type. Select which kind of IP addresses can be accepted by the web server instance.When only one IP type is selected, only one socket and TCP connection will be reserved to listen for incoming connections.When the two IP types are selected, two sockets and TCP connections will be reserved for listening.

- HTTPs_SOCK_SEL_IPv4 (Accept Only IPv4)- HTTPs_SOCK_SEL_IPv6 (Accept Only IPv6)- HTTPs_SOCK_SEL_IPv4_IPv6 (Accept IPv4 and IPv6)

.SecurePtr

HTTPs_SECURE_CFG

Configure instance secure (SSL/TLS) configuration structure.'Secure' field is used to enabled or disable SSL/TLS:1. DEF_NULL, the web server instance is not secure and doesn't use SSL/TLS.2. Point to a secure configuration structure, the web server is secure and use SSL/TLS.The secure web server can be enabled only if the application project contains a secure module supported by the Network module such as:1. NanoSSL provided by Mocana.2. CyaSSL provided by YaSSL.

- DEF_NULL for a non-secure web server- Pointer to the secure configuration (Instance^Secure^Configuration ) to be used.

.Port

CPU_INT16U

Configure instance server port.1. Default HTTP port used by all web browser is 80. The default port number is defined by the following value:HTTPs_CFG_DFLT_PORTWhen default port is used the web server instance can be accessed using the IP address of the target from any web browser:http://*\\

<target ip address\

>If the web server instance is configured with the non-default port, the instance server should be accessed via this kind of address:http://\

<target ip address\

>:\

<port number\

>Where: \

<target ip address\

> must be replaced by the IP address of the target. \

<port number\

> must be replaced by the configured port number.2. Default secure port used by all browser is 443. The default secure port number is defined by the following value:HTTPs_CFG_FDLT_PORT_SECUREWhen default port is used the web server instance can be accessed using the IP address of the target from any web browser:https:// \

<target ip address\

>If the web server instance is configured with the non-default port, the instance server should be accessed via this kind of address:https:// \

<target ip address\

> : \

<port number\

>Where\

<target ip address\

> must be replaced by the IP address of the target.\

<port number\

>* must be replaced by the configured port number.3. Port number must be unique, i.e., it's not possible to start two instances with the same port number.

- HTTPs_CFG_DFLT_PORT (Default HTTP port)- HTTPs_CFG_FDLT_PORT_SECURE Default (HTTP SSL port)

Connection#
Table - Connection Configuration#

Structure Field

Type

Description

Possible Values

.ConnNbrMax

CPU_INT08U

Configure the maximum number of simultaneous connections.'ConnNbrMax' is used to configure the maximum number of connections that the web server will be able to serve simultaneously.The maximum number of connections must be configured following your requirements about the memory usage and the number of connection:- Each connection requires memory space. So the memory required by the web server is greatly affected by the number of connection configured.- When a client downloads an item such as HTML document, image, CSS file, Javascript file, it should open a new connection for each of these items when the Persistent Connection feature is disabled. Also, most common web server can open up to 15 simultaneous connections. As an example, for an HTML document which includes 2 images + 1 CSS file, 4 connections could be opened simultaneously.The number of connection and the Network core module configuration must be configured accordingly. Each connection requires 1 TCP socket and the server requires 1 or 2 TCP socket depending if IPv4 and IPv6 connection can be accepted, see TCP Layer Configuration and Socket Layer Configuration to properly configure the web instance and Micrium OS Network module.

MUST be >= 1

.ConnInactivityTimeout_s

CPU_INT16U

Configure connection maximum inactivity timeout in integer seconds.For each connection when the inactivity timeout occurs the connection is automatically closed whatever what the state of the connection was.

SHOULD be >= 1

.BufLen

CPU_INT16U

Configure connection buffer length.Each connection has a buffer to receive & transmit data and to read file. If the memory is limited the buffer size can be reduced, but the performance could be impacted.

MUST be >= 512

.ConnPersistentEn

CPU_BOOLEAN

Configure Persistent Connection feature.See section Persistent Connection for more details on the Persistent Connection concept.

- DEF_DISABLED- DEF_ENABLED

File System#

See section File System Configuration for additional details on the File System configuration and configuration structures.

Table - File System Configuration#

Structure Field

Type

Description

Possible Values

.FS_Type

HTTPs_FS_TYPE

Configure the Type of File System to use with the HTTP server:HTTPs_FS_TYPE_NONE : No File System is present.HTTPs_FS_TYPE_STATIC : Use the HTTP Static File System offered inside the HTTP-server.HTTPs_FS_TYPE_DYN : Use a standard dynamic File System (e.g., Micrium OS File System)

HTTPs_FS_TYPE_NONEHTTPs_FS_TYPE_STATICHTTPs_FS_TYPE_DYN

.FS_CfgPtr

const void*

Configure Pointer to the File System Configuration object.Each File System Type has its configuration structure:HTTPs_CFG_FS_NONEHTTPs_CFG_FS_STATICHTTPs_CFG_FS_DYN

MUST be a valid pointer.

.DfltResourceNamePtr

CPU_CHAR*

Configure instance default HTML document.The default HTML document is returned when no file is specified in the request of the client, i.e., accessing with only the web server address. Most of the time this file should be "index.html".

MUST be a string pointer

Proxy#
Table - Proxy Configuration#

Structure Field

Type

Description

Possible Values

.HostNameLenMax

CPU_INT16U

Configure maximum host name length.When an HTTP Server is behind an HTTP Proxy, the HTTP client must send its requests with an absolute URI. For example :GET http://example.com/index.html HTTP/1.1When the absolute URI feature is enabled, the HTTP server will support absolute URI in the first line of the HTTP request messages (see the example just above). The server will also look for the 'Host' header field in the received request messages and save it in the HostPtr field of the HTTPs_CONN structure.The maximum host name length is the maximum length the server will allow for the received host name in a request message.Proxy support must be enabled to allow the web server to support absolute URI. See Proxy Configuration for further information.

SHOULD be >= 1.

Hook Functions#

See Section Hook Configuration for additional details on the hook functions configuration structure.

Table - Hook Functions Configuration#

Structure Field

Type

Description

Possible Values

.HookPtr

const HTTPs_HOOK_CFG Pointer

Pointer to an HTTPs_HOOK_CFG type object. This object contains all the hook function pointers available to personalize the processing of HTTP requests received.

Pointer to Hook object or DEF_NULL.

.Hook_CfgPtr

void*

Data associated with the Hook set-up that will be available inside each hook function.

Pointer to Hook Configuration object or DEF_NULL.

Header Field#

See Section HTTP Header Configuration for additional details on the Header Configuration structures.

Table - Header Field Configuration#

Structure Field

Type

Description

Possible Values

.HdrRxCfgPtr

const HTTPs_HDR_RX_CFG Pointer

Configure pointer to HTTP Request (RX) Header Configuration object structure.

Pointer to Configuration object structure.DEF_NULL, if feature not necessary.

.HdrTxCfgPtr

const HTTPs_HDR_TX_CFG Pointer

Configure pointer to HTTP Response (TX) Header Configuration object structure.

Pointer to Configuration object structure.DEF_NULL, if feature not necessary.

Query String#

See section Query String Configuration for additional details on Query String Configuration structure.

Table - Query String Configuration#

Structure Field

Type

Description

Possible Values

.QueryStrCfgPtr

const HTTPs_QUERY_STR_CFG Pointer

Configure pointer to HTTP Query String Configuration object structure.

Pointer to Configuration object structure.DEF_NULL, if feature not necessary.

Form#

See section HTTP Form Configuration for additional details on Form Configuration structure.

Table - Form Configuration#

Structure Field

Type

Description

Possible Values

.FormCfgPtr

const HTTPs_FORM_CFG Pointer

Configure pointer to HTML Form Configuration object structure.

Pointer to Configuration object structure.DEF_NULL, if feature not necessary.

Dynamic Token Replacement#

See section Token Configuration for additional details on Token Configuration structure.

Table - Token Configuration#

Structure Field

Type

Description

Possible Values

.Token_CfgPtr

const HTTPs_TOKEN_CFG Pointer

Configure pointer to Token Replacement Configuration object structure.

Pointer to Configuration object structure.DEF_NULL, if feature not necessary.

p_task_cfg#

Each HTTP server instance has a kernel task associated. p_task_cfg is a pointer to a configuration structure of type RTOS_TASK_CFG that allows you to configure the priority, stack base pointer, and stack size for that task.

Guidelines on How to Properly Set the Priority and Stack Size#

The priority of an HTTP Server instance's task greatly depends on the requirements of your application. For some applications, it might be better to set it at a high priority, especially if your application requires a lot of tasks and is CPU intensive.

Task Stack Sizes#

The arbitrary stack size of 1024 is a good starting point for most applications.

The only guaranteed method of determining the required task stack sizes is to calculate the maximum stack usage for each task. Obviously, the maximum stack usage for a task is the total stack usage along the task’s most-stack-greedy function path. Note that the most-stack-greedy function path is not necessarily the longest or deepest function path.

The easiest and best method for calculating the maximum stack usage for any task/function should be performed statically by the compiler or by a static analysis tool since these can calculate function/task maximum stack usage based on the compiler’s actual code generation and optimization settings. So for optimal task stack configuration, we recommend that you invest in a task stack calculator tool compatible with your build toolchain.

HTTP Server Instance Secure Configuration#

The HTTPs_SECURE_CFG structure referenced in instance configuration must exist throughout the lifetime of the HTTPs instance since the certificate and the key are not copied internally and are directly referenced throughout the HTTPs_SECURE_CFG pointer.

SSL/TLS certificate and key can be acquired either:

  1. From a certificate authority. Acquiring the certificate from an authority should ensure to avoid the untrusted warning message to be displayed when accessing the web server.

  2. Generated from a SSL tool such as OpenSSL. This kind of tool generates self-signed certificate and the untrusted warning message will be displayed every time the web server is accessed.

Configuration Field Description#
Table - Secure Configuration#

Structure Field

Type

Description

Possible Values

.CertPtr

CPU_CHAR *

Pointer to the public certificate’s character string.

String

.CertLen

CPU_INT32U

Length of the public certificate.

MUST BE > 0

.KeyPtr

CPU_CHAR *

Pointer to the private key’s character string.

String

.KeyLen

CPU_INT32U

Length of the private key.

MUST BE > 0

.Fmt

NET_SOCK_SECURE_CERT_KEY_FMT

Format of the key and certificate. Supported formats are PEM and DER.If the PEM format is used, do not include the “-----BEGIN CERTIFICATE-----”, “-----END CERTIFICATE-----”, “-----BEGIN RSA PRIVATE KEY-----” or “-----END RSA PRIVATE KEY-----” sections.

- NET_SOCK_SECURE_CERT_KEY_FMT_PEM- NET_SOCK_SECURE_CERT_KEY_FMT_DER

.CertChain

CPU_BOOLEAN

Flag to set if the certificate is chained to another one.

- DEF_NO- DEF_YES

Structure Example#

Listing - Secure Configuration Structure Example in the HTTP Server Instance Secure Configuration page demonstrates how to create an HTTP Server secure configuration structure.

Listing - Secure Configuration Structure Example#
#define HTTPs_CFG_SECURE_CERT                                    \
"MIIEEjCCAvqgAwIBAgIBBzANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDEw9WYWxp\
Y29yZS1EQzEtQ0EwHhcNMTEwMzE4MTcwMTQyWhcNMjEwMzE1MTcwMTQyWjCBkDEL\
MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQ8wDQYDVQQHEwZJcnZpbmUxHjAcBgNV\
BAoTFVZhbGljb3JlIFRlY2hub2xvZ2llczEhMB8GA1UEAxMYbGFuLWZ3LTAxLnZh\
bGljb3JlLmxvY2FsMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBsb2NhbGRvbWFpbjCC\
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwGOahytiwshzz1s/ngxy1+\
+VrXZYjKSEzMYbJCUhK9xA5fz8pGtOZIXI+CasZPSbXv+ZDLGpSpeFnOL49plYRs\
vmTxg2n3AlZbP6pD9OPU8rmufsTvXAmQGxxIkdmWiXYJk0pbj+U698me6DKMV/sy\
3ekQaQC2I2nr8uQw8RhuNhhlkWyjBWdXnS2mLNLSan2Jnt8rumtAi3B+vF5Vf0Fa\
kLJNt45R0f5jjuab+qw4PKMZEQbqe0XTNzkxdD0XNRBdKlajffoZPBJ7xkfuKUA3\
cMjXKzetABoKvsv+ElfvqlrI9RXvTXy52EaQmVhiOyBHrScq4RbwtDQsd59Qmk0C\
AwEAAaOB6zCB6DAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDA0BglghkgB\
hvhCAQ0EJxYlRWFzeS1SU0EgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAd\
BgNVHQ4EFgQUrq5KF11M9rpKm75nAs+MaiK0niYwUQYDVR0jBEowSIAU2Q9eGjzS\
LZhvlRRKO6c4Q5ATtuChHqQcMBoxGDAWBgNVBAMTD1ZhbGljb3JlLURDMS1DQYIQ\
T9aBcT0uXoxJmC0ohp7oSTATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMC\
BaAwDQYJKoZIhvcNAQEFBQADggEBAAUMm/9G+mhxVIYK4anc34FMqu88NQy8lrh0\
loNfHhIEKnerzMz+nQGidf+KBg5K5U2Jo8e9gVnrzz1gh2RtUFvDjgosGIrgYZMN\
yreNUD2I7sWtuWFQyEuewbs8h2MECs2xVktkqp5KPmJGCYGhXbi+zuqi/19cIsly\
yS01kmexwcFMXyX4YOVbG+JFHy1b4zFvWgSDULj14AuKfc8RiZNvMRMWR/Jqlpr5\
xWQRSmkjuzQMFavs7soZ+kHp9vnFtY2D6gF2cailk0sdG0uuyPBVxEJ2meifG6eb\
o3FQzdtIrB6oMFHEU00P38SJq+mrDItPDRXNLa2Nrtc1EJtmjws="

#define HTTPs_CFG_SECURE_KEY                                     \
"MIIEogIBAAKCAQEAvAY5qHK2LCyHPPWz+eDHLX75WtdliMpITMxhskJSEr3EDl/P\
yka05khcj4Jqxk9Jte/5kMsalKl4Wc4vj2mVhGy+ZPGDafcCVls/qkP049Tyua5+\
xO9cCZAbHEiR2ZaJdgmTSluP5Tr3yZ7oMoxX+zLd6RBpALYjaevy5DDxGG42GGWR\
bKMFZ1edLaYs0tJqfYme3yu6a0CLcH68XlV/QVqQsk23jlHR/mOO5pv6rDg8oxkR\
Bup7RdM3OTF0PRc1EF0qVqN9+hk8EnvGR+4pQDdwyNcrN60AGgq+y/4SV++qWsj1\
Fe9NfLnYRpCZWGI7IEetJyrhFvC0NCx3n1CaTQIDAQABAoIBAEbbqbr7j//RwB2P\
EwZmWWmh4mMDrbYBVYHrvB2rtLZvYYVxQiOexenK92b15TtbAhJYn5qbkCbaPwrJ\
E09eoQRI3u+3vKigd/cHaFTIS2/Y/qhPRGL/OZY5Ap6EEsMHYkJjlWh+XRosQNlw\
01zJWxbFsq90ib3E5k+ypdStRQ7JQ9ntvDAP6MDp3DF2RYf22Tpr9t3Oi2mUirOl\
piOEB55wydSyIhSHusbms3sp2uvQBYJjZP7eENEQz55PebTzl9UF2dgJ0wJFS073\
rvp46fibcch1L7U6v8iUNaS47GTs3MMyO4zda73ufhYwZLU5gL8oEDY3tf/J8zuC\
mNurr0ECgYEA8i1GgstYBFSCH4bhd2mLu39UVsIvHaD38mpJE6avCNOUq3Cyz9qr\
NzewG7RyqR43HsrVqUSQKzlAGWqG7sf+jkiam3v6VW0y05yqDjs+SVW+ZN5CKyn3\
sMZV0ei4MLrfxWneQaKy/EUTJMlz3rLSDM/hpJoA/gOo9BIFRf2HPkkCgYEAxsGq\
LYU+ZEKXKehVesh8rIic4QXwzeDmpMF2wTq6GnFq2D4vWPyVGDWdORcIO2BojDWV\
EZ8e7F2SghbmeTjXGADldYXQiQyt4Wtm+oJ6d+/juKSrQ1HIPzn1qgXDNLPfjd9o\
9lX5lGlRn49Jrx/kKQAPTcnCa1IirIcsmcdiy+UCgYBEbOBwUi3zQ0Fk0QJhb/Po\
LSjSPpl7YKDN4JP3NnBcKRPngLc1HU6lElny6gA/ombmj17hLZsia1GeHMg1LVLS\
NtdgOR5ZBrqGqcwuqzSFGfHqpBXEBl6SludmoL9yHUreh3QhzWuO9aFcEoNnl9Tb\
g9z4Wf8Pxk71byYISYLt6QKBgERActjo3ZD+UPyCHQBp4m45B246ZQO9zFYdXVNj\
gE7eTatuR0IOkoBawN++6gPByoUDTWpcsvjF9S6ZAJH2E97ZR/KAfijh4r/66sTx\
k26mQRPB8FHQvqv/kj3NdsgdUJJeeqPEyEzPkcjyIoJxuB7gN2El/I5wCRon3Qf9\
sQ6FAoGAfVOaROSAtq/bq9JIL60kkhA9sr3KmX52PnOR2hW0caWi96j+2jlmPT93\
4A2LIVUo6hCsHLSCFoWWiyX9pIqyYTn5L1EmeBO0+E8BH9F/te9+ZZ53U+quwc/X\
AZ6Pseyhj7S9wkI5hZ9SO1gcK4rWrAK/UFOIzzlACr5INr723vw="

#define  HTTPs_CFG_SECURE_CERT_LEN      (sizeof(HTTPs_CFG_SECURE_CERT) - 1)
#define  HTTPs_CFG_SECURE_KEY_LEN       (sizeof(HTTPs_CFG_SECURE_KEY)  - 1)

HTTPs_SECURE_CFG  HTTPs_Cfg_InstanceSecure = {
                                                HTTPs_CFG_SECURE_CERT,
                                                HTTPs_CFG_SECURE_CERT_LEN,
                                                HTTPs_CFG_SECURE_KEY,
                                                HTTPs_CFG_SECURE_KEY_LEN,
                                                NET_SOCK_SECURE_CERT_KEY_FMT_PEM,
                                                DEF_NO,
                                             };
HTTP Server Instance File System Configuration#

The HTTP Server module can run with or without Micrium OS File System module.

If you don't use Micrium's File System and still need to store files on your HTTP server, the HTTP Server module comes with a "Static File System". This pseudo File System allows to store your files in constant C arrays, read them and navigate inside them. A script allows you to convert your files to constant C arrays that should then be added to your project. Afterwards, the function HTTPs_FS_AddFile() allows you to store those files in the "Static File System".

Configuration#

Three types of File System can be configured with the HTTP Server. Each type has its own File System configuration structure.

In the HTTP server Instance configuration, the FS Type and the Pointer to the associated FS configuration must be passed. See section Instance Configuration .

HTTPs_FS_TYPE

Configuration Structure

Description

HTTPs_FS_TYPE_NONE

None

Use when no File System is present.

HTTPs_FS_TYPE_STATIC

HTTPs_CFG_FS_STATIC

Use when the HTTP Server Static File System is used.

HTTPS_FS_TYPE_DYN

HTTPs_CFG_FS_DYN

Use when Micrium OS File System module is used.

No File System Configuration#

No configuration is required when no File System is present.

HTTP Server Static File System Configuration#

The configurations structure is of type HTTPs_CFG_FS_STATIC. Table - HTTPs_CFG_FS_STATIC Configuration Structure Description in the HTTP Server Instance File System Configuration page describes this configuration structure.

Table - HTTPs_CFG_FS_STATIC Configuration Structure Description#

Field

Type

Description

Possible Values

.FS_API_Ptr

const NET_FS_API*

Configure the pointer to the File System Network API object structure.

HTTPs_FS_API_Static located in http_server_fs_port_static.h.

Dynamic File System Configuration#

The configurations structure is of type HTTPs_CFG_FS_DYN. Table - HTTPs_CFG_FS_DYN Configuration Structure Description in the HTTP Server Instance File System Configuration page describes this configuration structure.

Table - HTTPs_CFG_FS_DYN Configuration Structure Description#

Field

Type

Description

Possible Values

.FS_API_Ptr

const NET_FS_API*

Configure the pointer to the File System Network API object structure.

NetFS_API_Native located in net_fs.h.

.WorkingFolderPtr

CPU_CHAR*

Pointer to the Working Folder name.Web server instances can use a working folder where files and subfolders are located. It can be set as a null pointer (DEF_NULL) if the file system doesn't support 'set working folder' functionality, but HTML documents and files must be located in the default path used by the file system.

SHOULD be a string pointer.

HTTP Server Instance Hook Configuration#

The HTTP Server module offers multiple hook functions during the processing of an HTTP transaction.Those hooks allow the HTTP server to be customized according to your application requirements. The hook configuration is part of the HTTP server Instance configuration and must be included in the HTTPs_CFG object (see section Instance Configuration ).

See section the Hook Functions to see at what point of the process each hook is called by the server stack.

The configuration structure is of type HTTPs_HOOK_CFG. It contains only function pointers. The sections below describe this configuration structure.

.OnInstanceInitHook#

When the instance is created, a hook function can be called to initialize connection objects used by the instance (see Hook Functions page to see when this function is called).

If the hook is not required by the upper application, it can be set as DEF_NULL and no function will be called.

See Connection Objects Initialization for further details.

CPU_BOOLEAN App_OnInstanceInit (const  HTTPs_INSTANCE  *p_instance,
                                const  void            *p_hook_cfg);
.OnReqHdrRxHook#

Configure request header field receive callback function.

Each time a header field other than the default one is received, a hook function is called allowing to choose which header field(s) to keep for further processing.

If the hook is not required by the upper application, it can be set as DEF_NULL and no function will be called.

See Receive Request Header Field for further details.

CPU_BOOLEAN  App_OnReqHdrRx (const  HTTPs_INSTANCE  *p_instance,
                             const  HTTPs_CONN      *p_conn,
                             const  void            *p_hook_cfg,
                                    HTTP_HDR_FIELD   hdr_field);
.OnReqHook#

Configure request hook function.

For each new incoming request, a hook function can be called by the HTTP server to authenticate the request and accept or reject it. At this point, the Start Line and the HTTP headers of the request have been parsed. The data received can be access in the HTTPs_CONN object. This function has also the right to modify some of the parameters of the HTTP transaction inside the HTTPs_CONN object.

If the hook is not required by the upper application, it can be set as DEF_NULL and no function will be called.

See Connection Request for further details.

CPU_BOOLEAN  App_OnReq (const  HTTPs_INSTANCE  *p_instance,
                               HTTPs_CONN      *p_conn,
                        const  void            *p_hook_cfg);
.OnReqBodyRxHook#

Configure request body data received hook function.

For some applications, it is required to parse itself the data as soon as received and not let the HTTP server core do it. It that case, this hook function allows the application to retrieve the received data directly.

If the hook is not required by the upper application, it can be set as DEF_NULL and no function will be called.

See On Request Body Received Hook for further details.

CPU_BOOLEAN  App_OnReqBodyRx (const  HTTPs_INSTANCE         *p_instance,
                                     HTTPs_CONN             *p_conn,
                              const  void                   *p_hook_cfg,
                                     void                   *p_buf,
                              const  CPU_SIZE_T              buf_size,
                                     CPU_SIZE_T             *p_buf_size_used);
.OnReqRdySignalHook#

Configure request ready signal hook function.

The Signal hook function occurs after the request has been parsed completely (header + body). In the case of a POST request containing a form, all the data have been saved in the CGI key-value pairs block. The list of CGI data is available in the HTTPs_CONN object. The callback function should not be blocking and should return quickly. A time-consuming function will block the processing of the other connections and reduce the HTTP server performance.

In case the CGI data processing is time-consuming, the Poll hook function should be enabled to allow the server to periodically verify if the upper application has finished the CGI data processing.

If the CGI form feature is not enabled, this field is not used and can be set as DEF_NULL.

See Request Ready Signal Hook for further details.

CPU_BOOLEAN  App_OnReqRdySignal (const  HTTPs_INSTANCE  *p_instance,
                                        HTTPs_CONN      *p_conn,
                                 const  void            *p_hook_cfg,
                                 const  HTTPs_KEY_VAL   *p_data);
.OnReqRdyPollHook#

Configure request ready poll hook function.

The Poll hook function should be enabled in case the request data processing require lots of time. It allows the HTTP server to periodically poll the upper application and verify if the request data processing has finished.

If the Poll feature is not required, this field should be set as DEF_NULL.

See Request Ready Poll Hook for further details.

CPU_BOOLEAN  App_OnReqRdyPoll (const  HTTPs_INSTANCE  *p_instance,
                                      HTTPs_CONN      *p_conn,
                               const  void            *p_hook_cfg);
.OnRespHdrTxHook#

Configure response header field transmit hook function.

Before an HTTP response message is sent, a hook function is called allowing to add header field(s) to the message before it is sent.

If the hook is not required by the upper application, it can be set as DEF_NULL and no function will be called.

See Add Response Header Field for further details.

CPU_BOOLEAN  App_OnRespHdrTx (const  HTTPs_INSTANCE  *p_instance,
                                     HTTPs_CONN      *p_conn,
                              const  void            *p_hook_cfg);
.OnRespTokenHook#

Configure response dynamic token replacement hook function.

The hook function is called by the HTTP server when a token is found. Basically, the callback function must fill a buffer with the value to be sent instead of the token.

If the header feature is not enabled, this field is not used and can be set as DEF_NULL.

See Get Token Value for further information.

CPU_BOOLEAN  App_OnRespToken (const  HTTPs_INSTANCE  *p_instance,
                                     HTTPs_CONN      *p_conn,
                              const  void            *p_hook_cfg,
                              const  CPU_CHAR        *p_token,
                                     CPU_INT16U       token_len,
                                     CPU_CHAR        *p_val,
                                     CPU_INT16U       val_len_max);
.OnRespChunkHook#

Configure response chunked data hook function.

The hook function must be set up when the application needs to send data in chunked transfer encoding. In that case, the HTTP server core will call the hook when the response body is being built.

If the hook is not required by the upper application layer, it can be set as DEF_NULL and no function will be called.

See On Response Chunk Hook for further details.

CPU_BOOLEAN  App_OnRespChunk (const  HTTPs_INSTANCE  *p_instance,
                                     HTTPs_CONN      *p_conn,
                              const  void            *p_hook_cfg,
                                     void            *p_buf,
                                     CPU_SIZE_T       buf_len_max,
                                     CPU_SIZE_T      *p_tx_len);
.OnTransCompleteHook#

Configure HTTP Transaction complete hook function.

This hook function is called after an HTTP transaction has been completed. When the persistent connection mode is enabled, it is possible that the application needs to free some memory objects related to a transaction and this hook function is there for that.

If the hook is not required by the upper application layer, it can be set as DEF_NULL and no function will be called.

See On Transaction Complete Hook for further details.

void  App_OnTransCmpl (const  HTTPs_INSTANCE  *p_instance,
                              HTTPs_CONN      *p_conn,
                       const  void            *p_hook_cfg);
.OnErrHook#

Configure error hook function.

When an internal error occurred during the processing of a transaction a hook function can be called to change the behavior such as the status code and the page returned.

If the hook is not required by the upper application layer, it can be set as DEF_NULL and no function will be called.

See Connection Error for further details.

void  App_OnErr (const  HTTPs_INSTANCE  *p_instance,
                        HTTPs_CONN      *p_conn,
                 const  void            *p_hook_cfg,
                        HTTPs_ERR        err);
.OnErrFileGetHook#

Configure Get error file hook function.

Get error file hook can be called every time an error has occurred when processing a transaction, i.e., status code is not equal to 'OK'. This function can set the web page that should be transmitted instead of the default error page defined in http-s_cfg.h.

If set to DEF_NULL the default error page will be used for every error.

See Get Error Document for further details.

void  App_OnErrFileGet (const  void                   *p_hook_cfg,
                               HTTP_STATUS_CODE        status_code,
                               CPU_CHAR               *p_file_str,
                               CPU_INT32U              file_len_max,
                               HTTPs_BODY_DATA_TYPE   *p_file_type,
                               HTTP_CONTENT_TYPE      *p_content_type,
                               void                  **p_data,
                               CPU_INT32U             *p_date_len);
.OnConnCloseHook#

Configure Connection close hook function.

Once a connection is closed a hook function can be called to let the upper application layer know that a connection is not yet active. This hook function could be used to free some previously allocated memory.

If the hook is not required by the upper application layer, it can be set as DEF_NULL and no function will be called.

See Connection Close for further details.

void  App_OnConnClose (const  HTTPs_INSTANCE  *p_instance,
                              HTTPs_CONN      *p_conn,
                       const  void            *p_hook_cfg);
HTTP Server Instance Header Configuration#

HTTP headers can be added to HTTP request and response messages to specify additional parameters for the HTTP transaction. See section Headers for more details on HTTP headers.

The HTTP Server module supports both reception and transmission of additional headers. However, note that some header fields are already taken care of by the HTTP Server stack and must therefore not be added by the application :

  • Host

  • Content-Type

  • Content-Length

  • Transfer-Encoding

  • Connection

  • Location

Two distinct structures are available to configure the request and response part. Therefore, header fields received have their own configuration as the headers fields to transmit an HTTP response. This allows more flexibility in customizing your own HTTP server application. For example, your server can be more interested in receiving many headers from clients and not adding any headers of its own in the HTTP response.

The Header configurations are part of the HTTP server Instance configuration and must be included in the HTTPs_CFG object (see section Instance Configuration ).

Fields Description#

Structure Field

Type

Description

Possible Values

.NbrPerConnMax

CPU_INT16U

Maximum number of headers for each HTTP request or response.

SHOULD be >= 1LIB_MEM_BLK_QTY_UNLIMITED to set an unlimited pool.

.DataLenMax

CPU_INT16U

Maximum length of the header field value accepted by the HTTP server.

SHOULD be >= 1

Since the HTTP server only processed an HTTP Transaction at a time on a given Connection, the .NbrPerConnMax field set the number of headers available for an HTTP transaction and connection.

HTTP Server Instance Query String Configuration#

To enable the Query String feature, the compile-time configuration HTTPs_CFG_QUERY_STR_EN must be set accordingly (See section Module Configuration ).

Also a configuration object (HTTPs_QUERY_STR_CFG) MUST be added to the HTTP Instance configuration (See section Instance Configuration ).

For more information on HTTP Query String, see section Query String .

Fields Description#

Structure Field

Type

Description

Possible Values

.NbrPerConnMax

CPU_INT16U

Maximum number of Query String fields accepted for each HTTP request.

SHOULD be >= 1LIB_MEM_BLK_QTY_UNLIMITED to set an unlimited pool.

.KeyLenMax

CPU_INT16U

Maximum length of the key part accepted by the HTTP server.

SHOULD be >= 1

.ValLenMax

CPU_INT16U

Maximum length of the value part accepted by the HTTP server.

SHOULD be >= 1

HTTP Server Instance Form Configuration#

To enable the Form feature, the compile-time configuration HTTPs_CFG_FORM_EN must be set accordingly (See section Module Configuration ).

Also a configuration object (HTTPs_FORM_CFG) MUST be added to the HTTP Instance configuration (See section Instance Configuration ).

For more information on HTTP Form Submission, see section HTTP Form .

Fields Description#

Structure Field

Type

Description

Possible Values

.NbrPerConnMax

CPU_INT16U

Maximum number of Form fields accepted for each HTTP request.Number must be greater than or equal to the maximum number of input fields which can be transmitted inside a received HTML form.

SHOULD be >= 1LIB_MEM_BLK_QTY_UNLIMITED to set an unlimited pool.

.KeyLenMax

CPU_INT16U

Maximum length of the key part accepted by the HTTP server.

SHOULD be >= 1

.ValLenMax

CPU_INT16U

Maximum length of the value part accepted by the HTTP server.

SHOULD be >= 1

.MultipartEn

CPU_BOOLEAN

Enable/Disable Multipart Form support.

DEF_ENABLED or DEF_DISABLED

.MultipartFileUploadEn

CPU_BOOLEAN

Enable/Disable File Upload feature inside Multipart Form.If File Upload feature is enabled, the web server will store the file received. If the feature is not enabled and a file is received the file will simply be dropped.File upload is not yet possible with the Static File System.

DEF_ENABLED or DEF_DISABLED

.MultipartFileUploadOverWrEn

CPU_BOOLEAN

Enable/Disable File overwrite when file is uploaded to server.File overwrite must be enabled to allow a file to be received if the file already exists in the folder.

DEF_ENABLED or DEF_DISABLED

.MultipartFileUploadFolderPtr

CPU_CHAR *

Configures the folder where the uploaded files will be stored.A folder name needs to be specified to indicate where the uploaded files will be save.If it is wished to save uploaded files directly in the root web directory, the name folder needs to be set as "\".I f uploaded files need to be saved inside a subfolder of the root web directory, the folder MUST already exist when the HTTP server tries to access it.

SHOULD be a string pointer

HTTP Server Instance Token Configuration#

To enable the Dynamic Token Replacement feature, the compile-time configuration HTTPs_CFG_TOEKN_EN must be set accordingly (See section Module Configuration ).

Also a configuration object (HTTPs_TOKEN_CFG) MUST be added to the HTTP Instance configuration (See section Instance Configuration ).

Fields Description#

Structure Field

Type

Description

Possible Values

.NbrPerConnMax

CPU_INT16U

Maximum number of tokens accepted for each HTTP transaction.

SHOULD be >= 1LIB_MEM_BLK_QTY_UNLIMITED to set an unlimited pool.

.ValLenMax

CPU_INT16U

Maximum length of the token replacement value accepted by the HTTP server.

SHOULD be >= 1

HTTP Server Programming Guide#

This section regroups topics to help developing a custom HTTP server application with the Micrium OS HTTP Server stack. Examples are include in many sub-sections.

HTTP Server Interface with File System#

Although the HTTP Server module can be used without a File System, when file operations are required by the HTTP server, Micrium OS File System module is needed. This will allow you to dynamically load the web pages and enable your web server to receive files. However, the HTTP Server comes with a minimalist in-house Static File system which only stores static files (stored in the code space memory). Obviously, it is only possible to read them and thus not possible to upload files to a web server when the static file system is used.

Configuration#
Compile-Time Configuration#

The configuration macro HTTPs_CFG_FS_PRESENT_EN must be set to DEF_ENABLED in the http_server_cfg.h file when a File System (the in-house static or a standard FS) must be used with the HTTP server.

See section File System Compile-time Configuration for more details.

Run-Time Configuration#

Three types of configuration structure exist for the File System Configuration: one when No FS is used, one for the Static FS and one when Micrium OS File System is used. Depending on your setup, an object of one of those structures type must be defined in the application and passed as a pointer inside the instance configuration object structure (HTTPs_CFG).

See section File System Run-time Configuration for additional details.

Usage#
Transferring Files to Use with the HTTP Server#

Transferring files on the file system for use with the HTTP Server module is outside the scope of this document. For this purpose, you could use an FTP client, such as Micrium OS FTP Client , or alternatively, use a mass storage media to access your file system.

Note that the HTTP Server can support file upload when Micrium OS File System is used. Thus it’s possible to create scripts to transmit files using the POST method even if no file is yet loaded. Also, many web browsers now have plugins for testing purposes. They allow you to send custom HTTP requests to a server. You can therefore use some of those tools to upload files to the HTTP server. Micrium has tested the Postman plugin with Chrome.

Using the HTTP Server with the Static File System#

The HTTP Server provides a small file system that could allow it to be used without Micrium OS File System.

The static file system relies on C arrays to represent the various files, and those files are accessible only for reading. The HTTP Server ships with a very basic web page consisting of a .gif and two .html files.

A python script named GenerateFS.py is offered in the HTTP Server code allowing to convert files into C arrays. The script can be useful if many files are to be converted since it supports recursion inside a folder. The script also generates C files (generated_fs.c/.h) with the function to call to include all the C arrays generated.

This script has been created to ease your life as a developer. It is not intended to be a production tool.

The script should be called in a command line shell like shown below:

python GenerateFS.py [source directory or file name] [destination directory] -f

The first argument is the path directory where to files to be converted are located or the file name of the single file to convert. The second argument is the directory path where to save the generated file(s). An optional -f argument can be used to force the re-writing if the destination file already exists.

Static File System Module Configuration#

A configuration file will be created if you select a static file system in your project. The configuration file name is http_server_fs_port_static_cfg.h. Refer to Configuration for Static File System for more information.

HTTP Server Control Structures#

Many hook functions receive pointers to control structures which can be used by upper layer to change the behavior of the server and for debugging purpose.

HTTPs_INSTANCE#

The instance control structure should be only used for debugging purpose. The upper application MUST not modify this structure, it must only read data except for the .DataPtr field. Here is a list of fields of interest:

Field

Description

.Started

The HTTP Server instance is running or is stopped.

.CfgPtr

Pointer to the instance's configuration.

.SockListenID_IPv4

Socket ID used to listen on server port for IPv4 socket family.

.SockListenID_IPv6

Socket ID used to listen on server port for IPv6 socket family.

.ConActiveCtr

Current number of connection active.

.StatsCtr

Pointer to instance statistics counter structure.

.ErrsCtr

Pointer to instance errors counter structure.

.DataPtr

This field is available for the upper application to store memory location relative to the instance that will be accessible across all hook functions.

HTTPs_CONN#

The connection control structure may be used to change the behavior on a particular HTTP transaction occurring on a connection and for connection processing and debugging purpose.

Fields to Read#

Those are the relevant connection fields that can be read inside the hook functions by the application. They can, among others things, be used to demultiplex a connection:

.ClientAddr

Contains the IP address and port of the client.

.SockID

Contains the socket ID used to receive and transmit data.

.Method

This field contains the method of the request received:

  • HTTP_METHOD_GET

  • HTTP_METHOD_POST

  • HTTP_METHOD_HEAD

  • HTTP_METHOD_PUT

  • HTTP_METHOD_DELETE

.ReqContentType

If the HTTP request has a body, this field will contains the content type of the body.

.QueryStrListPtr

This field is the head of the list of key-value pairs received inside a Query String if one was present after the request URL.

.HdrListPtr

This field is the head of the list of header fields received inside the HTTP request.

.FormDataListPtr

This field is the head of the list of key-value pairs received in a form inside a POST request.

NULL, if no key-value pairs was received.

Fields to Read/Write#

The following is a list of field that can be modified via some hook functions:

.StatusCode

HTTP status code of the connection. When it changes, the web server transmits the response (status code and status phrase) with the status code of the connection. See section HTTP Server Recognized Status Codes for a list of Status Code recognized by the HTTP Server module.

.PathPtr

At the request level, this field contains the path to the resource received in the HTTP request URL. It can be used for comparison inside hooks to do some operations according to the URL received.

At the response level, if the resource is a file (see RespBodyDataType field), this field will be used to fetch the file from the File System whose location is indicated by the PathPtr. This file will then be copied in the response body. This field will also be used to construct the location header if necessary.

Before the response level, the upper application can modify the PathPtr contents via the hook functions if its needs to modify the file to send in the response. If the resource to send back in the response is not a file, the field can still be used to set the path of the resource in case a location header also needs to be sent.

The pointer MUST NOT be changed at any moment. Only the buffer content pointed by PathPtr can be modified to write a new string.

.DataPtr

In the case where the resource to send in the response is a file contained in a FS (RespBodyDataType == FILE), this field is used by the server to store the file data to transmit. Therefore, It MUST NOT be modified by the application.

In the case where the resource to send in the response is static data located in memory (RespBodyDataType == STATIC DATA), this field MUST be set by the application via the hook functions. It should be set the point to the data to send.

In the case where the resource to send is also data located in memory (RespBodyDataType == STATIC DATA) but that must be sent in Chunked Transfer Encoding with the Chunk Hook , the DataPtr MUST be set to NULL by the application via the hooks functions. That way the Chunk Hook will be called later.

.DataLen

In the case where the resource to send is a file contain in a FS (RespBodyDataType == FILE), this field will be used by the server to store the length of the file. Therefore, it MUST NOT be modified by the application via the hook functions.

In the case where the resource to send is static data located in memory (RespBodyDataType == STATIC DATA) and that the DataPtr was set to the memory address of the data, the DataLen field MUST be set to the data length by the application.

When transferring data via the Chunk Hook because the DataPtr was previously set to NULL, the DataLen field is not taken into account by the server.

.RespContentType

This field will contains the content type of the response body.

If a file (that is in a File System) is to be sent and the RespContentType field is set to "Unknown", the server will parse the file extension to set the Content Type. Therefore, the application could set the field via the hook functions, but doesn't need to in the case of a file.

If static data is to be sent (RespBodyDataType == STATIC DATA), this field MUST absolutely be set by the application via the hook functions.

.RespBodyDataType

This field set the type of data of the response body. Three types are available:

  • HTTPs_BODY_DATA_TYPE_FILE: When data body is from a file that was stored in a File System.

  • HTTPs_BODY_DATA_TYPE_STATIC_DATA: When data body is from memory allocation or is sent via Chunk Hook .

  • HTTPs_BODY_DATA_TYPE_NONE: When no body will be sent with the response.

By default this field is set to HTTPs_BODY_DATA_TYPE_FILE for GET and HEAD methods and to HTTPs_BODY_DATA_TYPE_NONE for POST, DELETE and PUT method. The field can be modified by the application via the hook functions.

.ConnDataPtr

This parameter is available for the upper application to store memory location for connection processing across all hook functions.

All other fields MUST NOT be modified but they could be read for the connection processing and for debugging.

We strongly recommend to use the three following API functions: HTTPs_RespBodySetParamFile () , HTTPs_RespBodySetParamStaticData() and HTTPs_RespBodySetParamNoBody() , to set the Response Body parameters adequately instead of changing the fields directly. Those functions will change the right fields for you according to the type of body you want to send.

HTTP Server Query String#

A Query String is a set of Key-Value pairs or single values added at the end of the request's URL after a question mark character "?". Each fields of the Query are separated by the "&" character.

For more details, see section Query String .

The HTTP Server can supports the reception of a Query String in the HTTP request.

Configuration#
Compile-Time Configuration#

The configuration macro HTTPs_CFG_QUERY_STR_EN must be set to DEF_ENABLED in the http_server_cfg.h file to enable this feature.

See section Query String Configuration for more details.

Run-Time Configuration#

The run-time configuration for Query String is defined as a HTTPs_QUERY_STR_CFG structure. Your application must declare an HTTPs_QUERY_STR_CFG object and include a pointer to this object in the HTTP server instance configuration HTTPs_CFG object where the QueryStrCfgPtr parameter is defined.

See section Query String Configuration for additional details.

Hook Function#

The HTTP Server Instance configuration structure (HTTPs_CFG) contains a pointer to an HTTPs_HOOK_CFG object. This object indexes all the hook functions required by your application.

For additional details on the configuration of hook functions, see section Hook Configuration .

To visualize when each hook function is called by the HTTP server core, see section Hook Functions .

To retrieve the Query String data saved by the HTTP server, two hook functions can be used: OnReqHook and OnReqRdySignalHook .

Usage#

When the feature is enabled, query strings received in an HTTP request are saved by the HTTP server core under a list of key-value pair. This list is available using the field .QueryStrListPtr inside the HTTPs_CONN structure. This list is accessible to your application inside the hook functions OnReqHook and OnReqRdySignalHook.

Single value fields inside the Query String are also supported. The value will still be saved in a Key-Value pair block, but only the value field will be meaningful.

HTTP Server Hook Functions#

Each Web server is highly customizable using hook functions. Many hook functions can be called by the HTTP Server module during the processing of each client's request. Those hook functions allow the application to respond differently based on the application context. For example, it's possible to implement functionality such as dynamic content replacement, authentication, adding HTTP headers to the HTTP response (i.e., cookie), redirect, generate run-time data page, etc.

For more information on how to configure the hook functions for a given HTTP server instance, see the section Hook Configuration .

Also for the complete list of all the hook functions available and their prototype, see the section Hook Functions API .

HTTP Tasks Global Overview#

The diagrams below show a simplified state diagram of the HTTP server transaction processing but also when and where the hook functions are called.

HTTP Tasks Global OverviewHTTP Tasks Global Overview

HTTP Request Processing#

The diagrams below shows in more detail the HTTP received request processing section.

HTTP Request ProcessingHTTP Request Processing

HTTP Response Processing#

The diagrams below show in more details the HTTP response processing section.

HTTP Response ProcessingHTTP Response Processing

HTTP Server Header Fields#

The Header Field feature allows the HTTP Server module to receive and transmit additional HTTP headers to the one already processed internally by the HTTP server core.

The header fields listed below are already taken care of by the HTTP Server stack and must therefore not be added or processed by the application:

  • Host

  • Content-Type

  • Content-Length

  • Transfer-Encoding

  • Connection

  • Location

See section HTTP Header Fields Recognized for a list of all the header field recognized by the HTTP Server product.

To learn more on the HTTP header concepts, see section Headers .

Configuration#

For the HTTP server to support processing of additional headers, two types of configuration must be set up: the compile-time and the run-time configuration. Also, some hook functions must be defined to allow the upper application to use this feature.

The Header Field feature is divided in two independent parts: the reception and the transmission. Each part has its own configuration as it will be shown below.

The reception is associated with HTTP header fields received in HTTP requests and the transmission is associated with HTTP header fields to send in HTTP responses.

Compile-time Configuration#

Two configuration macros are available for the Header Field feature: HTTPs_CFG_HDR_RX_EN for the reception and HTTPs_CFG_HDR_TX_EN for the transmission. Each can be enabled and disabled separately.

See section Header Field Configuration for more details.

Run-time Configuration#

The run-time configuration for the Header Field feature has defined two structures: HTTPs_HDR_RX_CFG and HTTPs_HDR_TX_CFG. If your application needs to save headers received in HTTP requests, it must declare an HTTPs_HDR_RX_CFG object and include a pointer to this object in the HTTP server instance configuration HTTPs_CFG object where the HdrRxCfgPtr parameter is defined. The same must be done with an HTTPs_HDR_TX_CFG object if your application wishes to add headers to HTTP responses. The HdrTxCfgPtr parameter of the HTTPs_CFG object must therefore be defined.

See section HTTP Header Configuration for additional details.

Hook Function#

The general HTTP Server Instance configuration structure (HTTPs_CFG) contains a pointer to an HTTPs_HOOK_CFG object. This object indexes all the hook functions required by your application.

For additional details on the configuration of hook functions, see section Hook Configuration .

To visualize when each hook function is called by the HTTP server core, see section Hook Functions .

In reception, the hook OnReqHdrRxHook() can be used to set which header field the application wishes to keep.

In transmission, the hook OnRespHdrTxHook() can be used to add a header field to the header list that the server will use to construct the HTTP response to send.

Usage#
Reception#

Once a HTTP request is received by the HTTP server, the server will call, if defined, the OnReqHdrRxHook() for each header fields received. The upper application must implement this hook to the return status DEF_YES when the header field must be saved and DEF_NO otherwise.

Transmission#

When the server is constructing an HTTP response to send, it will call the hook function OnRespHdrTxHook() when adding headers to the response. In this hook, the upper application can add header fields to the HTTP headers list by using the API function HTTPs_RespHdrGet(). This function will find a Header Field block available in the pool and add it to the list. The upper application just needs to fill the block fields afterwards.

HTTP Server Request Body Data#

The HTTP Server module has the capacity to parse forms received in a POST request body when the Form feature is enabled on the server instance. For more information, see section Form .

Forms are the only body parsing integrated in the server core. For your application to retrieve the body data of other requests (or even form's data when the feature is disabled) the server offers a hook function: On Request Body Received Hook .

CPU_BOOLEAN  HTTPs_ReqBodyRxHook (const  HTTPs_INSTANCE  *p_instance,
                                         HTTPs_CONN      *p_conn,
                                  const  void            *p_hook_cfg,
                                         void            *p_buf,
                                  const  CPU_SIZE_T       buf_size,
                                         CPU_SIZE_T      *p_buf_size_used);

This hook, if defined, will be called by the HTTP server each time new data is received in the server's internal buffer. With this hook function, the application has the liberty to copy the data received or to read it directly in the HTTP buffer to retrieve only the information needed. The application doesn't have the obligation to read all the data contained in the buffer. It MUST return the length of the data that was read (p_buf_size_used) and therefore, the next time around, the data not read will still be in the reception buffer. If the application doesn't want to receive more data, it can return DEF_NO at any time and data received afterward will be dropped by the server.

HTTP Server Form#

The HTTP Server module supports HTML form submissions through the POST method. The following POST Internet media type are supported:

  • "application/x-www-form-urlencoded" is the default format for encoding key-value pairs when a web browser sends a POST request from a web form element.

  • "multipart/form-data" is the format that must be used when uploading large amount of data such as a file on a web server.

For more information on HTML Forms, see section HTTP Form.

Configuration#

For the HTTP server to support processing of incoming form submissions, two types of configuration must be set up: the compile-time and the run-time configuration. Also, some hook functions must be defined to allow the application to retrieve the data received in the form.

Compile-time Configuration#

Two compile-time configuration macros are available for the form submissions: HTTPs_CFG_FORM_EN and HTTPs_CFG_FORM_MULTIPART_EN.

The first macro, if set to DEF_ENABLED, enables the Form feature and all the functions and data associated with it. Moreover, if the multipart form must be supported the second macro should also be enabled.

See section Module Configuration for more details.

Run-time Configuration#

The run-time configuration for Form submission is defined as a HTTPs_FORM_CFG structure. Your application must declare an HTTPs_FORM_CFG object and include a pointer to this object in the HTTP server instance configuration HTTPs_CFG object where the FormCfgPtr parameter is defined.

See section HTTP Form Configuration for additional details.

Hook Functions#

The general HTTP Server Instance configuration structure (HTTPs_CFG) contains a pointer to an HTTPs_HOOK_CFG object. This object indexes all the hook functions required by your application.

For additional details on the configuration of hook functions, see section Hook Configuration.

To visualize when each hook function is called by the HTTP server core, see section Hook Functions.

The hook function OnReqRdySignalHook() can be used to access the data received inside the form. The data is located under a list of key-value pairs (parameter FormDataListPtr) inside the HTTPs_CONN object. If a lot of processing must be done with the data received, it is recommend not to do it inside the OnReqRdySignalHook() hook because it will slow down all the other connection processing. Instead, the OnReqRdySignalHook() hook should be used to signal another task that the data was received and is ready to be processed. In that case, the hook function OnReqRdyPollHook () should be used to indicate to the server when the data processing is completed. When defined, the server will call the OnReqRdyPollHook () hook until the function returns the status Ok to indicate that the processing is finished.

Usage#

When the form is posted, the web server will process the POST action and will invoke the callback with a list of key-value pairs transmitted.

Assuming the HTML page that look like this:

Listing - HTML Page Example Application Form#
<html>
  <body>
    <form action="form_return_page.htm" method="post">
      Text Box 1: <input type="text" name="textbox1" />
      Text Box 2: <input type="text" name="textbox1" />
      <input type="submit" name="submit" value="Submit"></input>
    </form>
  </body>
</html>

The HTTP server core will receive the POST request and save the form data inside a key-value pairs list (FormDataListPtr parameter of the HTTPs_CONN structure). The server will then call the hook function OnReqRdySignalHook() (of the HTTPs_HOOK_CFG object inside the HTTPs_CFG object) to allow the application to retrieve and process the data received. The key-value pairs inside the list will be:

Key: "textbox1", Value: "Text Box 1 value"

Key: "textbox2", Value: "Text Box 2 value"

Key: "submit", Value: "Submit"

Since all connections are processing within only one task it is very important that all hook functions are non-blocking and can be executed quickly.

If the upper application takes a while to complete the data processing, the upper application should implement a task where the data can be process. The task should be polled to know if the processing is completed with the OnReqRdyPollHook () hook.

Uploading files using the HTTP Server#

It is possible to use a HTML form to upload files on the file system using the HTTP Server. The following listing shows an example of HTML code that can be used to implement that functionality:

Listing - HTML Page Example Multipart Form#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html>
<head>
   <title>File Upload</title>
</head>
<body>
  <form action="File_Upload.htm"
        ENCTYPE="multipart/form-data"
        method="post">
    <p><b>Choose The file To Upload:</b>
      <input type="file" name="file_form_field_name" ></input></p>
    <p><input type="submit" name="Submit" value="Submit"></input></p>
  </form>
</body>
</html>

Multipart form type must absolutely be specified in the form tag. For example: \<form action="upload.html" ENCTYPE="multipart/form-data" method="post"\>

When the file upload feature is enabled (parameter MultipartFileUploadEn inside the run-time configuration), the HTTP Server instance writes the file to the default location specified by the run-time configuration. If no error occurred when writing the file a key-value pair will be added to the list to specify the HTML control name of the field and the absolute location of the uploaded file. Thus, the upper application can easily retrieve or even move any file transmitted when the OnReqRdySignalHook() function is called. For example, for the upper listing, the key value pair list will contain the following:

Key: "file_form_field_name", Value: "||Path|RemoteFileName.html"

Key: "submit", Value: "Submit"

If an error occurs during the file transfer such as inability to open or write the file, the OnReqRdySignalHook() function is not called, and the upper application is notified by the Error hook function.

Note that the file upload is not possible using the static file system.

HTTP Server Response Body Data#

To configure and edit the response body data, the HTTP Server module offers three API functions:

HTTPs_RespBodySetParamFile()

This function can be used to transmit in the response body a file contained in a File System (a standard FS or the HTTP Static FS) . See section Specify File to Send in Response Body .

HTTPs_RespBodySetParamStaticData()

This function can be used to transmit data contained in an application buffer or also to specify that the data should be sent with the Chunked Transfer Encoding. See sections Send data contained in Application Buffer and Send data with the Chunk Hook .

HTTPs_RespBodySetParamNoBody()

This function can be used to specify that no body should be added in the HTTP response.

Those three API functions should be used by the upper application inside one of two hook functions: Connection Request and Request Ready Signal .

Specify File to Send in Response Body#

CPU_BOOLEAN App_OnReqHook (const HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, const void *p_hook_cfg){ RTOS_ERR err_https; HTTPs_RespBodySetParamFile(p_instance, p_conn, "index.html", HTTP_CONTENT_TYPE_HTML, DEF_NO, &err_https); return (DEF_YES);}

Send data contained in Application Buffer#

#define APP_BUF_LEN 20CPU_CHAR AppBuf[APP_BUF_LEN]; CPU_BOOLEAN App_OnReqHook (const HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, const void *p_hook_cfg){ RTOS_ERR err_https; Str_Copy_N(&AppBuf[0], "Hello World", APP_BUF_LEN); data_len = Str_Len_N(&AppBuf[0], APP_BUF_LEN); HTTPs_RespBodySetParamStaticData (p_instance, p_conn, HTTP_CONTENT_TYPE_PLAIN, &AppBuf[0], data_len, DEF_NO, &err_https); return (DEF_YES);}

Send data with the Chunk Hook#

CPU_BOOLEAN App_OnReqHook (const HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, const void *p_hook_cfg){ RTOS_ERR err_https; HTTPs_RespBodySetParamStaticData (p_instance, p_conn, HTTP_CONTENT_TYPE_JSON, DEF_NULL, 0, DEF_NO, &err_https); return (DEF_YES);} CPU_BOOLEAN HTTPs_RespChunkDataGetHook(const HTTPs_INSTANCE *p_instance, HTTPs_CONN *p_conn, const void *p_hook_cfg, void *p_buf, CPU_SIZE_T buf_len_max, CPU_SIZE_T *p_tx_len){}

HTTP Server Token Replacement#

The HTTP Server module allows dynamic content to be inserted in HTML and plain text documents by using special tokens being substituted before the page is actually sent to the web browser. There are two type of token: internal and external. The value of external token must be provided by the upper application via a hook function. Internal tokens are defined to print some data related to HTTP such as status lines and error codes.

Configuration#
Compile-time Configuration#

The macro configuration HTTPs_CFG_TOKEN_PARSE_EN inside the http_server_cfg.h file must be set to DEF_ENABLED to enable the token substitution feature.

See section Dynamic Content Configuration for more details on compile-time configuration.

Run-time Configuration#

The run-time configuration for Token Replacement is defined as a HTTPs_TOKEN_CFG structure. Your application must declare an HTTPs_TOKEN_CFG object and include a pointer to this object in the HTTP server instance configuration HTTPs_CFG object where the TokenCfgPtr parameter is defined.

See section Token Configuration for additional details.

Hook Configuration#

The HTTP Server Instance configuration structure (HTTPs_CFG) contains a pointer to an HTTPs_HOOK_CFG object. This object indexes all the hook functions required by your application.

For additional details on the configuration of hook functions, see section Hook Configuration .

To visualize when each hook function is called by the HTTP server core, see section Hook Functions .

The hook function OnRespTokenHook() must be used to set the value that will be used to replace the token found. Each time a token is found in the HTML/text file, the hook function will be called.

Usage#
External Token#

External tokens are represented in the HTML/text files as:

${TOKEN_NAME}

Assuming we have an HTML page that look like this:

<html><body><center> This system's IP address is ${My_IP_Address} </center></body></html>

When a web client requests this file, the HTTP Server will parse the file, find ${My_IP_Address} token, and pass the string "My_IP_Address" into the OnRespTokenHook() hook function. That function will copy the token value then the HTTP Server instance will send the token value instead of the token:

<html><body><center> This system's IP address is 135.17.115.215 </center></body></html>

Note that if the upper application doesn’t copy a valid data, the token is automatically replaced by ‘~’ characters. See Response Token Transmit Hook for more information on how the callback function has to be implemented to support this.

Internal Token#

Internal tokens are represented in the HTML files as:

#{TOKEN_NAME}

For every HTML document that must be transmitted, the HTTP Server parses the document and replaces all internal tokens automatically without calling any callback function. Internal token can be use in any HTML/text documents. Here is the list of built-in token replacement:

Token

Value

#{STATUS_CODE}

Replaced by status code number of the connection.

#{REASON_PHRASE}

Replaced by the reason phrase based on the status code of the connection

HTTP Server Proxy#

The HTTP Server module can be accessed behind a proxy. When an HTTP Server is behind a HTTP Proxy, the HTTP client must send its requests using an absolute URI. For example,

GET http://example.com/index.html HTTP/1.1

When the absolute URI feature is enable, the HTTP server will support absolute URI in the first line of the HTTP request messages.

The server will also look for the Host header field in the received request messages and save it in the .HostPtr field of the HTTPs_CONN structure.

HTTP Server Add-on#

The HTTP Server module offers different add-on to simplify complex HTTP server application development.

Add-on Module

Description

Control Layer

The Control Layer is a module bound to the HTTP Server by its hook functions and used to manage multiple groups of authentication process and application process.

Authentication

This module basically implements an authentication and authorization process based on the HTTP cookie header. It is made to work with the Control Layer only.

REST

This module was created to facilitate the development of RESTful applications. Its allows you to create REST resources based on a specific URL. Each resource has its own set of hook functions with a different hook for each HTTP method. It can be used with or without the Control Layer module.

HTTP Server Control Layer#
Introduction#

The control layer is a module bound to the HTTP Server used to manage multiple groups of authentication process and application process. There are many cases where one would like to have multiple functions bound to the same hook but with different goals. This is a the role of the Control layer.

The control layer maps each hook function available in the HTTP Server on its own hook. The configuration of those hooks has two layers: The Authentications and the Applications.

It provides an abstraction over the HTTPs_CONN's and HTTPs_INSTANCE's contextual data holders: p_instance->DataPtr and p_conn->ConnDataPtr. The Control Layer will automatically substitute them. Those contextual information are saved after each hook call and restored before each hook call. Which means that each Control Layer instance has its own connection and instance data pointers. The following diagram shows these context switches through color variance:

IntroductionIntroduction

Authentications#

The Authentications layer is the part of the configuration where one can specify how to hide an application, e.g., put your application behind a Login form. Each Control Layer configuration can have a list of authentications which must succeed in order to access any application of the same configuration.

Listing - Authentication structure#
typedef  struct  https_ctrl_layer_auth_hooks {
    HTTPs_INSTANCE_INIT_HOOK   OnInstanceInit;
    HTTPs_REQ_HDR_RX_HOOK      OnReqHdrRx;
    HTTPs_REQ_HOOK             OnReqAuth;
    HTTPs_RESP_HDR_TX_HOOK     OnRespHdrTx;
    HTTPs_TRANS_COMPLETE_HOOK  OnTransComplete;
    HTTPs_CONN_CLOSE_HOOK      OnConnClose;
} HTTPs_CTRL_LAYER_AUTH_HOOKS;

typedef  struct  https_ctrl_layer_auth_inst {
    HTTPs_CTRLLAYER_AUTH_HOOKS     *HooksPtr;
    void                           *HooksCfgPtr;
} HTTPs_CTRL_LAYER_AUTH_INST;

Therefore, for a given Control Layer configuration, many Authentication modules can be defined. Each module must declared its own HTTPs_CTRL_LAYER_AUTH_INST object that regroups a pointer to its own hook configuration (HTTPs_CTRL_LAYER_AUTH_HOOKS object) and a pointer to other configurations required by the module if necessary (See section HooksCfgPtr Parameter ).

Applications#

The Application layer is the part where HTTP requests can be analyze and HTTP responses will be built. At this point, the authentications required have passed already. The application layer handles both body parsing and body formatting. The application has full control over the HTTP Server response and is called every time the server needs to poll the hook to complete its task.

Listing - Application structures#
typedef  struct  https_ctrl_layer_app_hooks {
    HTTPs_INSTANCE_INIT_HOOK   OnInstanceInit;
    HTTPs_REQ_HDR_RX_HOOK      OnReqHdrRx;
    HTTPs_REQ_HOOK             OnReq;
    HTTPs_REQ_BODY_RX_HOOK     OnReqBodyRx;
    HTTPs_REQ_RDY_SIGNAL_HOOK  OnReqSignal;
    HTTPs_REQ_RDY_POLL_HOOK    OnReqPoll;
    HTTPs_RESP_HDR_TX_HOOK     OnRespHdrTx;
    HTTPs_RESP_TOKEN_HOOK      OnRespToken;
    HTTPs_RESP_CHUNK_HOOK      OnRespChunk;
  HTTPs_TRANS_COMPLETE_HOOK  OnTransComplete;
    HTTPs_ERR_HOOK             OnError;
    HTTPs_CONN_CLOSE_HOOK      OnConnClose;
} HTTPs_CTRL_LAYER_APP_HOOKS;

typedef  struct  https_ctrl_layer_app_inst {
    HTTPs_CTRL_LAYER_APP_HOOKS     *HooksPtr;
    void                           *HooksCfgPtr;
} HTTPs_CTRL_LAYER_APP_INST;

As for the Authentication Layer, a given Control Layer configuration can have many Application modules. each module must declared its own HTTPs_CTRL_LAYER_APP_INST object that regroups a pointer to its own hook configuration (HTTPs_CTRL_LAYER_APP_HOOKS object) and a pointer to other configurations required by the module if necessary (See section HooksCfgPtr Parameter ).

Configuration#
Demystify the HooksCfgPtr Parameter#

The HooksCfgPtr parameter will be passed as argument with each hook function from HooksPtr. Therefore, HooksCfgPtr parameter is offered to pass information necessary to specify the behavior of a given authentication instance or application instance. This information highly depends on the instance nature. If not necessary, the HooksCfgPtr parameter can be set to DEF_NULL.

HTTPs_CTRL_LAYER_CFG and HTTPs_CTRL_LAYER_CFG_LIST#

The control layer takes an HTTPs_CTRL_LAYER_CFG_LIST structure pointer as configuration. Below is the definition of the structures for the configuration of the Control Layer:

Listing - HTTPs_CTRLL_CFG and HTTPs_CTRLL_CFG_LIST#
/* Controlled service layer. */
typedef  struct  https_ctrl_layer_cfg {
    HTTPs_CTRL_LAYER_AUTH_INST     **AuthInstsPtr;
    CPU_SIZE_T                       AuthInstsNbr;
    HTTPs_CTRL_LAYER_APP_INST      **AppInstsPtr;
    CPU_SIZE_T                       AppInstsNbr;
} HTTPs_CTRL_LAYER_CFG;

/* List of controlled services. */
typedef  struct https_ctrl_layer_cfg_List {
    HTTPs_CTRL_LAYER_CFG  **CfgsPtr;
    CPU_SIZE_T              Size;
} HTTPs_CTRL_LAYER_CFG_LIST;

Here's an example how to declare a Control Layer configuration:

Listing - Control layer config example#
/* Define some authentication hook set. */
HTTPs_CTRL_LAYER_AUTH_HOOKS  AuthHooks    = { ... };

/* Create an auth instance based on the hook set and a user config pointer */
HTTPs_CTRL_LAYER_AUTH_INST   AuthInst     = { &AuthHooks, ... };

/* Define some application hook set */
HTTPs_CTRL_LAYER_APP_HOOKS   SomeAppHooks = { ... };

/*Create an app instance based on the hook set and a user config pointer */
HTTPs_CTRL_LAYER_APP_INST    SomeAppInst  = { &SomeAppHooks, ... };

/* List both authentications and applications */
HTTPs_CTRL_LAYER_AUTH_INST  *AuthInsts[]  = { &AuthInst };
HTTPs_CTRL_LAYER_APP_INST   *AppInsts[]   = { &SomeAppInst };

/* Create a config for the control layer */
HTTPs_CTRL_LAYER_CFG         SomeCfg      = {
        authInsts,
        sizeof(authInsts) / sizeof(HTTPs_CTRL_LAYER_AUTH_INST *),
        appInsts,
        sizeof(appInsts)  / sizeof(HTTPs_CTRL_LAYER_APP_INST *),
};

/* List the configurations. */
HTTPs_CTRL_LAYER_CFG        *CtrlLayerCfgs[] = { &SomeCfg };

/* Build the cfg structure for the control layer */
HTTPs_CTRL_LAYER_CFG_LIST    CtrlLayerCfgList= {
        CtrlLayerCfgs,
        sizeof(CtrlLayerCfgs) / sizeof(HTTPs_CTRL_LAYER_CFG *)
};
HTTP Server Hook Binding#

Here's an example of how to bind it to an HTTPs_CFG:

Listing - HTTPs_CFG using ControlLayer#
const  HTTPs_CFG  foo = {
    ...,

/*
*--------------------------------------------------------------------------------------------------------
*                                           HOOKS CONFIGURATION
*--------------------------------------------------------------------------------------------------------
*/
                                        /* Declared in HTTP/Server/Add-on/CtrlLayer/http-s_ctrl_layer.h  */
   &HTTPsCtrlLayer_HookCfg,             /* .HooksPtr                                                     */

                                      /* Previously declared in the configuration section                */
   &CtrlLayerCfgList,                 /* .Hooks_CfgPtr                                                   */

    ...
};
HTTP Server Authentication module#
Introduction#

The HTTP Server authentication system is built on top of the Control Layer. Without the control layer it wont work. It also requires the Authentication module of the Micrium OS Common libraries that defines the User Management.

There is two subsystems for this module: The Control Layer Authentication Layer and the Control Layer Application Layer.

Authentication Layer : Cookie Checker#

The cookie checker is basically a Control Layer instance bound to the Authentication layer. When a request is made without a valid cookie, it refuses to let it go and will take on the request. When a cookie is present and valid, the request is then checked to know which rights are required to continue. If the user bound to the cookie provided has the rights to continue, the request is marked as accepted.

Application Layer#
Unprotected Requests: Cookie Creator#

The cookie creator work after the cookie checker has done it's work and could not find a valid cookie. In that case, if the request is a POST with the "logme form", the request is "catched" and the parsed body is inspected to find a username and a password.This happens at the application phase of the Control Layer. If a username and a password is found within the request, it is then validated with known credentials from the user management layer. If a valid match is found, a session is created, the user is associated with it, and the cookie identifier is sent to the HTTP client.

Protected Requests#

Once the session was created, requests related to log in should not occurred, but for safety the Authentication module will still "catched" them. A request to the login page will be redirect to the default page. A POST request with the "logme form" will be parsed even though a session is already existing and if the credentials are incorrect the session will be terminated.

Session Timeout#

The Authentication module also configures a timer to periodically check if any created sessions have timed out. After a session timed out, a cookie received with the session ID number will be considered invalid and any not authorized requests will be redirect to the configured page for unauthorized requests.

How to Configure#

To configure the HTTP Server authentication, here are the steps to follow:

  1. Create users with their appropriate credentials and rights.

  2. Define an hook function which will return the right necessary to process a given request.

  3. Define an hook function which will check the requests received for a log in request but also set the pages for redirection for all of those requests.

  4. Define an hook function which will check the requests received for a log out request.

  5. Create the appropriate configurations and bind those three hook functions.

  6. Bind those configurations to their respective Control Layer Instance configuration.

  7. Use the three instances created in the Control Layer configuration.

Hook Functions#
Get Required Rights Hook#

This hook will be called by the Authentication Layer of the Control Layer when a request is received to check with the upper application what rights are associated with this request.

AUTH_RIGHT  HTTPsAuth_GetRequiredRightsHook (const  HTTPs_INSTANCE  *p_instance,
                                             const  HTTPs_CONN      *p_conn);
Login Hook#

This hook will be called by the Application Layer of the Control Layer to found requests related to the log in process, e.g., the GET requests for the resources of the log in page (html, css, images) and the POST request with the form log in. This hook functions will be called at two occasions : when the URL and headers of the request were received and parse by the server (state HTTPs_AUTH_STATE_REQ_URL), and also when the request body was received and parse (state HTTPs_AUTH_STATE_REQ_COMPLETE).

CPU_BOOLEAN  AppGlobal_Auth_ParseLoginHook (const  HTTPs_INSTANCE     *p_instance,
                                            const  HTTPs_CONN         *p_conn,
                                                   HTTPs_AUTH_STATE    state,
                                                   HTTPs_AUTH_RESULT  *p_result);
Logout Hook#

This hook will be called by the Application Layer of the Control Layer

CPU_BOOLEAN  AppGlobal_Auth_ParseLogoutHook (const  HTTPs_INSTANCE     *p_instance,
                                             const  HTTPs_CONN         *p_conn,
                                                    HTTPs_AUTH_STATE    state);
Example#

The output of the "How to" steps should look like the example provided:

Listing - Authentication Functions Examples#
/*
*********************************************************************************************************
*                                          AppGlobal_UsersInit()
*
* Description : Adds three users to the authentication system.
*
* Argument(s) : None.
*
* Return(s)   : DEF_OK,   if users initialization was successful.
*               DEF_FAIL, otherwise.
*
* Note(s)     : None.
*********************************************************************************************************
*/

CPU_BOOLEAN  AppGlobal_UsersInit(void)
{
    AUTH_USER    admin;
    AUTH_USER    user;
    AUTH_RIGHT   right;
    RTOS_ERR     err_auth;
    CPU_BOOLEAN  result;

    result = Auth_Init(&err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    result = Auth_CreateUser("admin",
                             "password",
                             &admin,
                             &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    right = (HTTP_USER_ACCESS | AUTH_RIGHT_MNG);
    result = Auth_GrantRight(right,
                            &admin,
                            &Auth_RootUser,
                            &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }
    result = Auth_CreateUser("user0",
                             "",
                             &user,
                             &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    result = Auth_GrantRight(HTTP_USER_ACCESS,
                            &user,
                            &admin,
                            &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    result = Auth_CreateUser("user1",
                             "user1",
                             &user,
                             &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    result = Auth_GrantRight(HTTP_USER_ACCESS,
                            &user,
                            &admin,
                            &err_auth);
    if (result != DEF_OK) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

/*
*********************************************************************************************************
*                                    AppGlobal_Auth_GetRequiredRightsHook()
*
* Description : Returns the rights required to fulfill the needs of a given request.
*
* Argument(s) : p_instance  Pointer to the HTTP server instance object.
*
*               p_conn      Pointer to the HTTP connection object.
*
* Return(s)   : returns the authorization right level for this example application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

AUTH_RIGHT  AppGlobal_Auth_GetRequiredRightsHook (const  HTTPs_INSTANCE  *p_instance,
                                                  const  HTTPs_CONN      *p_conn)
{
    return (HTTP_USER_ACCESS);
}

/*
*********************************************************************************************************
*                                     AppGlobal_Auth_ParseLoginHook()
*
* Description : (1) Check the HTTP requests received to see if they are related to resources of the login page.
*                   (a) Check if the POST login is received.
*                   (b) For each request set the redirect paths on no, invalid & valid credentials.
*                   (c) Parse the form fields received in the body for the user and password.
*
*
* Argument(s) : p_instance  Pointer to the HTTP server instance object.
*
*               p_conn      Pointer to the HTTP connection object.
*
*               state       State of the Authentication module:
*                               HTTPs_AUTH_STATE_REQ_URL:      The URL and the headers were received and parse.
*                               HTTPs_AUTH_STATE_REQ_COMPLETE: All the request (URL + headers + body)
*                                                              was received and parse.
*
*               p_result    Pointer to the authentication result structure to fill.
*
* Return(s)   : DEF_YES, if the request is the POST login.
*               DEF_NO,  otherwise.
*
* Note(s)     : (2) This hook will be called twice for a request processed by the Authentication module:
*                   (a) When the Start line of the request (with the URL) and the headers have been
*                       received and parse -> HTTPs_AUTH_STATE_REQ_URL state.
*                   (b) When all the request has been completely received and parse including the body
*                       -> HTTPs_AUTH_STATE_REQ_COMPLETE state.
*
*               (3) for each request received the redirect paths is set as follow:
*                   (a) RedirectPath_OnValidCred    INDEX_PAGE_URL
*                   (b) RedirectPath_OnInvalidCred  LOGIN_PAGE_URL
*                   (c) RedirectPath_OnNoCred
*                       (1) if the path is an unprotected path, let it go. (DEF_NULL) (i.e., the logo)
*                       (2) otherwise               LOGIN_PAGE_URL
*********************************************************************************************************
*/

CPU_BOOLEAN  AppGlobal_Auth_ParseLoginHook (const  HTTPs_INSTANCE     *p_instance,
                                            const  HTTPs_CONN         *p_conn,
                                                   HTTPs_AUTH_STATE    state,
                                                   HTTPs_AUTH_RESULT  *p_result)
{
    CPU_INT16S      cmp_val;
    CPU_BOOLEAN     is_login = DEF_NO;
#if (HTTPs_CFG_FORM_EN == DEF_ENABLED)
    HTTPs_KEY_VAL  *p_current;
    CPU_INT16S      cmp_val_username;
    CPU_INT16S      cmp_val_password;
#endif
    p_result->UsernamePtr = DEF_NULL;
    p_result->PasswordPtr = DEF_NULL;

                                                                /* Set redirect paths for each requests.       */
    p_result->RedirectPathOnInvalidCredPtr = LOGIN_PAGE_URL;
    p_result->RedirectPathOnValidCredPtr   = INDEX_PAGE_URL;

    switch (state) {
                                                                /* ----------- REQUEST URL RECEIVED ---------- */
        case HTTPs_AUTH_STATE_REQ_URL:
                                                                /* Set redirect paths for each requests.       */
             cmp_val = Str_Cmp(p_conn->PathPtr, LOGIN_PAGE_URL);
             if (cmp_val != 0) {
                 cmp_val = Str_Cmp(p_conn->PathPtr, MICRIUM_LOGO_URL);
                 if (cmp_val != 0) {
                     cmp_val = Str_Cmp(p_conn->PathPtr, MICRIUM_CSS_URL);
                 }
             }
             p_result->RedirectPathOnNoCredPtr = (cmp_val == 0) ? DEF_NULL : LOGIN_PAGE_URL;
                                                                /* Check if POST login received.               */
             cmp_val = Str_Cmp(p_conn->PathPtr, LOGIN_PAGE_CMD);
             if (cmp_val == 0) {
                 is_login = DEF_YES;
             }
             break;
                                                                /* ---------- REQUEST BODY RECEIVED ---------- */
        case HTTPs_AUTH_STATE_REQ_COMPLETE:
#if (HTTPs_CFG_FORM_EN == DEF_ENABLED)
                                                                /* Parse form fields received for user/pass.   */
             p_current = p_conn->FormDataListPtr;
             while ((p_current              != DEF_NULL)  &&
                    ((p_result->UsernamePtr == DEF_NULL)  ||
                     (p_result->PasswordPtr == DEF_NULL))) {
                 if (p_current->DataType == HTTPs_KEY_VAL_TYPE_PAIR) {
                     cmp_val_username = Str_CmpIgnoreCase_N(p_current->KeyPtr,
                                                            FORM_USERNAME_FIELD_NAME,
                                                            p_current->KeyLen);
                     cmp_val_password = Str_CmpIgnoreCase_N(p_current->KeyPtr,
                                                            FORM_PASSWORD_FIELD_NAME,
                                                            p_current->KeyLen);
                     if (cmp_val_username == 0) {
                         p_result->UsernamePtr = p_current->ValPtr;
                         is_login = DEF_YES;
                     } else if (cmp_val_password == 0) {
                         p_result->PasswordPtr = p_current->ValPtr;
                     }
                 }
                 p_current = p_current->NextPtr;
             }
#endif
             break;

        default:
             break;
    }

    return (is_login);
}

/*
*********************************************************************************************************
*                                     AppGlobal_Auth_ParseLogoutHook()
*
* Description : Parse requests received for logout URL and form data logout info.
*
* Argument(s) : p_instance  Pointer to HTTPs instance object.
*
*               p_conn      Pointer to HTTPs connection object.
*
*               state       State of the Authentication module:
*                               HTTPs_AUTH_STATE_REQ_URL:      The URL and the headers were received and parse.
*                               HTTPs_AUTH_STATE_REQ_COMPLETE: All the request (URL + headers + body) w
*                                                              as received and parse.
*
* Return(s)   : DEF_YES, if Logout received.
*               DEF_NO,  otherwise.
*
* Caller(s)   : AppGlobal_AppInst_AuthCfg.
*
* Note(s)     : (1) This hook will be called twice for a request processed by the Authentication module:
*                   (a) When the Start line of the request (with the URL) and the headers have been
*                       received and parse -> HTTPs_AUTH_STATE_REQ_URL state.
*                   (b) When all the request has been completely received and parse including the body
*                       -> HTTPs_AUTH_STATE_REQ_COMPLETE state.
*********************************************************************************************************
*/

CPU_BOOLEAN  AppGlobal_Auth_ParseLogoutHook (const  HTTPs_INSTANCE    *p_instance,
                                             const  HTTPs_CONN        *p_conn,
                                                    HTTPs_AUTH_STATE   state)
{
    CPU_BOOLEAN     is_logout = DEF_NO;
#if (HTTPs_CFG_FORM_EN == DEF_ENABLED)
    HTTPs_KEY_VAL  *p_current;
    CPU_INT16S       cmp_val;
#endif

    switch (state) {
                                                                /* ----------- REQUEST URL RECEIVED ---------- */
        case HTTPs_AUTH_STATE_REQ_URL:
                                                                /* Check if POST logout received.              */
             cmp_val = Str_Cmp(p_conn->PathPtr, LOGOUT_PAGE_CMD);
             if (cmp_val == 0) {
                 is_logout = DEF_YES;
             }
             break;
                                                                /* ---------- REQUEST BODY RECEIVED ---------- */
        case HTTPs_AUTH_STATE_REQ_COMPLETE:
#if (HTTPs_CFG_FORM_EN == DEF_ENABLED)
                                                                /* Parse form fields received for logout.      */
             p_current = p_conn->FormDataListPtr;
             while (p_current != DEF_NULL) {
                 if (p_current->DataType == HTTPs_KEY_VAL_TYPE_PAIR) {
                     cmp_val = Str_CmpIgnoreCase_N(p_current->KeyPtr,
                                                   FORM_LOGOUT_FIELD_NAME,
                                                   p_current->KeyLen);
                     if (cmp_val == 0) {
                         is_logout = DEF_YES;
                         break;
                     }
                 }
                 p_current = p_current->NextPtr;
             }
#endif
             break;

        default:
             break;
    }

    return (is_logout);
}

Code Block 1 Authentication Configuration Variables

 /********************************************************************************************************************************************************************************************************************GLOBAL VARIABLES*******************************************************************************************************************************************************************************************************************/

 HTTPs_AUTHORIZATION_CFG  HTTPs_AppGlobal_AuthInst_Cfg = {        AppGlobal_Auth_GetRequiredRightsHook};
 HTTPs_AUTH_CFG  HTTPs_AuthAppCfg = {        AppGlobal_Auth_ParseLoginHook,        AppGlobal_Auth_ParseLogoutHook};
 HTTPs_CTRL_LAYER_AUTH_INST  AppGlobal_AuthInst = {        &HTTPsAuth_CookieHooksCfg,        &AppGlobal_AuthInst_Cfg};
 HTTPs_CTRL_LAYER_APP_INST  AppGlobal_AppInst_AuthUnprotected = {        &HTTPsAuth_AppUnprotectedCookieHooksCfg,        &AppGlobal_AppInst_AuthCfg};
 HTTPs_CTRL_LAYER_APP_INST  AppGlobal_AppInst_AuthProtected = {       &HTTPsAuth_AppProtectedCookieHooksCfg,                       &AppGlobal_AppInst_AuthCfg  };
HTTP Server REST module#
Introduction#

The REST Framework is built to be either used on top of the Control layer or the server core itself. It remaps the HTTP Server hooks or the applicative Control Layer hooks on a single hook per HTTP request method. This single method is called an HTTPs_REST_HOOK.

The REST Framework is designed to ease the production of simple web service applications. HTTP requests are made to perform actions on web resources. Inside your REST framework, those resources are mapped to HTTPs_REST_RESOURCE objects.

REST Resource#

A resource is associated with a specific path. REST Resources are accessible through path pattern matching and specifies the method supported and the headers needed. Here's the structure defining them:

Listing - REST Resource Structure#
typedef  struct  https_rest_resource {
    const   CPU_CHAR                 *PatternPtr;      /* Access path to the resource ending with an EOF char. */
    const   HTTP_HDR_FIELD           *HTTP_Hdrs;       /* List of HTTP headers to keep.                        */
    const   CPU_SIZE_T                HTTP_HdrsNbr;    /* Number of HTTP headers in the list.                  */
    const   HTTPs_REST_METHOD_HOOKS   MethodHooks;     /* Hooks Configuration for the resource.                */
}  HTTPs_REST_RESOURCE;
Hooks Configuration#

Each REST resource has its own set of hook functions. Like mentioned before, there is one hook per HTTP method, but the hook pointer can be set to DEF_NULL in the configuration if not needed for the given resource.

Listing - REST Hooks Configuration Structure#
typedef  struct  https_rest_method_hooks {
    HTTPs_REST_HOOK_FNCT  Delete;
    HTTPs_REST_HOOK_FNCT  Get;
    HTTPs_REST_HOOK_FNCT  Head;
    HTTPs_REST_HOOK_FNCT  Post;
    HTTPs_REST_HOOK_FNCT  Put;
} HTTPs_REST_METHOD_HOOKS;

Below is the prototype for REST hook functions:

Listing - Definition of HTTPs_REST_HOOK_FNCT#
typedef  HTTPs_REST_HOOK_STATE  (*HTTPs_REST_HOOK_FNCT)  (const  HTTPs_REST_RESOURCE      *p_resource,
                                                          const  HTTPs_REST_MATCHED_URI   *p_uri,
                                                          const  HTTPs_REST_STATE          state,
                                                                 void                    **p_data,
                                                          const  HTTPs_INSTANCE           *p_instance,
                                                                 HTTPs_CONN               *p_conn,
                                                                 void                     *p_buf,
                                                          const  CPU_SIZE_T                buf_size,
                                                                 CPU_SIZE_T               *p_buf_size_used);

Each hook is map on multiple hooks of the server core or Control Layer, therefore the same REST hook will be called many times during an HTTP transaction processing. To differentiate at which moment the REST hook is being called, a state variable HTTPs_REST_STATE is passed to the hook function. The table below presents a mapping of the HTTPS_REST_STATE with the corresponding HTTP server hooks.

REST STATE

Hook Function in REST Module

HTTP Server Hook

Control Layer Application Hook

HTTPs_REST_STATE_INIT

HTTPsREST_Authenticate()

(HTTPs_HOOK_CFG *)->OnReqHook()

(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnReq()

HTTPs_REST_STATE_RX

HTTPsREST_RxBody()HTTPsREST_ReqRdySignal()

(HTTPs_HOOK_CFG *)->OnReqBodyRxHook()(HTTPs_HOOK_CFG *)->OnReqRdySignalHook() with argument buf_size == 0

(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnReqBodyRx()(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnReqSignal()

HTTPs_REST_STATE_TX

HTTPsREST_GetChunk()

(HTTPs_HOOK_CFG *)->OnRespChunkHook()

(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnRespChunk()

HTTPs_REST_STATE_CLOSE

HTTPsREST_OnTransComplete()HTTPsREST_OnConnClosed()

(HTTPs_HOOK_CFG *)->OnTransCompleteHook()(HTTPs_HOOK_CFG *)->OnConnCloseHook()

(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnTransComplete()(HTTPs_CTRL_LAYER_APP_HOOKS *)->OnConnClose()

URI Pattern Matching#

The URI pattern matching of this framework is quite primitive and shines by its simplicity. The URI is divided into two sections: the separator and the path component. This leads to the following rules:

  • The pattern string must start with a separator.

  • The pattern string must end with a '\0'

  • A wild card can only be used between a separator and another separator or at the end of the pattern string.

  • A wild card will not match a separator char unless the wild card is the last component of the pattern string.

URI Path Separator#

The separator within the pattern string is exactly the same that must be found according to rfc3986 : '/'. This character cannot be escaped and can't be used in any other context.

URI Path Component#

A URI path component is the element between two path separator or between a path separator and the end of the pattern string. This element can either be a wild card or text.

Wild Cards#

The wild card begins with a { and ends with a }. A wild card cannot contain another wild card. The element between the curly brackets is used as the wild card token key.

URI Pattern and Match Examples#

URI Pattern and Match ExamplesURI Pattern and Match Examples

Publish REST Resources#

Once a resource has been created, in order to make a resource accessible through the REST Framework, two steps must be followed. The first one is to call the HTTPsREST_Publish() function which will add the resource to the specified list. Then that list of resources is used in the configuration of the HTTP server.

This function can only be called after the HTTP server initialization and before the HTTP server start. Also, the HTTPsREST_Init() function must be bound to the HTTP server or to the Control layer prior the initialization. Otherwise, the REST memory pools won't be initialized and the resource lists cannot be created.

REST Configuration#

No matter which layer REST is bound to, the HTTP Server core or the Control Layer, you need to provide a HTTPs_REST_CFG structure. That structure is used to configure the REST framework behavior for that specific instance.

Listing - REST Configuration Structure#
typedef  struct  https_rest_cfg {
    const  CPU_INT32U   ListID;
}  HTTPs_REST_CFG;
Listing - Server Instance Configuration Example for REST Application#
/*
*********************************************************************************************************
*                                         REST HOOKS CONFIGURATION
*********************************************************************************************************
*/

const  HTTPs_REST_CFG HTTPs_REST_Cfg = { 0 };       /* 0 is the list ID number. The same used in  */
                                                        /* the resources publishing.                  */

const  HTTPs_HOOK_CFG HTTPs_REST_HookCfg = {
        HTTPsREST_Init,
        HTTPsREST_RxHeader,
        HTTPsREST_Authenticate,
        HTTPsREST_RxBody,
        HTTPsREST_ReqRdySignal,
        DEF_NULL,
        DEF_NULL,
        DEF_NULL,
        HTTPsREST_GetChunk,
        HTTPsREST_OnTransComplete,
        DEF_NULL,
        DEF_NULL,
        HTTPsREST_OnConnClosed
};

/*
*********************************************************************************************************
*                               HTTP SERVER INSTANCE CONFIGURATION
*********************************************************************************************************
*/

const  HTTPs_CFG  AppEx_HTTPsInstanceCfg = {

  ...

/*
*---------------------------------------------------------------------------------
*                                      HOOK CONFIGURATION
*---------------------------------------------------------------------------------
*/

   &HTTPs_REST_HookCfg,                         /* .HooksPtr     */

   &HTTPs_REST_Cfg,                 /* .Hooks_CfgPtr */

    ...
};

The REST Hook Configuration variable HTTPs_REST_HookCfg and the variable HTTPs_REST_Cfg are given in a template file inside the REST module source code (http_server_rest_hook_cfg.c/h). You can use it has-is for your REST application or you can make your own if you don't need all the hooks to be defined. In the above example, the REST module is used directly on top of the HTTP server core, if you want to use it with the Control Layer, a template Control Layer hooks configuration for REST is also given inside the Control Layer add-on module source code (http_server_ctrl_layer_rest_cfg.c/h).

How to Use REST Module#
  1. Create your REST resource(s) in your application.

  2. Define the necessary hook functions for each HTTP method of each resource and set the hook configuration inside the REST resource declaration.

  3. Set the REST configuration for the server instance configuration or the Control Layer configuration.

  4. Use the API function HTTPsREST_Publish() between the HTTPs_InstanceInit() and HTTPs_InstanceStart() to publish all your REST resources inside the global resources list.

Example#

See the complete REST application available in the Example directory (see section HTTP Server Example Applications for more details).

HTTP Server Protocol Recognized Fields#

This section regroups lists of all the HTTP fields recognized by Micrium OS HTTP Server module.

HTTP Versions#

HTTP Version

Micrium Type

0.9

HTTP_PROTOCOL_VER_0_9

1.0

HTTP_PROTOCOL_VER_1_0

1.1

HTTP_PROTOCOL_VER_1_1

HTTP Methods#

HTTP Method

Micrium Type

CONNECT

HTTP_METHOD_CONNECT

DELETE

HTTP_METHOD_DELETE

GET

HTTP_METHOD_GET

HEAD

HTTP_METHOD_HEAD

OPTIONS

HTTP_METHOD_OPTIONS

POST

HTTP_METHOD_POST

PUT

HTTP_METHOD_PUT

TRACE

HTTP_METHOD_TRACE

Those are the methods recognized by the HTTP Server and Client stacks. It doesn't mean that all those methods are supported.

HTTP Header Fields#

Header Field Type

Micrium Type

Content-Type

HTTP_HDR_FIELD_CONTENT_TYPE

Content-Length

HTTP_HDR_FIELD_CONTENT_LEN

Content-Disposition

HTTP_HDR_FILED_CONTENT_DISPOSITION

Host

HTTP_HDR_FIELD_HOST

Location

HTTP_HDR_FIELD_LOCATION

Connection

HTTP_HDR_FIELD_CONN

Transfer-Encoding

HTTP_HDR_FIELD_TRANSFER_ENCODING

Accept

HTTP_HDR_FIELD_ACCEPT

Accept-Charset

HTTP_HDR_FIELD_ACCEPT_CHARSET

Accept-Encoding

HTTP_HDR_FIELD_ACCEPT_ENCODING

Accept-Language

HTTP_HDR_FIELD_ACCEPT_LANGUAGE

Accept-Ranges

HTTP_HDR_FIELD_ACCEPT_RANGES

Age

HTTP_HDR_FIELD_AGE

Allow

HTTP_HDR_FIELD_ALLOW

Authorization

HTTP_HDR_FIELD_AUTHORIZATION

Content-Encoding

HTTP_HDR_FIELD_CONTENT_ENCODING

Content-Language

HTTP_HDR_FIELD_CONTENT_LANGUAGE

Content-Location

HTTP_HDR_FIELD_CONTENT_LOCATION

Content-MD5

HTTP_HDR_FIELD_CONTENT_MD5

Content-Range

HTTP_HDR_FIELD_CONTENT_RANGE

Cookie

HTTP_HDR_FIELD_COOKIE

Cookie2

HTTP_HDR_FIELD_COOKIE2

Date

HTTP_HDR_FIELD_DATE

ETag

HTTP_HDR_FEILD_ETAG

Expect

HTTP_HDR_FIELD_EXPECT

Expires

HTTP_HDR_FIELD_EXPIRES

From

HTTP_HDR_FIELD_FROM

If-Modified-Since

HTTP_HDR_FIELD_IF_MODIFIED_SINCE

If-Match

HTTP_HDR_FIELD_IF_MATCH

If-None-Match

HTTP_HDR_FIELD_IF_NONE_MATCH

If-Range

HTTP_HDR_FIELD_IF_RANGE

If-Unmodified-Since

HTTP_HDR_FIELD_IF_UNMODIFIED_SINCE

Last-Modified

HTTP_HDR_FIELD_LAST_MODIFIED

Range

HTTP_HDR_FIELD_RANGE

Referrer

HTTP_HDR_FIELD_REFERER

Retry-After

HTTP_HDR_FIELD_RETRY_AFTER

Server

HTTP_HDR_FIELD_SERVER

Set-Cookie

HTTP_HDR_FIELD_SET_COOKIE

Set-Cookie2

HTTP_HDR_FIELD_SET_COOKIE2

TE

HTTP_HDR_FIELD_TE

Trailer

HTTP_HDR_FIELD_TRAILER

Upgrade

HTTP_HDR_FIELD_UPGRATE

User-Agent

HTTP_HDR_FIELD_USER_AGENT

Vary

HTTP_HDR_FIELD_VARY

Via

HTTP_HDR_FIELD_VIA

Warning

HTTP_HDR_FIELD_WARNING

WWW-Authenticate

HTTP_HDR_FIELD_WWW_AUTHENTICATE

If a header is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

HTTP Content Types#

MIME Content Type

File Extension

Micrium Type

text/html

.html

HTTP_CONTENT_TYPE_HTML

application/octet-stream

.bin

HTTP_CONTENT_TYPE_OCTET_STREAM

application/pdf

.pdf

HTTP_CONTENT_TYPE_PDF

application/zip

.zip

HTTP_CONTENT_TYPE_ZIP

image/gif

.gif

HTTP_CONTENT_TYPE_GIF

image/jpeg

.jpeg, .jpg

HTTP_CONTENT_TYPE_JPEG

image/png

.png

HTTP_CONTENT_TYPE_PNG

application/javascript

.js

HTTP_CONTENT_TYPE_JS

text/plain

.txt

HTTP_CONTENT_TYPE_PLAIN

text/css

.css

HTTP_CONTENT_TYPE_CSS

application/json

.json

HTTP_CONTENT_TYPE_JSON

application/x-www-form-urlencoded

-

HTTP_CONTENT_TYPE_APP_FORM

multipart/form-data

-

HTTP_CONTENT_TYPE_MULTIPART_FORM

If a Content Type is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

HTTP Status Codes#

HTTP Status Code

Micrium Type

200

HTTP_STATUS_OK

201

HTTP_STATUS_CREATED

202

HTTP_STATUS_ACCEPTED

204

HTTP_STATUS_NO_CONTENT

205

HTTP_STATUS_RESET_CONTENT

301

HTTP_STATUS_MOVED_PERMANENTLY

302

HTTP_STATUS_FOUND

303

HTTP_STATUS_SEE_OTHER

304

HTTP_STATUS_NOT_MODIFIED

305

HTTP_STATUS_USE_PROXY

307

HTTP_STATUS_TEMPORARY_REDIRECT

400

HTTP_STATUS_BAD_REQUEST

401

HTTP_STATUS_UNAUTHORIZED

403

HTTP_STATUS_FORBIDDEN

404

HTTP_STATUS_NOT_FOUND

405

HTTP_STATUS_METHOD_NOT_ALLOWED

406

HTTP_STATUS_NOT_ACCEPTABLE

408

HTTP_STATUS_REQUEST_TIMEOUT

409

HTTP_STATUS_CONFLICT

410

HTTP_STATUS_GONE

411

HTTP_STATUS_LENGTH_REQUIRED

412

HTTP_STATUS_PRECONDITION_FAILED

413

HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE

414

HTTP_STATUS_REQUEST_URI_TOO_LONG

415

HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE

416

HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE

417

HTTP_STATUS_EXPECTATION_FAILED

500

HTTP_STATUS_INTERNAL_SERVER_ERR

501

HTTP_STATUS_NOT_IMPLEMENTED

503

HTTP_STATUS_SERVICE_UNAVAILABLE

505

HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED

If a Status Code is missing for your application, contact your sales representative so that it can be included in subsequent release of Micrium OS.

MQTT Client Module#

The Micrium OS MQTT Client allows your application to access MQTT servers and perform actions on resources stored on a server.

In an embedded environment, an MQTT client is used to publish values such as sensor data to a topic, and receive messages by subscribing to topics.

MQTT Client Overview#

The MQTT Client module allows your application to access MQTT brokers (also know as MQTT servers). Your application can publish messages and subscribe to topics of interest so that it can receive messages from other MQTT clients.

The MQTT Client module has been designed to have a very small memory footprint and be simple to use. It provides an API that is similar to other Micrium products, allowing you to start developing quickly.

The MQTT-client supports:

  • Multiple messages on same or different topics at the same time

  • Multiple connections to multiple servers

  • Every type of messages defined by the MQTT specifications V3.1 and V3.1.1, including the three levels of QoS for PUBLISH messages

See the section MQTT-client Message Types Supported for additional details on each feature.

Memory Usage#

MQTT client applications can have dramatically different memory requirements. For example, some applications will require a connection to only one server, while others may require more; some applications will prefer to allocate objects on their own stack, while others will want to use a memory pool on the heap. So to meet all of these different requirements, the MQTT client does not have its own memory module.

As a result, all the objects required by the MQTT client must be passed by the application. This includes a single MQTTc_MSG object that will be used to receive any incoming PUBLISH message from the server. For any message the application wishes to send to the server, an MQTTc_MSG object must also be provided. Each MQTTc_MSG object must have its own buffer, with a size varying from a few bytes for very simple messages to a few of hundred bytes for complex messages.

It is important that every object passed by the application to the MQTT-Client stay valid for the duration of the MQTT message (until the callback is called) or until the connection is closed for the MQTTc Connection Object using that message.

Internal Task#

To support multiple simultaneous connections, the MQTT Client module has a dedicated internal task. This task also allows the queuing of multiple messages on a given connection.

Auto Select Remote IP address#

When the DNS Client is present, the MQTT-Client can accept a hostname string to connect to the remote server. IP address resolution will be performed by a DNS server. If the DNS server sends back IPv4 and IPv6 addresses, the first attempt will be to use the IPv6 address to connect to the remote MQTT server. If this connection fails the IPv4 address will be used instead.

When the DNS Client is not present, you must pass an IPv4 or IPv6 remote address in string form to the MQTT-Client.

With its compile-time configuration, MQTT's code footprint can be adjusted to fit your application's requirements by enabling/disabling features.

MQTT Client Example Applications#

This section describes the examples application provided for the MQTT Client module of Micrium OS.

MQTT Client Initialization Example#

Description#

This is a generic example that shows how to initialize the MQTT client module. It accomplishes the following tasks:

  • Change default task's stacks size, if specified by the example configuration

  • Initialize the MQTTClient module

  • Change default the task's priority, if specified by the example configuration

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the HTTP Server module correctly:

#define

Description

EX_MQTT_CLIENT_INIT_AVAIL

Lets the upper example layer know that the Network Initialization example is present and must be called by other examples.

Location#
/examples/net/mqtt/ex_mqtt_client_init.c

/examples/net/mqtt/ex_mqtt_client.h
API#

API

Description

Ex_MQTT_Client_Init()

Initialize the MQTT Client stack for the example application.

Notes#

None.

MQTT Client Connect Example#

Description#

This is a generic example for the MQTT Client module. It shows how to connect to a broker.

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_MQTTc_BROKER_NAME

"mqtt.micrium.com"

Specify the broker hostname

EX_MQTTc_USERNAME

"micrium"

Specify the username

EX_MQTTc_PASSWORD

"micrium"

Specify the password

EX_MQTTc_CLIENT_ID_NAME

"micrium-example-basic"

Specify another client ID

EX_MQTTc_MSG_LEN_MAX

128

Specify the message maximum length

EX_TRACE

printf(VA_ARGS)

Specify where to output information about the example

Location#
/examples/net/mqtt/ex_mqtt_client_connect.c

/examples/net/mqtt/ex_mqtt_client.h
API#

API

Description

Ex_MQTT_Client_Connect()

Connect the client to the broker.

Notes#

None.

MQTT Client Publish Example#

Description#

This is a generic example for the MQTT Client module. It accomplishes the following tasks:

  • Connect to a broker

  • Publish message on a topic

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_MQTTc_BROKER_NAME

"mqtt.micrium.com "

Specify the broker hostname

EX_MQTTc_USERNAME

"micrium"

Specify the username

EX_MQTTc_PASSWORD

"micrium"

Specify the password

EX_MQTTc_CLIENT_ID_NAME

"micrium-example-publish"

Specify another client ID

Location#
/examples/net/mqtt/ex_mqtt_client_publish.c

/examples/net/mqtt/ex_mqtt_client.h
API#

API

Description

Ex_MQTT_Client_Publish()

Open a connection and publish message from the callback

Notes#

None.

MQTT Client Subscribe Example#

Description#

This is a generic example for the MQTT Client module. It accomplishes the following tasks:

  • Connect to a broker

  • Subscribe to a topic

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_MQTTc_BROKER_NAME

"mqtt.micrium.com "

Specify the broker hostname

EX_MQTTc_USERNAME

"micrium"

Specify the username

EX_MQTTc_PASSWORD

"micrium"

Specify the password

EX_MQTTc_CLIENT_ID_NAME

"micrium-example-sub"

Specify another client ID

Location#
/examples/net/mqtt/ex_mqtt_client_subscribe.c

/examples/net/mqtt/ex_mqtt_client.h
API#

API

Description

Ex_MQTT_Client_Subscribe()

Open a connection and subscribe to a topic.

Notes#

None.

MQTT Client Echo Example#

Description#

This is a generic example for the MQTT Client module. It accomplishes the following tasks:

  • Connect to a broker

  • Subscribe to a topic

  • Publish on the subscribed topic

Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_MQTTc_BROKER_NAME

"mqtt.micrium.com "

Specify the broker hostname

EX_MQTTc_USERNAME

"micrium"

Specify the username

EX_MQTTc_PASSWORD

"micrium"

Specify the password

EX_MQTTc_CLIENT_ID_NAME

"micrium-example-echo"

Specify another client ID

Location#
/examples/net/mqtt/ex_mqtt_client_echo.c

/examples/net/mqtt/ex_mqtt_client.h
API#

API

Description

Ex_MQTT_Client_Echo()

Open a connection and publish message from the callback and receive message using subscribe.

Notes#

None.

MQTT Client Configuration#

This section describes the runtime configurations for the MQTT Client module.

Initialization#

To initialize the MQTT Client module, you call the function MQTTc_Init(). This function takes no configuration argument. Unless you override an optional configuration before calling the function MQTTc_Init(), the default configurations will be used.

Optional Configurations#

This section describes the optional configurations. If you do not set them in your application, the default configurations will apply.

The default values can be retrieved via the structure MQTTc_InitCfgDflt.

Note that these configurations must be set before you call the function MQTTc_Init().

Table - MQTT Client Optional Configurations#

Configurations

Description

Type

Function to call

Default

Field from default configuration structure

Task's stack

The MQTT client module has a dedicated task. This configuration allows you to set the stack pointer and the stack size (in quantity of elements).

CPU_STK_SIZE void *

MQTTc_ConfigureTaskStk()

A stack of 512 elements allocated on Common 's memory segment.

.StkSizeElements.StkPtr

Memory segment

The MQTT module allocates control data. You can specify the memory segment where such data should be located.

MEM_SEG *

MQTTc_ConfigureMemSeg()

General-purpose heap .

.MemSegPtr

Quantity parameters

The MQTT client task use a message queue. You can overwrite the maximum element in the message pool.

MQTTc_QTY_CFG

MQTTc_ConfigureQty()

Unlimited queue size.

.QtyCfg

Post-Init Configurations#

This section describes the configurations that can be set at any time during execution after you called the function MQTTc_Init().

These configurations are optional. If you do not set them in your application, the default configurations will apply.

Table - HTTP Client Post-init Configurations#

Configurations

Description

Type

Function to call

Default

Task priority

The MQTT client module creates a task. You can change the priority of this task at any time.

RTOS_TASK_PRIO

MQTTc_TaskPrioSet()

See Appendix A - Internal Tasks .

Task Delay

You can change the delay inside this task to allow a period of time for other tasks to run.

CPU_INT08U

MQTTc_TaskDlySet()

1u

Default Inactivity timeout

You can change the default inactivity assigned automatically to new connections.

CPU_INT16U

MQTTc_InactivityTimeoutDfltSet()

1800u

MQTT Client Programming Guide#

This section includes the following sub-topics:

Include Files#

To include MQTT functions in your application, include this file:

Include file

Description

rtos/net/include/mqtt_client.h

Functions used for MQTT API.

Configuration#

Some parameters should be configured and/or optimized for your project requirements. See the section MQTT Client Configuration for further details.

API Reference#

Function name

Description

MQTTc_ConnClr()

Clears an MQTT client connection before its first usage.

MQTTc_ConnSetParam()

Sets parameters related to the TCP and MQTT client connection.

MQTTc_ConnOpen()

Opens a new MQTT client connection.

MQTTc_ConnClose()

Request to close a MQTT client connection.

MQTTc_MsgClr()

Clears the Message object members.

MQTTc_MsgSetParam()

Sets parameters related to a given MQTT message.

MQTTc_Connect()

Sends a 'Connect' message to the MQTT broker.

MQTTc_Publish()

Sends a 'Publish' message to the MQTT broker.

MQTTc_Subscribe()

Sends a 'Subscribe' message to the MQTT broker.

MQTTc_SubscribeMult()

Sends a 'Subscribe' message containing multiple topics to MQTT broker.

MQTTc_Unsubscribe()

Sends an 'Unsubscribe' message to the MQTT broker.

MQTTc_UnsubscribeMult()

Sends an 'Unsubscribe' message for multiple topics to the MQTT broker.

MQTTc_PingReq()

Sends a 'PingReq' message to the MQTT broker.

MQTTc_Disconnect()

Sends a 'Disconnect' message to the MQTT broker.

MQTT Client Objects#

This section describes the various structures that your application can use to create objects in order to use the MQTT Client. All MQTT Client objects must be allocated by the application and passed to the MQTT Client module.

All objects or strings passed to the MQTT Client module must stay valid and unmodified for the duration of the MQTT message (for message-oriented parameters and objects), or until the MQTT connection is closed (for Connection-oriented parameters and objects).

MQTT-Client Connection (MQTTc_CONN)#

This is the main structure used by MQTT Client module. It contains all parameters related to an MQTT connection (broker port number, broker address, broker host name, etc.) and also many internal parameters for the MQTT connection and MQTT message processing.

Each configurable parameter should be set up with the function MQTTc_ConnSetParam(). The list of available parameters for a connection can be viewed here .

Your application should never directly modify the members of an MQTT Client Connection object at any time.

Listing - MQTTc_CONN Structure#
struct  mqttc_conn {
    NET_SOCK_ID                 SockId;                /* Connection's socket ID.                              */
    CPU_INT08U                  SockSelFlags;          /* Flags to identify which oper must be checked in Sel. */
    CPU_CHAR                   *BrokerIP_Addr;         /* MQTT broker's IP addr.                               */
    CPU_CHAR                   *BrokerNamePtr;         /* MQTT broker's name.                                  */
    CPU_INT16U                  BrokerPortNbr;         /* MQTT broker's port nbr.                              */
    CPU_INT16U                  InactivityTimeout_s;   /* Inactivity timeout, in seconds.                      */
    CPU_CHAR                   *ClientID_Str;          /* Client ID str.                                       */
    CPU_CHAR                   *UsernameStr;           /* Username str.                                        */
    CPU_CHAR                   *PasswordStr;           /* Password str.                                        */
    CPU_INT16U                  KeepAliveTimerSec;     /* Keep alive timer duration, in seconds.               */
    MQTTc_WILL_CFG             *WillCfgPtr;            /* Ptr to will cfg, if any.                             */
    NET_APP_SOCK_SECURE_CFG    *SecureCfgPtr;          /* Ptr to secure will cfg, if any.                      */
                                                       /* -------------------- CALLBACKS --------------------- */
    MQTTc_CMPL_CALLBACK         OnCmpl;                /* Generic, on cmpl callback.                           */
    MQTTc_CMPL_CALLBACK         OnConnectCmpl;         /* On connect cmpl callback.                            */
    MQTTc_CMPL_CALLBACK         OnPublishCmpl;         /* On publish cmpl callback.                            */
    MQTTc_CMPL_CALLBACK         OnSubscribeCmpl;       /* On subscribe cmpl callback.                          */
    MQTTc_CMPL_CALLBACK         OnUnsubscribeCmpl;     /* On unsubscribe cmpl callback.                        */
    MQTTc_CMPL_CALLBACK         OnPingReqCmpl;         /* On ping req cmpl callback.                           */
    MQTTc_CMPL_CALLBACK         OnDisconnectCmpl;      /* On disconnect cmpl callback.                         */
    MQTTc_PUBLISH_RX_CALLBACK   OnPublishRx;           /* On publish rx'd cmpl callback.                       */
    void                       *ArgPtr;                /* Ptr to arg that will be provided to callbacks.       */
    CPU_INT32U                  TimeoutMs;             /* Timeout for 'Open' operation, in milliseconds.       */
                                                       /* ----------------- NEXT MSG VALUES ------------------ */
    CPU_INT08U                  NextMsgHeader;         /* Header of next msg to parse.                         */
    CPU_INT32U                  NextMsgRxLen;          /* Rx len of next msg.                                  */
    MQTTc_MSG_TYPE              NextMsgType;           /* Next msg's type.                                     */
    CPU_INT32U                  NextMsgLen;            /* Len remaining to RX for next msg.                    */
    CPU_BOOLEAN                 NextMsgLenIsCmpl;      /* Flag indicating if next msg's len value is rx'd.     */
    CPU_INT16U                  NextMsgMsgID;          /* ID of next msg, if any.                              */
    CPU_BOOLEAN                 NextMsgMsgID_IsCmpl;   /* Flag indicating if next msg's ID has been rx'd.      */
    MQTTc_MSG                  *NextMsgPtr;            /* Ptr to next msg, if known.                           */
    MQTTc_MSG                  *PublishRxMsgPtr;       /* Ptr to msg that is used to RX publish from server.   */
    MQTTc_MSG                  *TxMsgHeadPtr;          /* Ptr to head of msg needing to TX or waiting reply.   */
    CPU_INT32U                  NextTxMsgTxLen;        /* Len of already xfer'd data.                          */
    MQTTc_CONN                 *NextPtr;               /* Ptr to next conn.                                    */
};
MQTT Client Message (MQTTc_MSG)#

This structure contains parameters and flags related to the configuration of an MQTT message.

Each configurable parameter should be set up with the function MQTTc_MsgSetParam(). The list of available parameters for a connection can be viewed here .

Your application should never directly modify the members of an MQTT-Client Message object at any time.

Listing - MQTTc_MSG Structure#
struct  mqttc_msg {
    MQTTc_CONN       *ConnPtr;                                  /* Ptr to MQTTc_CONN associated.               */
    MQTTc_MSG_TYPE    Type;                                     /* Msg's type.                                 */
    MQTTc_MSG_STATE   State;                                    /* Msg's state.                                */
    CPU_INT08U        QoS;                                      /* Msg's QoS.                                  */
    CPU_INT16U        MsgID;                                    /* Msg ID used by msg.                         */
    CPU_INT08U       *BufPtr;                                   /* Ptr to RX/TX buf.                           */
    CPU_INT32U        BufLen;                                   /* Avail buf len for msg.                      */
    CPU_INT32U        XferLen;                                  /* Len of xfer.                                */
    MQTTc_ERR         Err;                                      /* Err associated to processing of msg.        */
    MQTTc_MSG        *NextPtr;                                  /* Ptr to next msg.                            */
};

MQTT Client Connection Object Setup#

To configure the MQTT Client Connection object , the MQTT Client module provides the function MQTTc_ConnSetParam(). This function takes as arguments: the type of parameter, the parameter's value, and a pointer to the parameter. The following parameter types are available:

Generic Parameters#
Table - MQTTc Connection's Parameters#

Parameter Type

Description

MQTTc_PARAM_TYPE_BROKER_IP_ADDR

IP Address of the MQTT broker.This field is ignored if broker name is set.

MQTTc_PARAM_TYPE_BROKER_NAME

Name of the MQTT broker.This method will work only if a DNS server is available**This field is ignored if the broker IP address is set.

MQTTc_PARAM_TYPE_BROKER_PORT_NBR

Sets a specific port for the MQTT broker.By default, the port is set to 1883.

MQTTc_PARAM_TYPE_INACTIVITY_TIMEOUT_S

Sets the inactivity timeout of the connectionThis value represents the time of inactivity allowed on a connection before it is automatically closed.

MQTTc_PARAM_TYPE_CLIENT_ID_STR

Connection's Client ID. This ID should be unique among devices connected to the broker.

MQTTc_PARAM_TYPE_USERNAME_STR

Connection's username string.This field is optional.

MQTTc_PARAM_TYPE_PASSWORD_STR

Connection's password string.This field is optional.

MQTTc_PARAM_TYPE_KEEP_ALIVE_TMR_SEC

Connection's keep alive, in seconds.This value represents the maximum allowed time between messages sent by the device to the broker.**If no message is sent for more than this time, the broker will close the connection.

MQTTc_PARAM_TYPE_WILL_CFG_PTR

Pointer to last will and testament configuration.This field is optional.

MQTTc_PARAM_TYPE_SECURE_CFG_PTR

Pointer to secure configuration.This field is optional.

MQTTc_PARAM_TYPE_TIMEOUT_MS

Connection's timeout for socket 'Open', in milliseconds.

MQTTc_PARAM_TYPE_PUBLISH_RX_MSG_PTR

Pointer to MQTT-client message object that will be used to receive PUBLISH messages from the broker.This parameter is *mandatory**.*

Callback options#
Table - MQTTc Connection's Callbacks#

MQTTc_PARAM_TYPE_CALLBACK_ON_COMPL

Sets the generic callback function to notify the application whenever an event occurs. This callback is called before every other callback and may be used in place of all the other ones.

MQTTc_PARAM_TYPE_CALLBACK_ON_CONNECT_CMPL

Sets the callback function to notify the application when a CONNECT message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_CMPL

Sets the callback function to notify the application when a PUBLISH message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_SUBSCRIBE_CMPL

Sets the callback function to notify the application when a SUBSCRIBE message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_UNSUBSCRIBE_CMPL

Sets the callback function to notify the application when an UNSUBSCRIBE message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_PINGREQ_CMPL

Sets the callback function to notify the application when a PINGREQ message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_DISCONNECT_CMPL

Sets the callback function to notify the application when a DISCONNECT message with the MQTT broker is completed.This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_ERR_CALLBACK

Sets the callback function to notify the application when an error with the socket connection occurs.A connection can be closed by the MQTT broker, by the client when an unexpected error occurred. To be able to re-open the socket connection and re-connect the client, this callback should be provided. This parameter is optional.

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_RX

Sets the callback function to notify the application when a PUBLISH message is received from the broker.This parameter is *mandatory**.*

MQTTc_PARAM_TYPE_CALLBACK_ARG_PTR

Sets the argument that will be passed to every callback function.This parameter is optional.

Example#
Listing - MQTTc Connection Configuration Example#
CPU_BOOLEAN  App_MQTTc_ConnPrepare (MQTTc_CONN  *p_conn)
{
    RTOS_ERR  err;

                                                        /* ---------- INIT NEW CONNECTION --------- */
    MQTTc_ConnClr(p_conn, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* Set conn parameters.                     */
    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_BROKER_NAME,
                       (void *)APP_MQTTc_BROKER_NAME,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CLIENT_ID_STR,
                       (void *)APP_MQTTc_CLIENT_ID_NAME,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_USERNAME_STR,
                       (void *)APP_MQTTc_USERNAME,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_PASSWORD_STR,
                       (void *)APP_MQTTc_PASSWORD,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_KEEP_ALIVE_TMR_SEC,
                       (void *)1000u,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_COMPL,
                       (void *)AppMQTTc_OnCmplCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_CONNECT_CMPL,
                       (void *)AppMQTTc_OnConnectCmplCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_CMPL,
                       (void *)AppMQTTc_OnPublishCmplCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_SUBSCRIBE_CMPL,
                       (void *)AppMQTTc_OnSubscribeCmplCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_ERR_CALLBACK,
                       (void *)AppMQTTc_OnErrCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(        &AppMQTTc_Conn,
                                MQTTc_PARAM_TYPE_PUBLISH_RX_MSG_PTR,
                       (void *)&AppMQTTc_MsgPublishRx,
                               &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_RX,
                       (void *)AppMQTTc_OnPublishRxCallbackFnct,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_ConnSetParam(       &AppMQTTc_Conn,
                               MQTTc_PARAM_TYPE_TIMEOUT_MS,
                       (void *)30000u,
                              &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

MQTT Client Message Object Setup#

To set up an MQTT message, the MQTT Client provides the function MQTTc_MsgSetParam(). The function takes as arguments: the type of parameter, the pointer to the parameter, and the parameter's value. The following parameter types are available:

Table - MQTTc Message's Parameters#

Parameter Type

Description

MQTTc_PARAM_TYPE_MSG_BUF_PTR

Sets a pointer to the message.

MQTTc_PARAM_TYPE_MSG_BUF_LEN

Sets the message's buffer length.

Example#
Listing - MQTTc Message Configuration Example#
static  MQTTc_MSG    AppMQTTc_Msg;
static  CPU_INT08U   AppMQTTc_MsgBuf[APP_MQTTc_MSG_LEN_MAX];

CPU_BOOLEAN  App_MQTTc_MsgPrepare (void)
{
    RTOS_ERR  err;

                                                                 /* ------------ INIT NEW MESSAGE ------------ */
    MQTTc_MsgClr(&AppMQTTc_Msg, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_MsgSetParam(&AppMQTTc_Msg, MQTTc_PARAM_TYPE_MSG_BUF_PTR, (void *)&AppMQTTc_MsgBuf[0u], &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    MQTTc_MsgSetParam(&AppMQTTc_Msg, MQTTc_PARAM_TYPE_MSG_BUF_LEN, (void *)APP_MQTTc_MSG_LEN_MAX, &err);
    if (err.Code != RTOS_ERR_NONE) {
        return (DEF_FAIL);
    }

    return (DEF_OK);
}

MQTT Client Callback Functions#

Callback functions are used by the MQTT Client module to notify your application when certain activities occur in the MQTT Client core.

Callbacks can be set up by using the MQTTc_ConnSetParam() function. The p_arg parameter that is passed in every callback can be set via MQTTc_ConnSetParam() by using MQTTc_PARAM_TYPE_CALLBACK_ARG_PTR as the type argument.

No blocking calls (delays, pending on an OS object, etc.) or long operations should ever be performed in any of these callbacks. These callbacks are executed from the MQTT Client internal task, and if this task is delayed or blocked, the entire MQTT Client module will be delayed/blocked too, preventing the reception or transmission of any message on any connection.

On Complete Callbacks#

The following callbacks are of type MQTTc_CMPL_CALLBACK. Even though they are optional, they are necessary for your application to know when a particular message has been completely sent, in order to re-use it for another message. The generic complete callback may be used to emulate all other callbacks in this category.

Table - MQTTc On Complete Callback Functions#

Trigger Event

Description

type argument for MQTTc_ConnSetParam()

Any message completed (in this section, not a received PUBLISH message)

Generic notification for any event.

MQTTc_PARAM_TYPE_CALLBACK_ON_COMPL

CONNECT message completed

Notify that a CONNECT message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_CONNECT_CMPL

PUBLISH (to broker) message completed

Notify that a PUBLISH message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_CMPL

SUBSCRIBE message completed

Notify that a SUBSCRIBE message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_SUBSCRIBE_CMPL

UNSUBSCRIBE message completed

Notify that an UNSUBSCRIBE message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_UNSUBSCRIBE_CMPL

PINGREQ message completed

Notify that a PINGREQ message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_PINGREQ_CMPL

DISCONNECT message completed

Notify that a DISCONNECT message has completed.

MQTTc_PARAM_TYPE_CALLBACK_ON_DISCONNECT_CMPL

On Error Callback#

This callback is of type MQTTc_ERR_CALLBACK. Even though it is optional, we recommend that your application make use of it to know if an error occurs.

Table - MQTTc On Error Callback Function#

Trigger Event

Description

type argument for MQTTc_ConnSetParam()

Whenever an error occurs on the connection and is not related to a particular message

Notify that an error occurred on the connection.

MQTTc_PARAM_TYPE_CALLBACK_ON_ERR_CALLBACK

On PUBLISH Message Received Callback#

This callback is of type MQTTc_PUBLISH_RX_CALLBACK. This callback is required only if the application expects to receive data from the broker. If not, it will never be called.

Table - MQTTc On PUBLISH received Callback Function#

Trigger Event

Description

type argument for MQTTc_ConnSetParam()

A PUBLISH message has been completely received

Notify that a PUBLISH message has completed to be received.

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_RX

MQTT Client - On Complete Callback Type#

This callback function type is used by any callback that receives a notification when a message exchange with the broker has been completed, successfully or not. The parameters passed are the same in every callback and are detailed below.

Prototype#
typedef  void  (*MQTTc_CMPL_CALLBACK) (MQTTc_CONN  *p_conn,
                                       MQTTc_MSG   *p_msg,
                                       void        *p_arg,
                                       RTOS_ERR     err);
Arguments#

p_conn

Pointer to the current MQTTc Connection Object.

p_msg

Pointer to the MQTTc Message Object used to send the message to the broker.

In the generic complete callback, you can use p_msg->Type to find out the type of message that just completed. The other fields of p_msg may not be relied upon.

p_arg

Pointer to the argument specified by your application via MQTTc_ConnSetParam() with the MQTTc_PARAM_TYPE_CALLBACK_ARG_PTR type.

err

Error code for this operation.

Return Values#

None.

Notes / Warnings#

None.

Example Template#
Listing - CONNECT Complete Callback Example#
static  void  AppMQTTc_OnConnectCmplCallbackFnct (MQTTc_CONN  *p_conn,
                                                  MQTTc_MSG   *p_msg,
                                                  void        *p_arg,
                                                  RTOS_ERR     err)
{
    RTOS_ERR  err_mqttc;

    (void)&p_arg;

    if (err.Code != RTOS_ERR_NONE) {
        printf("ConnectCmpl callback called with err (%i). NOT sending PUBLISH message.\n\r", err);
    } else {
        printf("ConnectCmpl callback called. Sending PUBLISH message.\n\r");
        MQTTc_Publish(p_conn,
                      p_msg,
                      APP_MQTTc_DOMAIN_PUBLISH,
                      APP_MQTTc_PUBLISH_TEST_QoS,
                      DEF_YES,
                      APP_MQTTc_PUBLISH_TEST_MSG,
                     &err_mqttc);
        if (err_mqttc.Code != RTOS_ERR_NONE) {
            printf("!!! APP ERROR !!! Failed to Publish test string. Err: %i\n\r.", err_mqttc);
        }
    }
}
Listing - Generic Complete Callback Example#
static  void  AppMQTTc_OnCmplCallbackFnct (MQTTc_CONN  *p_conn,
                                           MQTTc_MSG   *p_msg,
                                           void        *p_arg,
                                           RTOS_ERR     err)
{
    (void)&p_conn;
    (void)&p_arg;

    if (err.Code != RTOS_ERR_NONE) {
        printf("Operation completed with err (%i). ", err);
    }

    switch (p_msg-\>Type) {
        case MQTTc_MSG_TYPE_CONNECT:                   /\* Gen callback called for event type: Connect Cmpl.    \*/
             printf("Gen callback called for event type: Connect Cmpl.\n\r");
             break;
        case MQTTc_MSG_TYPE_PUBLISH:                   /\* Gen callback called for event type: Publish Cmpl.    \*/
             printf("Gen callback called for event type: Publish Cmpl.\n\r");
             break;
        case MQTTc_MSG_TYPE_SUBSCRIBE:                 /\* Gen callback called for event type: Subscribe Cmpl.  \*/
             printf("Gen callback called for event type: Subscribe Cmpl.\n\r");
             break;
        case MQTTc_MSG_TYPE_UNSUBSCRIBE:               /\* Gen callback called for event type: Unsubscribe Cmpl.\*/
             printf("Gen callback called for event type: Unsubscribe Cmpl.\n\r");
             break;
        case MQTTc_MSG_TYPE_PINGREQ:                   /\* Gen callback called for event type: PingReq Cmpl.    \*/
             printf("Gen callback called for event type: PingReq Cmpl.\n\r");
             break;
        case MQTTc_MSG_TYPE_DISCONNECT:                /\* Gen callback called for event type: Disconnect Cmpl. \*/
             printf("Gen callback called for event type: Disconnect Cmpl.\n\r");
             break;
        default:
             printf("Gen callback called for event type: default. !!! ERROR !!! %i\n\r", p_msg-\>Type);
             break;
    }
}

MQTT Client - On Error Callback Type#

This callback function type is used to notify your application that an error occurred within the stack that is not related to a particular message.

Prototype#
typedef  void  (*MQTTc_ERR_CALLBACK) (MQTTc_CONN  *p_conn,
                                      void        *p_arg,
                                      RTOS_ERR     err);
Arguments#

p_conn

Pointer to the current MQTTc Connection Object.

p_arg

Pointer to the argument specified by your application via MQTTc_ConnSetParam() with the MQTTc_PARAM_TYPE_CALLBACK_ARG_PTR type.

err

Error code.

Return Values#

None.

Notes / Warnings#

After this callback is called, your application must re-call MQTTc_ConnOpen() , and MQTTc_Connect(), since both the TCP and MQTT connections will have been closed. We recommend that you do this outside the scope of the callback, to avoid slowing the whole MQTTc stack if it has other messages to process.

Example Template#
Listing - On Error Callback Example#
static  void  AppMQTTc_OnErrCallbackFnct (MQTTc_CONN  *p_conn,
                                          void        *p_arg,
                                          RTOS_ERR     err)
{
    (void)&p_conn;
    (void)&p_arg;

    printf("!!! APP ERROR !!! Err detected via OnErr callback. Err = %s.\n\r", err.CodeText);
}

MQTT Client - On PUBLISH Received Callback Type#

This callback function type is used to notify your application that a PUBLISH message has been received or that there has been an error when trying to receive it.

Prototype#
typedef  void  (*MQTTc_PUBLISH_RX_CALLBACK) (       MQTTc_CONN   *p_conn,
                                             const  CPU_CHAR     *topic_name_str,
                                                    CPU_INT32U    topic_len,
                                             const  CPU_INT08U   *p_message,
                                                    CPU_INT32U    message_len,
                                                    void         *p_arg,
                                                    RTOS_ERR      err);
Arguments#

p_conn

Pointer to the current MQTTc Connection Object.

topic_name_str

Pointer to the start of the string containing the topic name. Note: For performance reasons, this string is not NULL-terminated.

topic_len

Length, in bytes, of the topic string.

p_message

Pointer to the start of the buffer containing the message.

message_len

Length, in bytes, of the message.

p_arg

Pointer to the argument specified by the application via MQTTc_ConnSetParam() with the MQTTc_PARAM_TYPE_CALLBACK_ARG_PTR type.

err

Error code for this operation.

Return Values#

None.

Notes / Warnings#

None.

Example Template#
Listing - On PUBLISH Received Callback Example(1) This example assumes that the message is string-based and NULL terminated#
static  void  AppMQTTc_OnPublishRxCallbackFnct (       MQTTc_CONN  *p_conn,
                                                const  CPU_CHAR    *topic_name_str,
                                                       CPU_INT32U   topic_len,
                                                const  CPU_INT08U  *p_message,
                                                       CPU_INT32U   message_len,
                                                       void        *p_arg,
                                                       RTOS_ERR     err)
{
    (void)&p_conn;
    (void)&p_arg;

    if (err.Code != RTOS_ERR_NONE) {
        printf("!!! APP ERROR !!! Err detected when receiving a PUBLISH message (%s).\n\r", err.CodeText);
    }

    printf("Received PUBLISH message from server. Topic is %.*s.", topic_len, topic_name_str);
    printf(" Message is %s.", (CPU_CHAR *)p_message);                                         /* See Note #1. */
}

MQTT Client Message Types Supported#

MQTT Message Type

Associated Function

Associated Callback Type (set via MQTTc_ConnSetParam())

CONNECTCONNACK

MQTTc_Connect()

MQTTc_PARAM_TYPE_CALLBACK_ON_CONNECT_CMPL

PUBLISH (to server)PUBACKPUBRECPUBRELPUBCOMP

MQTTc_Publish()

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_CMPL

PUBLISH (from server)PUBACKPUBRECPUBRELPUBCOMP

None, waiting on server.

MQTTc_PARAM_TYPE_CALLBACK_ON_PUBLISH_RX

SUBSCRIBESUBACK

MQTTc_Subscribe(),MQTTc_SubscribeMult()

MQTTc_PARAM_TYPE_CALLBACK_ON_SUBSCRIBE_CMPL

UNSUBSCRIBEUNSUBACK

MQTTc_Unsubscribe(),MQTTc_UnsubscribeMult()

MQTTc_PARAM_TYPE_CALLBACK_ON_UNSUBSCRIBE_CMPL

PINGREQPINGRESP

MQTTc_PingReq()

MQTTc_PARAM_TYPE_CALLBACK_ON_PINGREQ_CMPL

DISCONNECT

MQTTc_Disconnect()

MQTTc_PARAM_TYPE_CALLBACK_ON_DISCONNECT_CMPL

SNTP Client Module#

SNTP Client Overview#

The Simple Network Time Protocol (SNTP) is a protocol used to synchronized computer clock times in a computer network. SNTP uses Universal Time Coordinated (UTC) to synchronize computer clocks to the millisecond, and sometimes to a fraction of a millisecond. The SNTP Client module implements the following RFC:

ftp-ftp-rfc-editor-org-in-notes-rfc4330-txt

SNTP Client Example Applications#

This section describes the examples that are related to the Micrium OS SNTP Client module.

SNTP Client Initialization Example#

Description#

This is a generic example that shows how to initialize the SNTP client module.

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the SNTP Client module correctly:

#define

Description

EX_SNTP_CLIENT_INIT_AVAIL

Lets the upper example layer know that the SNTP Client Initialization example is present and must be called by other examples.

Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_TRACE

printf(VA_ARGS)

Specify the function used to output information

Location#
/examples/net/sntp/ex_sntp_client.c

/examples/net/sntp/ex_sntp_client.h
API#

API

Description

Ex_SNTP_Client_Init()

Initialize the Micrium OS SNTP Client module for the example application.

Notes#

None.

Basic SNTP Current Time Retrieve#

Description#

This is a simple example that will retrieve the current time from the following NTP server: 0.pool.ntp.org.

The example will then display the current time in the following format:

Day <day> of year <year>. Time: hh:mm:ss(UTC)

Location#
/examples/net/sntp/ex_sntp_client.c

/examples/net/sntp/ex_sntp_client.h
Configuration#
Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_TRACE

printf(VA_ARGS)

Specify the function used to output information

API#

API

Description

Ex_SNTP_Client_CurTimeDisplay()

Retrieves the current time from the NTP server and displays it

Notes#

None.

SNTP Client Configuration#

Initialization#

Initializing the SNTP Client module is done by calling the function SNTPc_Init(). This function takes no configuration argument. Unless you override an optional configuration before calling the function SNTPc_Init(), the default configurations will be used.

Optional Configurations#

This section describes the configurations that are optional. If you do not set them in your application, the default configurations will apply.

You can retrieve the default values from the structure SNTPc_InitCfgDflt.

Note that these configurations must be set before you call the function SNTPc_Init().

Table - SNTP Client Optional Configurations#

Configurations

Description

Type

Function to call

Default

Field from default configuration structure

Memory segment

This module allocates some control data. You can specify the memory segment from where such data should be allocated.

MEM_SEG*

SNTPc_ConfigureMemSeg()

General-purpose heap .

.MemSegPtr

Post-Init Configurations#

This section describes the configurations that can be set at any time during execution after you called the function SNTPc_Init().

These configurations are optional. If you do not set them in your application, the default configurations will apply.

Table - SNTP Client Post-init Configurations#

SNTP Client Post-init ConfigurationsSNTP Client Post-init Configurations

SNTP Client Programming Guide#

This section describes the basic steps required to initialize and use the Simple Network Time Protocol (SNTP) module.

Initializing the SNTP Client Module#

First step is to initialize the SNTP client module. This is done by calling the function SNTPc_Init(). Note that the Network module MUST be initialized before the SNTP Client module.

Listing - Example of call to SNTPc_Init() in the SNTP Client Programming Guide page gives an example of call to SNTPc_Init().

Listing - Example of call to SNTPc_Init()#
RTOS_ERR  err;

SNTPc_Init(&err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

Requesting Remote Time#

Once you successfully initialized the SNTP Client module, you can request the remote time This is done by calling the function SNTPc_ReqRemoteTime().

Listing - Example of call to SNTPc_ReqRemoteTime() in the SNTP Client Programming Guide page gives an example of call to SNTPc_ReqRemoteTime() using default arguments. In this example, the remote NTP server is 0.pool.ntp.org.

Listing - Example of call to SNTPc_ReqRemoteTime()#
RTOS_ERR  err;
SNTP_PKT  pkt;

SNTPc_ReqRemoteTime("0.pool.ntp.org",
          &pkt,
            &err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

Retrieving Current Time#

Once you successfully requested the remote time, you can compute the current time. This is done by calling the function SNTPc_GetRemoteTime(). This function will take the pointer to the variable of type SNTP_PKT that was given to the function SNTPc_ReqRemoteTime() previously. Note that the returned time is UTC.

Listing - Example of call to SNTPc_GetRemoteTime() in the SNTP Client Programming Guide page gives an example of call to SNTPc_GetRemoteTime().

Listing - Example of call to SNTPc_GetRemoteTime()#
SNTP_TS   ts;
RTOS_ERR  err;

ts = SNTPc_GetRemoteTime(&pkt, &err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

ts.Sec;              /* Represents the quantity of seconds since Jan 1, 1900.  */
ts.Frac;            /* Represents the fractions of second. 32 bit precision.  */

SMTP Client Module#

SMTP Client Overview#

SMTP (Simple Mail Transfer Protocol) is a protocol designed to transfer mail reliably and efficiently. When an SMTP client has a message to transmit, it establishes a two-way transmission channel to an SMTP server. The responsibility of an SMTP client is to transfer mail messages to a SMTP server, or report its failure to do so [RFC 2821].

Micrium OS SMTP module implement part of the following RFC:

ftp-ftp-rfc-editor-org-in-notes-rfc2821-txt

ftp-ftp-rfc-editor-org-in-notes-rfc2822-txt

ftp-ftp-rfc-editor-org-in-notes-rfc4616-txt

ftp-ftp-rfc-editor-org-in-notes-rfc4648-txt

ftp-ftp-rfc-editor-org-in-notes-rfc4954-txt

SMTP Client Example Applications#

This section describes the examples that are related to the Micrium OS SMTP Client module.

SMTP Client Initialization Example#

Description#

This is a generic example that shows how to initialize the SMTP client module.

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the SNTP Client module correctly:

#define

Description

EX_SMTP_CLIENT_INIT_AVAIL

Lets the upper example layer know that the SMTP Client Initialization example is present and must be called by other examples.

Location#
/examples/net/smtp/ex_smtp_client.c

/examples/net/smtp/ex_smtp_client.h
API#

API

Description

Ex_SMTP_Client_Init()

Initialize the Micrium OS SMTP Client module for the example application.

Notes#

None.

SMTP Client Send Email Example#

Description#

This is a simple example that sends an email.

Configuration#
Mandatory#

The following #define must be added in ex_description.h to allow other examples to initialize the SNTP Client module correctly:

#define

Description

EX_SMTPc_SERVER_ADDR

Specify the SMTP server address to use. One should be provided by your ISP or by your organization.Note that the default value is invalid ("smtp.isp.com ").

EX_SMTPc_TO_ADDR

Specify the destination email address, i.e., your email address. Note that the default value is invalid ("test_to@gmail.com ").

Optional#

The following #define can be added to ex_description.h, as described in Example Applications section, to change default configuration value used by the example:

#define

Default value

Description

EX_SMTPc_FROM_NAME

"From Name"

Specify the displayed name of the sender

EX_SMTPc_FROM_ADDR

"test_from@gmail.com "

Specify the email address of the sender

EX_SMTPc_USERNAME

DEF_NULL

Specify a username, if null no authentication is applied.

EX_SMTPc_PW

DEF_NULL

Specify a password.

EX_SMTPc_MSG_SUBJECT

"Example Title"

Specify the email subject

EX_SMTPc_MSG_BODY

"Example email sent using Micrium OS"

Specify the email body

EX_TRACE

printf(VA_ARGS)

Specify the function used to output information

Location#
/examples/net/smtp/ex_smtp_client.c

/examples/net/smtp/ex_smtp_client.h
API#

API

Description

Ex_SMTP_Client_SendMail()

Send an email

SMTP Client Configuration#

Initialization#

Initializing the SMTP Client module is done by calling the function SMTPc_Init(). This function takes no configuration argument. Unless you override an optional configuration before calling the function SMTPc_Init(), the default configurations will be used.

Optional Configurations#

This section describes the configurations that are optional. If you do not set them in your application, the default configurations will apply.

The default values can be retrieved via the structure SMTPc_InitCfgDflt.Note that these configurations must be set before you call the function SMTPc_Init().

Table - SMTP Client Optional Configurations#

Configurations

Description

Type

Function to call

Default

Field from default configuration structure

Memory segment

This module allocates some control data. You can specify the memory segment from where such data should be allocated.

MEM_SEG*

SMTPc_ConfigureMemSeg()

General-purpose heap .

.MemSegPtr

Authentication encodes buffers

This module allocates buffers to encode the authentication data (user name and password). Two type of buffer are allocated; small buffers which will contain the username and the password and large buffers which will receive the encoded data.

CPU_INT16U

SMTPc_ConfigureAuthBufLen()

.AuthBufInputLen = 100.AuthBufOutputLen = 140

.AuthBufInputLen.AuthBufOutputLen

Post-Init Configurations#

This section describes the configurations that can be set at any time during execution after you called the function SMTPc_Init().

These configurations are optional. If you do not set them in your application, the default configurations will apply.

Table - SMTP Client Post-init Configurations#

SMTP Client Post-init Configurations 1SMTP Client Post-init Configurations 1

SMTP Client Programming Guide#

This section describes the basic steps required to initialize and use the Simple Mail Transfer Protocol (SMTP) module.

Initializing the SMTP Client Module#

The first step is to initialize the SMTP client module. This is done by calling the function SMTPc_Init(). Note that the Network module MUST be initialized before the SMTP Client module.

Listing - Example of call to SNTPc_Init() in the SMTP Client Programming Guide page gives an example of a call to SMTPc_Init() .

Listing - Example of call to SNTPc_Init()#
RTOS_ERR  err;

SMTPc_Init(&err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occured. Error handling should be added here. */
}

Prepare Mail Message#

Once you have successfully initialized the SMTP Client module, you can prepare message to be sent using SMTP client module :

SMTPc_MsgAlloc()

SMTPc_MsgClr()

SMTPc_MsgFree()

SMTPc_MsgSetParam()

Listing - Example of how to prepare a mail message in the SMTP Client Programming Guide page gives an example of how to prepare a mail message:

Listing - Example of how to prepare a mail message#
RTOS_ERR    err;
SMTPc_MSG  *p_msg;

p_msg = (SMTPc_MSG *)SMTPc_MsgAlloc(&err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_FROM_ADDR, "test_from@mail.com", &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_FROM_DISPL_NAME, "From Name", &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_TO_ADDR, "test_to@mail.com", &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_MSG_SUBJECT, "This is the mail title", &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_MSG_BODY, "This is the mail message body", &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

// TODO send message

SMTPc_MsgFree(p_msg, &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

Send Mail#

Once you have configured you mail message, you can transfer the mail using a remote SMTP server. You can send email using a high-level SMTPc_SendMail() function if you just need to send one email as shown by Listing - Example of call to SMTPc_SendMail() in the SMTP Client Programming Guide page.

Listing - Example of call to SMTPc_SendMail()#
SMTPc_MSG  *p_msg;
RTOS_ERR    err;

p_msg = (SMTPc_MSG *)SMTPc_MsgAlloc(&err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_FROM_ADDR, EX_SMTPc_FROM_ADDR, &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_FROM_DISPL_NAME, EX_SMTPc_FROM_NAME, &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_TO_ADDR, EX_SMTPc_TO_ADDR, &err);
APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);

SMTPc_MsgSetParam(p_msg, SMTPc_MSG_SUBJECT, EX_SMTPc_MSG_SUBJECT, &err);
APP_RTOS_ASSERT_CRITICAL(