Download client
The download client library can be used to download files from an HTTP or a CoAP server.
Overview
The download is carried out in a separate thread, and the application receives events such as DOWNLOAD_CLIENT_EVT_FRAGMENT
that contain the data fragments as the download progresses.
The fragment size can be configured independently for HTTP and CoAP (block-wise transfer).
When the download completes, the library sends the DOWNLOAD_CLIENT_EVT_DONE
event to the application.
Protocols
The library supports HTTP, HTTPS (TLS 1.2), CoAP, and CoAPS (DTLS 1.2) over IPv4 and IPv6.
HTTP and HTTPS (TLS 1.2)
In the case of download using HTTP, the library sends only one HTTP request to the server and receives only one HTTP response.
In the case of download using HTTPS, it is carried out through Content-Range requests (IETF RFC 7233) due to memory constraints that limit the maximum HTTPS message size to 2 kilobytes. The library thus sends and receives as many requests and responses as the number of fragments that constitutes the download. For example, to download a file of size 47 kilobytes file with a fragment size of 2 kilobytes, a total of 24 HTTP GET requests are sent. It is therefore recommended to use the largest fragment size to minimize the network usage.
CoAP and CoAPS (DTLS 1.2)
When downloading from a CoAP server, the library uses the CoAP block-wise transfer.
Configuration
The configuration of the library depends on the protocol you are using.
Configuring HTTP and HTTPS (TLS 1.2)
Set the CONFIG_DOWNLOAD_CLIENT_BUF_SIZE
and CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE
Kconfig options, so that the buffer is large enough to accommodate the entire HTTP header of the request and the response.
Moreover, the application must provision the TLS credentials and pass the security tag to the library when using HTTPS and calling the download_client_set_host()
function.
To provision a TLS certificate to the modem, use modem_key_mgmt_write()
and other Modem key management APIs.
Configuring CoAP and CoAPS (DTLS 1.2)
Make sure to configure the CONFIG_DOWNLOAD_CLIENT_BUF_SIZE
and CONFIG_DOWNLOAD_CLIENT_COAP_BLOCK_SIZE
Kconfig options, so that the buffer is large enough to accommodate the entire CoAP header and the CoAP block.
The application must provision the TLS credentials and pass the security tag to the library when using CoAPS and calling download_client_set_host()
.
When you have modem firmware v1.3.5 or newer, you can use the CONFIG_DOWNLOAD_CLIENT_CID
Kconfig option to enable the DTLS Connection Identifier feature in this library.
Limitations
The library requires the host server to provide a Content-Range field in the HTTP GET header when using HTTPS. If this header field is missing, the library logs the following error:
<err> download_client: Server did not send "Content-Range" in response
It is not possible to use a CoAP block size of 1024 bytes, due to internal limitations.
API documentation
include/download_client.h
subsys/net/lib/download_client/src/
- group dl_client
Client for downloading an object.
The download client provides APIs for:
connecting to a remote server,
downloading an object from the server,
disconnecting from the server,
receiving asynchronous event notifications on the download status.
Typedefs
-
typedef int (*download_client_callback_t)(const struct download_client_evt *event)
Download client asynchronous event handler.
Through this callback, the application receives events, such as download of a fragment, download completion, or errors.
If the callback returns a non-zero value, the download stops. To resume the download, use download_client_start().
- Param event:
[in] The event.
- Return:
Zero to continue the download, non-zero otherwise.
Enums
-
enum download_client_evt_id
Download client event IDs.
Values:
-
enumerator DOWNLOAD_CLIENT_EVT_FRAGMENT
Event contains a fragment. The application may return any non-zero value to stop the download.
-
enumerator DOWNLOAD_CLIENT_EVT_ERROR
An error has occurred during download and the connection to the server has been lost.
Error reason may be one of the following:
ECONNRESET: socket error, peer closed connection
ECONNREFUSED: socket error, connection refused by server
ENETDOWN: socket error, network down
ETIMEDOUT: socket error, connection timed out
EHOSTDOWN: host went down during download
EBADMSG: HTTP response header not as expected
ERANGE: HTTP response does not support range requests
E2BIG: HTTP response header could not fit in buffer
EPROTONOSUPPORT: Protocol is not supported
EINVAL: Invalid configuration
EAFNOSUPPORT: Unsupported address family (IPv4/IPv6)
EHOSTUNREACH: Failed to resolve the target address
In case of errors on the socket during send() or recv() (ECONNRESET), returning zero from the callback will let the library attempt to reconnect to the server and download the last fragment again. Otherwise, the application may return any non-zero value to stop the download. On any other error code than ECONNRESET, the client will not attempt to reconnect and ignores the return value.
In case the download is stopped, and it was started using download_client_get, the download client automatically closes the connection. The application should wait for DOWNLOAD_CLIENT_EVT_CLOSED before attempting another download. If download is stopped, and it was started using download_client_start the application should manually disconnect (download_client_disconnect) to clean up the network socket and wait for DOWNLOAD_CLIENT_EVT_CLOSED before attempting another download.
-
enumerator DOWNLOAD_CLIENT_EVT_DONE
Download complete.
-
enumerator DOWNLOAD_CLIENT_EVT_CLOSED
Connection have been closed. Client is now idle, ready for next download
-
enumerator DOWNLOAD_CLIENT_EVT_FRAGMENT
Functions
-
int download_client_init(struct download_client *client, download_client_callback_t callback)
Initialize the download client.
This function can only be called once in each client instance as it starts the background thread.
- Parameters:
client – [in] Client instance.
callback – [in] Callback function.
- Return values:
int – Zero on success, otherwise a negative error code.
-
int download_client_set_host(struct download_client *client, const char *host, const struct download_client_cfg *config)
Set a target hostname.
- Parameters:
client – [in] Client instance.
host – [in] Name of the host to connect to, null-terminated. Can include scheme and port number, defaults to HTTP or HTTPS if no scheme is provided.
config – [in] Configuration options.
- Return values:
int – Zero on success, a negative error code otherwise.
-
int download_client_start(struct download_client *client, const char *file, size_t from)
Download a file.
The download is carried out in fragments of up to
CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE
bytes for HTTP, orCONFIG_DOWNLOAD_CLIENT_COAP_BLOCK_SIZE
bytes for CoAP, which are delivered to the application via DOWNLOAD_CLIENT_EVT_FRAGMENT events.- Parameters:
client – [in] Client instance.
file – [in] File to download, null-terminated.
from – [in] Offset from where to resume the download, or zero to download from the beginning.
- Return values:
int – Zero on success, a negative error code otherwise.
-
int download_client_file_size_get(struct download_client *client, size_t *size)
Retrieve the size of the file being downloaded, in bytes.
The file size is only available after the download has begun.
- Parameters:
client – [in] Client instance.
size – [out] File size.
- Return values:
int – Zero on success, a negative error code otherwise.
-
int download_client_downloaded_size_get(struct download_client *client, size_t *size)
Retrieve the number of bytes downloaded so far.
The progress is only available after the download has begun.
- Parameters:
client – [in] Client instance.
size – [out] Number of bytes downloaded so far.
- Return values:
int – Zero on success, a negative error code otherwise.
-
int download_client_disconnect(struct download_client *client)
Initiate disconnection.
Request client to disconnect from the server. This does not block. When client have been disconnected, it send DOWNLOAD_CLIENT_EVT_CLOSED event.
Request client to disconnect from the server. This does not block. When client has been disconnected, it sends DOWNLOAD_CLIENT_EVT_CLOSED event.
- Parameters:
client – [in] Client instance.
- Returns:
Zero on success, a negative error code otherwise.
-
int download_client_get(struct download_client *client, const char *host, const struct download_client_cfg *config, const char *file, size_t from)
Download a file asynchronously.
This initiates an asynchronous connect-download-disconnect sequence to the target host. When only one file is required from a target server, it can be used instead of separate calls to download_client_set_host(), download_client_start() and download_client_disconnect().
Downloads are handled one at a time. If previous download is not finished this returns -EALREADY.
The download is carried out in fragments of up to
CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE
bytes for HTTP, orCONFIG_DOWNLOAD_CLIENT_COAP_BLOCK_SIZE
bytes for CoAP, which are delivered to the application through DOWNLOAD_CLIENT_EVT_FRAGMENT events.- Parameters:
client – [in] Client instance.
host – [in] URI of the host to connect to. Can include scheme, port number and full file path, defaults to HTTP or HTTPS if no scheme is provided.
config – [in] Configuration options.
file – [in] File to download or NULL if path is already provided in host parameter.
from – [in] Offset from where to resume the download, or zero to download from the beginning.
- Return values:
int – Zero on success, a negative error code otherwise.
-
struct download_fragment
- #include <download_client.h>
-
struct download_client_evt
- #include <download_client.h>
Download client event.
Public Members
-
enum download_client_evt_id id
Event ID.
-
int error
Error cause.
-
struct download_fragment fragment
Fragment data.
-
enum download_client_evt_id id
-
struct download_client_cfg
- #include <download_client.h>
Download client configuration options.
Public Members
-
const int *sec_tag_list
TLS security tag list. Pass NULL to disable TLS. The list must be kept in scope while download is going on.
-
uint8_t sec_tag_count
Number of TLS security tags in list. Set to 0 to disable TLS.
-
uint8_t pdn_id
PDN ID to be used for the download. Zero is the default PDN.
-
int family
Address family to be used for the download, AF_INET6 or AF_INET. Set to AF_UNSPEC (0) to fallback to AF_INET if AF_INET6 does not work.
-
size_t frag_size_override
Maximum fragment size to download. 0 indicates that values configured using Kconfig shall be used.
-
bool set_tls_hostname
Set hostname for TLS Server Name Indication extension
-
const int *sec_tag_list
-
struct download_client
- #include <download_client.h>
Download client instance.
Public Members
-
int fd
Socket descriptor.
-
char buf[CONFIG_DOWNLOAD_CLIENT_BUF_SIZE]
Response buffer.
-
size_t offset
Buffer offset.
-
size_t file_size
Size of the file being downloaded, in bytes.
-
size_t progress
Download progress, number of bytes downloaded.
-
const char *host
Server hosting the file, null-terminated. The host name must be kept in scope while download is going on.
-
const char *file
File name, null-terminated. The file name must be kept in scope while download is going on.
-
struct download_client_cfg config
Configuration options.
-
int proto
Protocol for current download.
-
bool has_header
Whether the HTTP header for the current fragment has been processed.
-
bool connection_close
The server has closed the connection.
-
bool ranged
Is using ranged query.
-
struct coap_block_context block_ctx
CoAP block context.
-
struct coap_pending pending
CoAP pending object.
-
k_tid_t tid
Internal thread ID.
-
struct k_sem wait_for_download
Ensure that thread is ready for download
-
download_client_callback_t callback
Event handler.
-
bool set_native_tls
Set socket to native TLS
-
bool close_when_done
Close the socket when finished.
-
int fd