picow-http 0.12.1-4-g9d4fd13
HTTP server for the Raspberry Pi PicoW
Server management and HTTP connections

Data Structures

struct  http
 Current HTTP connection, request and response. More...
 
struct  server_cfg
 HTTP server configuration. More...
 
struct  server
 HTTP server. More...
 

Macros

#define HTTP_DEFAULT_IDLE_TMO_S   (5)
 Default idle timeout. More...
 
#define HTTP_DEFAULT_SEND_TMO_S   (5)
 Default send timeout. More...
 
#define HTTP_DEFAULT_LISTEN_BACKLOG   (10)
 Default listener backlog. More...
 

Typedefs

typedef void priv_fini_f(void *p)
 Function type for private data finalizers. More...
 

Functions

static void http_cx_set_priv (struct http *http, void *priv, priv_fini_f *fini, priv_cnt_f *cnt)
 Set a connection-scoped private object. More...
 
static void * http_cx_priv (struct http *http)
 Return the connection-scoped private object, if any. More...
 
err_t http_cfg (const char *name, struct server_cfg *cfg)
 Get the default confiuration for a server by name. More...
 
static struct server_cfg http_default_cfg (void)
 Get the default HTTP server configuration. More...
 
err_t http_srv_init (struct server **server, struct server_cfg *cfg)
 Start an HTTP server. More...
 
err_t http_srv_fini (struct server *server)
 Stop an HTTP server. More...
 
ip_addr_t * http_srv_ip (struct server *server)
 Return the server listener IP address. More...
 
uint16_t http_srv_port (struct server *server)
 Return the server listener port number. More...
 
void http_srv_set_priv (struct server *server, void *priv, priv_fini_f *fini)
 Set a server-wide private object. More...
 
static ip_addr_t * http_cx_local_ip (struct http *http)
 Return the local IP address of the current HTTP connection. More...
 
static uint16_t http_cx_local_port (struct http *http)
 Return the local port of the current HTTP connection. More...
 
static ip_addr_t * http_cx_remote_ip (struct http *http)
 Return the remote IP address of the current HTTP connection. More...
 
static uint16_t http_cx_remote_port (struct http *http)
 Return the remote port of the current HTTP connection. More...
 
static void * http_srv_priv (struct http *http)
 Return the server-wide private object, if any. More...
 

Detailed Description

Configure, start and stop HTTP servers; and access the current HTTP connection, including the current request and response.

Application private data

Several functions of the API support optional access to private data – a pointer to any object provided by the application. These include:

For example, the private object may be a pointer to a struct storing configuration data, or to a sensor measurement value that is updated elsewhere in the application. The server never touches these objects; it just stores the pointers and hands them back when requested.

Private data is optional; if the application doesn't need it, set the pointer parameter to NULL, or just don't call the setter function.

As indicated above, each type of private object has a scope – a lifetime during which the pointer may be dereferenced:

Attention
A private pointer MUST point to memory that can be safely accessed throughout the lifetime of its scope. For example, a pointer to static storage is safe, or a pointer that was returned by malloc() or obtained through lwIP's memory pool facility. In most cases, it is not safe to use a pointer to stack memory, such as a function local variable.

If the contents of private data will be modified by both cores, it may be necessary to synchronize access, for example with the help of the SDK's pico_sync library.

An application may also specify an optional finalizer for private data. A finalizer function, defined by the application, is invoked for the private pointer when it goes out of scope. This gives the application an opportunity to free any resources stored by the private object, and/or to free the pointer itself. If the pointer was returned by malloc, the finalizer function can just be free (if nothing else requires cleanup).

A finalizer may be unnecessary; for example, a pointer to static storage must not be freed. In such cases, set the finalizer parameter to NULL. On the other hand, it may be critical to provide a finalizer in order to prevent resource leakage.

This is an example of connection-scoped private data, using http_cx_set_priv() and http_cx_priv(). The private object is a struct with an integer member that functions as a counter for the request/response transactions on a keep-alive connection. This illustrates allocation and finalization of private data with lwIP memory pools, which are usually more efficient and lead to less memory fragmentation than malloc and free.

#include "lwip/memp.h"
// The private object will have this type.
// Using the "magic number" idiom from picow_http/assertions.h.
struct cx_data {
unsigned magic;
#define CX_DATA_MAGIC (0x47110815)
int ctr;
}
// Declare an lwIP memory pool.
// Assume that N_OBJS was #defined as the number of objects in the pool.
LWIP_MEMPOOL_DECLARE(cx_priv, N_OBJS, sizeof(cx_data),
"Connection-scoped private data");
// A private pointer is passed into the finalizer when it goes out
// of scope; in this case when the connection closes.
// Use lwIP's mechanism to free the object in the pool.
static void
cx_priv_free(void *p)
{
LWIP_MEMPOOL_FREE(cx_priv, p);
}
// A custom response handler that uses connection-scoped private data.
err_t
cx_priv_hndlr(struct http *http, void *priv)
{
struct resp *resp = http_resp(http);
struct cx_data *priv_data;
err_t err;
// Get the private object in the current connection scope.
priv_data = http_cx_priv(http);
// If http_cx_priv() returns NULL, then no private object
// was set previously for this connection.
if (priv_data == NULL) {
// Allocate an object from the pool.
priv_data = LWIP_MEMPOOL_ALLOC(cx_priv);
if (priv_data == NULL) {
// Error handling ...
}
// Initialize the counter to 1, and set it as the
// the private object for the connection. The finalizer
// function is specified here.
INIT_OBJ(priv_data, CX_DATA_MAGIC);
priv_data->ctr = 1;
http_cx_set_priv(http, priv_data, cx_priv_free);
}
else {
// A non-NULL pointer returned from http_cx_priv() was
// set previously on the current connection. Check the magic
// number for safety, and increment the counter.
CHECK_OBJ(priv_data, CX_DATA_MAGIC);
priv_data->ctr++;
}
// ...
}
int
main(void)
{
// ...
// Initialize the memory pool in main().
LWIP_MEMPOOL_INIT(cx_priv);
// ...
}
#define CHECK_OBJ(ptr, type_magic)
Assert that an object is valid for its type.
Definition: assertion.h:321
#define INIT_OBJ(to, type_magic)
Initialize an object with its magic number.
Definition: assertion.h:200
static struct resp * http_resp(struct http *http)
Get the current response object.
Definition: http.h:2729
static void http_cx_set_priv(struct http *http, void *priv, priv_fini_f *fini, priv_cnt_f *cnt)
Set a connection-scoped private object.
Definition: http.h:453
static void * http_cx_priv(struct http *http)
Return the connection-scoped private object, if any.
Definition: http.h:479
Current HTTP connection, request and response.
HTTP response.

Macro Definition Documentation

◆ HTTP_DEFAULT_IDLE_TMO_S

#define HTTP_DEFAULT_IDLE_TMO_S   (5)

Default idle timeout in seconds that is set by http_default_cfg().

To change the default, define HTTP_DEFAULT_IDLE_TMO_S before the including picow_http/http.h, for example with a #define before the #include, or with a compiler definition.

See also
http_default_cfg()

◆ HTTP_DEFAULT_LISTEN_BACKLOG

#define HTTP_DEFAULT_LISTEN_BACKLOG   (10)

Default maximum length of the listen queue for incoming connections, set by http_default_cfg().

To change the default, define HTTP_DEFAULT_LISTEN_BACKLOG before the including picow_http/http.h, for example with a #define before the #include, or with a compiler definition.

See also
http_default_cfg()

◆ HTTP_DEFAULT_SEND_TMO_S

#define HTTP_DEFAULT_SEND_TMO_S   (5)

Default send timeout in seconds that is set by http_default_cfg().

To change the default, define HTTP_DEFAULT_SEND_TMO_S before the including picow_http/http.h, for example with a #define before the #include, or with a compiler definition.

See also
http_default_cfg()

Typedef Documentation

◆ priv_fini_f

typedef void priv_fini_f(void *p)

Function typedef for callbacks that finalize private data. The finalizer is called when the private object goes out of scope, so that, for example, allocated memory can be freed, or other kinds of resource cleanup can be performed.

See the discussion and example in Application private data.

Parameters
[in]ppointer to private data that was initially provided by the application. SHALL NOT be NULL.
See also
http_cx_set_priv(), Application private data

Function Documentation

◆ http_cfg()

err_t http_cfg ( const char *  name,
struct server_cfg cfg 
)

Get the default configuration for the server identified by name in the build-time configuration (www.yaml). The values of cfg are set as documented for http_default_cfg().

http_default_cfg() can be used for the server named "default" (which is the default value for the server.name field in www.yaml). http_cfg() is usually only necessary when more than one server/listener is configured.

Example:

struct server_cfg cfg;
if (http_cfg("my_server", &cfg) != ERR_OK) {
// Error handling
}
err_t http_cfg(const char *name, struct server_cfg *cfg)
Get the default confiuration for a server by name.
HTTP server configuration.
Definition: http.h:774
Parameters
[in]nameserver name configured in www.yaml
name MUST be nul-terminated
[out]cfgdefault configuration for the server
Returns
ERR_OK on success
ERR_ARG if either of name or cfg is NULL
ERR_VAL if name is not configured in www.yaml
See also
http_default_cfg(), struct server_cfg, lwIP err_t

◆ http_cx_local_ip()

static ip_addr_t * http_cx_local_ip ( struct http http)
inlinestatic

Return the local IP address of the current HTTP connection. The return value has an lwIP type that represents IP addresses, and may be handled using the lwIP API for address handling. The return value MAY NOT be modified.

Example:

#include "lwip/ip_addr.h"
err_t
my_handler(struct http *http, void *p)
{
ip_addr_t *ip;
// ...
HTTP_LOG_INFO("Local connection: %s:%u", ipaddr_ntoa(ip),
// ...
}
#define HTTP_LOG_INFO(...)
Log an informational message.
Definition: log.h:285
static uint16_t http_cx_local_port(struct http *http)
Return the local port of the current HTTP connection.
Definition: http.h:1184
static ip_addr_t * http_cx_local_ip(struct http *http)
Return the local IP address of the current HTTP connection.
Definition: http.h:1162
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
the HTTP connection's local IP address
See also
http_cx_local_port(), http_cx_remote_ip(), http_cx_remote_port(), lwIP ip_addr_t, lwIP address handling

◆ http_cx_local_port()

static uint16_t http_cx_local_port ( struct http http)
inlinestatic

Return the local port number of the current HTTP connection.

See the example for http_cx_local_ip().

Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
the HTTP connection's local port number
See also
http_cx_local_ip(), http_cx_remote_ip(), http_cx_remote_port()

◆ http_cx_priv()

static void * http_cx_priv ( struct http http)
inlinestatic

Return the private object previously set by http_cx_set_priv() for the client connection represented by http. If http_cx_set_priv() was never called for the current connection, http_cx_priv() returns NULL.

See the discussion and example in Application private data.

Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
pointer to an object set for http in http_cx_set_priv()
NULL if http_cx_set_priv() was not previously called for http
See also
http_cx_set_priv(), Application private data

◆ http_cx_remote_ip()

static ip_addr_t * http_cx_remote_ip ( struct http http)
inlinestatic

Return the remote IP address of the current HTTP connection. The return value has an lwIP type that represents IP addresses, and may be handled using the lwIP API for address handling. The return value MAY NOT be modified.

Example:

#include "lwip/ip_addr.h"
err_t
my_handler(struct http *http, void *p)
{
ip_addr_t *ip;
// ...
HTTP_LOG_INFO("Remote connection: %s:%u", ipaddr_ntoa(ip),
// ...
}
static uint16_t http_cx_remote_port(struct http *http)
Return the remote port of the current HTTP connection.
Definition: http.h:1252
static ip_addr_t * http_cx_remote_ip(struct http *http)
Return the remote IP address of the current HTTP connection.
Definition: http.h:1231
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
the HTTP connection's remote IP address
See also
http_cx_remote_port(), http_cx_local_ip(), http_cx_local_port(), lwIP ip_addr_t, lwIP address handling

◆ http_cx_remote_port()

static uint16_t http_cx_remote_port ( struct http http)
inlinestatic

Return the remote port number of the current HTTP connection.

See the example for http_cx_remote_ip().

Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
the HTTP connection's remote port number
See also
http_cx_remote_ip(), http_cx_local_ip(), http_cx_local_port()

◆ http_cx_set_priv()

static void http_cx_set_priv ( struct http http,
void *  priv,
priv_fini_f fini,
priv_cnt_f *  cnt 
)
inlinestatic

Sets a private object for http, which can be retrieved with http_cx_priv(). priv can be a pointer to an object of any type. It is available for the lifetime of the network connection represented by http; that is, it can be retrieved during every request/response transaction on the same keep-alive connection.

fini is an optional finalizer function for priv. If fini is not NULL, then it is invoked with priv as its argument when the connection closes. That gives an application the opportunity to deallocate resources and do any necessary cleanup. Set fini to NULL if no finalizer is needed.

See the discussion and example in Application private data.

Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
[in]privpointer to an object of any type
[in]finioptional finalizer function for priv; set to NULL if no finalizer is needed
[in]cntoptional next body segment function for http; set to NULL if no continuator is needed
See also
http_cx_priv(), typedef priv_fini_f, Application private data

◆ http_default_cfg()

static struct server_cfg http_default_cfg ( void  )
inlinestatic

Return an instance of struct server_cfg for the server identified as default in the build-time configuration (www.yaml). A server named default MUST be configured in www.yaml (note that default is the default value of server.name in www.yaml). This is a convenience for the case that only one server is configured.

The fields of the returned configuration are set so that:

Example:

static struct server_cfg http_default_cfg(void)
Get the default HTTP server configuration.
Definition: http.h:894
Returns
an HTTP configuration for server default set to default values
See also
http_cfg(), struct server_cfg,

◆ http_srv_fini()

err_t http_srv_fini ( struct server server)

Stop the HTTP server represented by *server. *server MUST be a server started previously by http_srv_init().

On success, the server listener is closed. If no other server is running (i.e. http_srv_fini() has been called for all other servers previously started), then NTP time synchronization is stopped.

Example:

struct server *srv;
struct server_cfg cfg;
if (http_srv_init(&srv, &cfg) != ERR_OK) {
// Error handling
}
// ...
if (http_srv_fini(srv) != ERR_OK) {
// Error handling
}
err_t http_srv_fini(struct server *server)
Stop an HTTP server.
err_t http_srv_init(struct server **server, struct server_cfg *cfg)
Start an HTTP server.
HTTP server.
Parameters
[in]serverpointer to a server previously started by http_srv_init().
Returns
ERR_OK on success
ERR_VAL if server is NULL
or any error returned by the TCP stack for the close operation
if ERR_MEM is returned, the caller should retry http_srv_fini() at a later time, since the TCP stack may be able to free memory
See also
lwIP err_t

◆ http_srv_init()

err_t http_srv_init ( struct server **  server,
struct server_cfg cfg 
)

Start an HTTP server as configured by cfg. The server binds to the address in cfg->ipaddr and cfg->port, and listens for HTTP requests.

NTP synchronization as configured by cfg->ntp_cfg is initiated, unless it has already begun due to an invocation of http_srv_init() for another server. If so, the configuration in cfg->ntp_cfg is ignored.

Example:

struct server *srv;
struct server_cfg cfg;
// Using the default configuration.
if (http_srv_init(&srv, &cfg) != ERR_OK) {
// Error handling
}
Parameters
[out]serverset to a pointer to the server on success
[in]cfgpointer to the server configuration
Returns
ERR_OK on success
ERR_VAL if either of cfg is NULL; if cfg.ntp_cfg->servers is NULL and NTP synchronization was not already initialized; or if either of cfg.idle_tmo_s or cfg.idle_tmo_s is out of range (greater then INT64_MAX microseconds)
ERR_MEM if there is insufficient memory to allocate *server or the underlying TCP structures
or any error returned by the TCP stack for the bind or listen operations
See also
lwIP err_t

◆ http_srv_ip()

ip_addr_t * http_srv_ip ( struct server server)

Return the IP address at which the server is currently listening. server MUST represent a running server when the function is called; that is, http_srv_init() has been called successfully for the server, and http_srv_fini() has not been called.

The return value has an lwIP type that represents IP addresses, and may be handled using the lwIP API for address handling. The return value MAY NOT be modified.

Example:

#include "lwip/ip_addr.h"
struct server *srv;
struct server_cfg cfg;
ip_addr_t *ip;
// ...
if (http_srv_init(&srv, &cfg) != ERR_OK) {
// Error handling ...
}
else {
ip = http_srv_ip(srv);
HTTP_LOG_INFO("Server listening at: %s", ipaddr_ntoa(ip));
switch (ip->type) {
case IPADDR_TYPE_V4:
HTTP_LOG_INFO("IPv4 address");
break;
case IPADDR_TYPE_V6:
HTTP_LOG_INFO("IPv6 address");
break;
case IPADDR_TYPE_ANY:
HTTP_LOG_INFO("'dual-stack' IPv4+IPv6 address");
break;
}
}
ip_addr_t * http_srv_ip(struct server *server)
Return the server listener IP address.
Parameters
[in]servera running HTTP server
Returns
the server's listener IP address
See also
http_srv_port(), lwIP ip_addr_t, lwIP address handling

◆ http_srv_port()

uint16_t http_srv_port ( struct server server)

Return the port number at which server is currently listening. As with http_srv_ip(), server MUST represent a running server when the function is called.

Example:

#include "lwip/ip_addr.h"
struct server *srv;
struct server_cfg cfg;
ip_addr_t *ip;
// ...
if (http_srv_init(&srv, &cfg) != ERR_OK) {
// Error handling ...
}
else {
ip = http_srv_ip(srv);
HTTP_LOG_INFO("Server listening at: %s:%u", ipaddr_ntoa(ip),
}
uint16_t http_srv_port(struct server *server)
Return the server listener port number.
Parameters
[in]servera running HTTP server
Returns
the server's listener port number
See also
http_srv_ip()

◆ http_srv_priv()

static void * http_srv_priv ( struct http http)
inlinestatic

Return the private object previously set by http_srv_set_priv(), if any. If http_srv_set_priv() was never called, http_srv_priv() returns NULL.

See the discussion in Application private data.

Example:

err_t
my_handler(struct http *http, void *priv)
{
struct app_data *srv_data;
srv_data = (struct app_data *)http_srv_priv(http);
if (srv_data == NULL) {
HTTP_LOG_WARN("Server-wide data not set");
// ...
}
// ...
}
#define HTTP_LOG_WARN(...)
Log a warning message.
Definition: log.h:239
static void * http_srv_priv(struct http *http)
Return the server-wide private object, if any.
Definition: http.h:1296
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
pointer to an object set in http_srv_set_priv()
NULL if http_srv_set_priv() was never called.
See also
http_srv_set_priv(), Application private data

◆ http_srv_set_priv()

void http_srv_set_priv ( struct server server,
void *  priv,
priv_fini_f fini 
)

Sets a private object for server, which can be retrieved with http_srv_priv(). priv can be a pointer to an object of any type. This makes it possible for handlers to access server-wide data.

fini is an optional finalizer function for priv. If fini is not NULL, it is invoked with priv as its parameter when http_srv_fini() is invoked.

See the discussion in Application private data.

Example:

// A struct for server-wide application data
static struct app_data my_app_data = {
.foo = 47,
.bar = 11,
};
struct server *srv;
// ...
http_srv_set_priv(srv, &my_app_data, NULL);
// The pointer to my_app_data can now be retrieved in every handler
// with http_srv_priv().
void http_srv_set_priv(struct server *server, void *priv, priv_fini_f *fini)
Set a server-wide private object.
Parameters
[in]servera running HTTP server
[in]privpointer to an object of any type
[in]finioptional finalizer function for priv
set to NULL if no finalizer is needed
See also
http_srv_priv(), Application private data