Download client

The download client library provides functions to download resources from a remote server. The resource could, for example, be a firmware image. Currently, the only supported protocol for the download is HTTP.

The library is designed to download large objects like firmware images. However, it does not impose any requirements on the object that is being downloaded, which means that you can use the library for any kind of object, not only firmware images. There are also no constraints on the object if it is a firmware image. The image can be of any form, for example, a delta image or a full image with many merged HEX files, and there is no revision management or specification of the flash address where the image is downloaded.

The size of the object to download is obtained from the server. The object is then downloaded in fragments of a maximum fragment size (CONFIG_NRF_DOWNLOAD_MAX_FRAGMENT_SIZE). For example, if the size of the object to be downloaded is 60478 bytes and the maximum fragment size is 1024 bytes, the module downloads 60 fragments of the object; 59 fragments with a size of 1024 bytes and one fragment with a size of 62 bytes. If any of the download requests fail, they can be repeated.

After every fragment download, a download_client_evt is returned, indicating if the download was successful (DOWNLOAD_CLIENT_EVT_DOWNLOAD_FRAG), failed (DOWNLOAD_CLIENT_EVT_ERROR), or is completed (DOWNLOAD_CLIENT_EVT_DOWNLOAD_DONE).

Make sure to configure CONFIG_NRF_DOWNLOAD_MAX_FRAGMENT_SIZE in a way that suits your application. A low value causes many download requests, which can result in too much protocol overhead, while a large value requires a lot of RAM.

Protocols

The download protocol is determined from the download URI. Currently, only HTTP is supported.

HTTP

For HTTP, the following requirements must be met:

  • The address family is IPv4.
  • TCP transport is used to communicate with the server.
  • The application protocol to communicate with the server is HTTP 1.1.
  • IETF RFC 7233 is supported by the HTTP Server.
  • CONFIG_NRF_DOWNLOAD_MAX_FRAGMENT_SIZE is configured so that it can contain the entire HTTP response.

HTTPS is not supported.

The library uses the “Range” header to request firmware fragments of size CONFIG_NRF_DOWNLOAD_MAX_FRAGMENT_SIZE. The firmware size is obtained from the “Content-Length” header in the response. To request the server to keep the TCP connection after a partial content response, the “Connection: keep-alive” header is included in the request. If the server response contains “Connection: close”, the library automatically reconnects to the server and resumes the download.

API documentation

group dl_client

Client to download an object.

Typedefs

typedef int (*download_client_event_handler_t)(struct download_client *client, enum download_client_evt event, u32_t status)

Download client asynchronous event handler.

The application is notified of the status of the object download through this event handler. The application can use the return value to indicate if it handled the event successfully or not. This feedback is useful when, for example, a faulty fragment was received or the application was unable to process a object fragment.

Parameters
  • client: The client instance.
  • event: The event.
  • status: Event status (either 0 or an errno value).
Return Value
  • 0: If the event was handled successfully. Other values indicate that the application failed to handle the event.

Enums

enum download_client_status

Download states.

Values:

DOWNLOAD_CLIENT_STATUS_IDLE = 0x00

Indicates that the client was either never connected to the server or is now disconnected.

DOWNLOAD_CLIENT_STATUS_CONNECTED = 0x01

Indicates that the client is connected to the server and there is no ongoing download.

DOWNLOAD_CLIENT_STATUS_DOWNLOAD_INPROGRESS = 0x02

Indicates that the client is connected to the server and download is in progress.

DOWNLOAD_CLIENT_STATUS_DOWNLOAD_COMPLETE = 0x03

Indicates that the client is connected to the server and download is complete.

DOWNLOAD_CLIENT_STATUS_HALTED = 0x04

Indicates that the object download is halted by the application. This status indicates that the application identified a failure when handling the DOWNLOAD_CLIENT_EVT_DOWNLOAD_FRAG event.

DOWNLOAD_CLIENT_ERROR = 0xFF

Indicates that an error occurred and the download cannot continue.

enum download_client_evt

Download events.

Values:

DOWNLOAD_CLIENT_EVT_ERROR = 0x00

Indicates an error during download. The application should disconnect and retry the operation when receiving this event.

DOWNLOAD_CLIENT_EVT_DOWNLOAD_FRAG = 0x01

Indicates reception of a fragment during download. The fragment field of the download_client object points to the object fragment, and the fragment size indicates the size of the fragment.

DOWNLOAD_CLIENT_EVT_DOWNLOAD_DONE = 0x02

Indicates that the download is complete.

Functions

int download_client_init(struct download_client *client)

Initialize the download client object for a given host and resource.

The server to connect to for the object download is identified by the host field of client. The callback field of client must contain an event handler.

Note
If this method fails, do no call any other APIs for the instance.
Parameters
  • client: The client instance. Must not be NULL. The target, host, resource, and callback fields must be correctly initialized in the object instance. The fd, status, fragment, fragment_size, download_size, and object_size fields are out parameters.
Return Value
  • 0: If the operation was successful.
  • -1: Otherwise.

int download_client_connect(struct download_client *client)

Establish a connection to the server.

The server to connect to for the object download is identified by the host field of client. The host field is expected to be a that can be resolved to an IP address using DNS.

Note
This is a blocking call. Do not initiate a download_client_start if this procedure fails.
Parameters
  • client: The client instance.
Return Value
  • 0: If the operation was successful.
  • -1: Otherwise.

int download_client_start(struct download_client *client)

Start downloading the object.

This is a blocking call used to trigger the download of an object identified by the resource field of client. The download is requested from the server in chunks of CONFIG_NRF_DOWNLOAD_MAX_FRAGMENT_SIZE.

This API may be used to resume an interrupted download by setting the download_size field of client to the last successfully downloaded fragment of the object.

If the API succeeds, use download_client_process to advance the download until a DOWNLOAD_CLIENT_EVT_ERROR or a DOWNLOAD_CLIENT_EVT_DOWNLOAD_DONE event is received in the registered callback. If the API fails, disconnect using download_client_disconnect, then reconnect using download_client_connect and restart the procedure.

Parameters
  • client: The client instance.
Return Value
  • 0: If the operation was successful.
  • -1: Otherwise.

void download_client_process(struct download_client *client)

Advance the object download.

Call this API to advance the download state identified by the status field of client. This is a blocking call. You can poll the fd field of client to decide whether to call this method.

Parameters
  • client: The client instance.

void download_client_disconnect(struct download_client *client)

Disconnect from the server.

This API terminates the connection to the server. If called before the download is complete, it is possible to resume the interrupted transfer by reconnecting to the server using the download_client_connect API and calling download_client_start to continue the download. If you want to resume after a power cycle, you must store the download size persistently and supply this value in the next connection.

Note
You should disconnect from the server as soon as the download is complete.
Parameters
  • client: The client instance.

struct download_client
#include <download_client.h>

Object download client instance that describes the state of download.

Public Members

char resp_buf[CONFIG_NRF_DOWNLOAD_MAX_RESPONSE_SIZE]

Buffer used to receive responses from the server. This buffer can be read by the application if necessary, but must never be written to.

char req_buf[CONFIG_NRF_DOWNLOAD_MAX_REQUEST_SIZE]

Buffer used to create requests to the server. This buffer can be read by the application if necessary, but must never be written to.

char *fragment

Pointer to the object fragment in resp_buf. The response from the server contains protocol metadata in addition to the object fragment. On every DOWNLOAD_CLIENT_EVT_DOWNLOAD_FRAG event, this pointer is updated to point to the latest object fragment. This pointer shall not be updated by the application.

int fragment_size

Size of the fragment. The size is updated on every DOWNLOAD_CLIENT_EVT_DOWNLOAD_FRAG event.

int fd

Transport file descriptor. If negative, the transport is disconnected.

int object_size

Total size of the object being downloaded. If negative, the download is in progress. If zero, the size is unknown.

volatile int download_size

Current size of the object being downloaded.

volatile int status

Status of the transfer (see download_client_status).

const char *host

Server that hosts the object.

const char *resource

Resource to be downloaded.

const download_client_event_handler_t callback

Event handler. Must not be NULL.