samples: net: http_client: HTTP client sample application
Simple HTTP client sample that connects to HTTP server and does GET and POST requests. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
eb40499627
commit
a07045d8b2
8 changed files with 538 additions and 0 deletions
16
samples/net/sockets/http_client/CMakeLists.txt
Normal file
16
samples/net/sockets/http_client/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13.1)
|
||||||
|
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||||
|
project(http_client)
|
||||||
|
|
||||||
|
FILE(GLOB app_sources src/*.c)
|
||||||
|
target_sources(app PRIVATE ${app_sources})
|
||||||
|
|
||||||
|
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)
|
||||||
|
|
||||||
|
generate_inc_file_for_target(
|
||||||
|
app
|
||||||
|
src/https-cert.der
|
||||||
|
${gen_dir}/https-cert.der.inc
|
||||||
|
)
|
88
samples/net/sockets/http_client/README.rst
Normal file
88
samples/net/sockets/http_client/README.rst
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
.. _sockets-http-client-sample:
|
||||||
|
|
||||||
|
Socket HTTP Client
|
||||||
|
##################
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
This sample application implements an HTTP(S) client that will do an HTTP
|
||||||
|
or HTTPS request and wait for the response from the HTTP server.
|
||||||
|
|
||||||
|
The source code for this sample application can be found at:
|
||||||
|
:zephyr_file:`samples/net/sockets/http_client`.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
************
|
||||||
|
|
||||||
|
- :ref:`networking_with_host`
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
********************
|
||||||
|
|
||||||
|
You can use this application on a supported board, including
|
||||||
|
running it inside QEMU as described in :ref:`networking_with_qemu`.
|
||||||
|
|
||||||
|
Build the http-client sample application like this:
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/net/sockets/http_client
|
||||||
|
:board: <board to use>
|
||||||
|
:conf: <config file to use>
|
||||||
|
:goals: build
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
Enabling TLS support
|
||||||
|
====================
|
||||||
|
|
||||||
|
Enable TLS support in the sample by building the project with the
|
||||||
|
``overlay-tls.conf`` overlay file enabled using these commands:
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/net/sockets/http_client
|
||||||
|
:board: qemu_x86
|
||||||
|
:conf: "prj.conf overlay-tls.conf"
|
||||||
|
:goals: build
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
An alternative way is to specify ``-DOVERLAY_CONFIG=overlay-tls.conf`` when
|
||||||
|
running ``west build`` or ``cmake``.
|
||||||
|
|
||||||
|
The certificate and private key used by the sample can be found in the sample's
|
||||||
|
:zephyr_file:`samples/net/sockets/http_client/src/` directory.
|
||||||
|
The default certificates used by Socket HTTP Client and
|
||||||
|
``https-server.py`` program found in the
|
||||||
|
`net-tools <https://github.com/zephyrproject-rtos/net-tools>`_ project, enable
|
||||||
|
establishing a secure connection between the samples.
|
||||||
|
|
||||||
|
|
||||||
|
Running http-server in Linux Host
|
||||||
|
=================================
|
||||||
|
|
||||||
|
You can run this ``http-client`` sample application in QEMU
|
||||||
|
and run the ``http-server.py`` (from net-tools) on a Linux host.
|
||||||
|
|
||||||
|
To use QEMU for testing, follow the :ref:`networking_with_qemu` guide.
|
||||||
|
|
||||||
|
In a terminal window:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ ./http-server.py
|
||||||
|
|
||||||
|
Run ``http-client`` application in QEMU:
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/net/sockets/http_client
|
||||||
|
:host-os: unix
|
||||||
|
:board: qemu_x86
|
||||||
|
:conf: prj.conf
|
||||||
|
:goals: run
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
Note that ``http-server.py`` must be running in the Linux host terminal window
|
||||||
|
before you start the http-client application in QEMU.
|
||||||
|
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||||
|
|
||||||
|
You can verify TLS communication with a Linux host as well. Just use the
|
||||||
|
``https-server.py`` program in net-tools project.
|
13
samples/net/sockets/http_client/overlay-tls.conf
Normal file
13
samples/net/sockets/http_client/overlay-tls.conf
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
CONFIG_MAIN_STACK_SIZE=3072
|
||||||
|
CONFIG_NET_BUF_RX_COUNT=80
|
||||||
|
CONFIG_NET_BUF_TX_COUNT=80
|
||||||
|
|
||||||
|
# TLS configuration
|
||||||
|
CONFIG_MBEDTLS=y
|
||||||
|
CONFIG_MBEDTLS_BUILTIN=y
|
||||||
|
CONFIG_MBEDTLS_ENABLE_HEAP=y
|
||||||
|
CONFIG_MBEDTLS_HEAP_SIZE=60000
|
||||||
|
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
|
||||||
|
|
||||||
|
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
|
||||||
|
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6
|
38
samples/net/sockets/http_client/prj.conf
Normal file
38
samples/net/sockets/http_client/prj.conf
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# Networking config
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
CONFIG_NET_IPV4=y
|
||||||
|
CONFIG_NET_IPV6=y
|
||||||
|
CONFIG_NET_TCP=y
|
||||||
|
CONFIG_NET_SHELL=y
|
||||||
|
|
||||||
|
# Sockets
|
||||||
|
CONFIG_NET_SOCKETS=y
|
||||||
|
CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||||
|
CONFIG_NET_SOCKETS_POLL_MAX=4
|
||||||
|
|
||||||
|
# Network driver config
|
||||||
|
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||||
|
|
||||||
|
# Network address config
|
||||||
|
CONFIG_NET_CONFIG_SETTINGS=y
|
||||||
|
CONFIG_NET_CONFIG_NEED_IPV4=y
|
||||||
|
CONFIG_NET_CONFIG_NEED_IPV6=y
|
||||||
|
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||||
|
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
|
||||||
|
# Address of HTTP IPv4 server
|
||||||
|
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
|
||||||
|
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
|
||||||
|
# Address of HTTP IPv6 server
|
||||||
|
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
|
||||||
|
|
||||||
|
# HTTP
|
||||||
|
CONFIG_HTTP_CLIENT=y
|
||||||
|
|
||||||
|
# Network debug config
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_LOG_IMMEDIATE=y
|
||||||
|
CONFIG_NET_LOG=y
|
||||||
|
CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=n
|
||||||
|
CONFIG_NET_HTTP_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
CONFIG_MAIN_STACK_SIZE=2048
|
11
samples/net/sockets/http_client/sample.yaml
Normal file
11
samples/net/sockets/http_client/sample.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
common:
|
||||||
|
tags: net http http_client
|
||||||
|
min_ram: 32
|
||||||
|
# Blacklist qemu_x86_64 because of SSE compile error, see #19066 for details
|
||||||
|
platform_exclude: qemu_x86_64
|
||||||
|
sample:
|
||||||
|
description: HTTP client sample
|
||||||
|
name: http_client
|
||||||
|
tests:
|
||||||
|
sample.net.sockets.http_client:
|
||||||
|
harness: net
|
15
samples/net/sockets/http_client/src/ca_certificate.h
Normal file
15
samples/net/sockets/http_client/src/ca_certificate.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CA_CERTIFICATE_TAG 1
|
||||||
|
|
||||||
|
#define TLS_PEER_HOSTNAME "localhost"
|
||||||
|
|
||||||
|
/* This is the same cert as what is found in net-tools/https-cert.pem file
|
||||||
|
*/
|
||||||
|
static const unsigned char ca_certificate[] = {
|
||||||
|
#include "https-cert.der.inc"
|
||||||
|
};
|
BIN
samples/net/sockets/http_client/src/https-cert.der
Normal file
BIN
samples/net/sockets/http_client/src/https-cert.der
Normal file
Binary file not shown.
357
samples/net/sockets/http_client/src/main.c
Normal file
357
samples/net/sockets/http_client/src/main.c
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(net_http_client_sample, LOG_LEVEL_DBG);
|
||||||
|
|
||||||
|
#include <net/net_ip.h>
|
||||||
|
#include <net/socket.h>
|
||||||
|
#include <net/tls_credentials.h>
|
||||||
|
#include <net/http_client.h>
|
||||||
|
|
||||||
|
#include "ca_certificate.h"
|
||||||
|
|
||||||
|
#define HTTP_PORT 8000
|
||||||
|
#define HTTPS_PORT 4443
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_CONFIG_PEER_IPV6_ADDR)
|
||||||
|
#define SERVER_ADDR6 CONFIG_NET_CONFIG_PEER_IPV6_ADDR
|
||||||
|
#else
|
||||||
|
#define SERVER_ADDR6 ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_CONFIG_PEER_IPV4_ADDR)
|
||||||
|
#define SERVER_ADDR4 CONFIG_NET_CONFIG_PEER_IPV4_ADDR
|
||||||
|
#else
|
||||||
|
#define SERVER_ADDR4 ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_RECV_BUF_LEN 512
|
||||||
|
|
||||||
|
static u8_t recv_buf_ipv4[MAX_RECV_BUF_LEN];
|
||||||
|
static u8_t recv_buf_ipv6[MAX_RECV_BUF_LEN];
|
||||||
|
|
||||||
|
static int setup_socket(sa_family_t family, const char *server, int port,
|
||||||
|
int *sock, struct sockaddr *addr, socklen_t addr_len)
|
||||||
|
{
|
||||||
|
const char *family_str = family == AF_INET ? "IPv4" : "IPv6";
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
memset(addr, 0, addr_len);
|
||||||
|
|
||||||
|
if (family == AF_INET) {
|
||||||
|
net_sin(addr)->sin_family = AF_INET;
|
||||||
|
net_sin(addr)->sin_port = htons(port);
|
||||||
|
inet_pton(family, server, &net_sin(addr)->sin_addr);
|
||||||
|
} else {
|
||||||
|
net_sin6(addr)->sin6_family = AF_INET6;
|
||||||
|
net_sin6(addr)->sin6_port = htons(port);
|
||||||
|
inet_pton(family, server, &net_sin6(addr)->sin6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
|
||||||
|
sec_tag_t sec_tag_list[] = {
|
||||||
|
CA_CERTIFICATE_TAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
*sock = socket(family, SOCK_STREAM, IPPROTO_TLS_1_2);
|
||||||
|
if (*sock >= 0) {
|
||||||
|
ret = setsockopt(*sock, SOL_TLS, TLS_SEC_TAG_LIST,
|
||||||
|
sec_tag_list, sizeof(sec_tag_list));
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to set %s secure option (%d)",
|
||||||
|
family_str, -errno);
|
||||||
|
ret = -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = setsockopt(*sock, SOL_TLS, TLS_HOSTNAME,
|
||||||
|
TLS_PEER_HOSTNAME,
|
||||||
|
sizeof(TLS_PEER_HOSTNAME));
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to set %s TLS_HOSTNAME "
|
||||||
|
"option (%d)", family_str, -errno);
|
||||||
|
ret = -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*sock < 0) {
|
||||||
|
LOG_ERR("Failed to create %s HTTP socket (%d)", family_str,
|
||||||
|
-errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int payload_cb(int sock, struct http_request *req, void *user_data)
|
||||||
|
{
|
||||||
|
const char *content[] = {
|
||||||
|
"foobar",
|
||||||
|
"chunked",
|
||||||
|
"last"
|
||||||
|
};
|
||||||
|
char tmp[64];
|
||||||
|
int i, pos = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(content); i++) {
|
||||||
|
pos += snprintk(tmp + pos, sizeof(tmp) - pos,
|
||||||
|
"%x\r\n%s\r\n",
|
||||||
|
(unsigned int)strlen(content[i]),
|
||||||
|
content[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += snprintk(tmp + pos, sizeof(tmp) - pos, "0\r\n\r\n");
|
||||||
|
|
||||||
|
(void)send(sock, tmp, pos, 0);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void response_cb(struct http_response *rsp,
|
||||||
|
enum http_final_call final_data,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (final_data == HTTP_DATA_MORE) {
|
||||||
|
LOG_INF("Partial data received (%zd bytes)", rsp->data_len);
|
||||||
|
} else if (final_data == HTTP_DATA_FINAL) {
|
||||||
|
LOG_INF("All the data received (%zd bytes)", rsp->data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Response to %s", (const char *)user_data);
|
||||||
|
LOG_INF("Response status %s", rsp->http_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int connect_socket(sa_family_t family, const char *server, int port,
|
||||||
|
int *sock, struct sockaddr *addr, socklen_t addr_len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = setup_socket(family, server, port, sock, addr, addr_len);
|
||||||
|
if (ret < 0 || *sock < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = connect(*sock, addr, addr_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Cannot connect to %s remote (%d)",
|
||||||
|
family == AF_INET ? "IPv4" : "IPv6",
|
||||||
|
-errno);
|
||||||
|
ret = -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 addr6;
|
||||||
|
struct sockaddr_in addr4;
|
||||||
|
int sock4 = -1, sock6 = -1;
|
||||||
|
s32_t timeout = K_SECONDS(3);
|
||||||
|
int ret;
|
||||||
|
int port = HTTP_PORT;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
|
||||||
|
ret = tls_credential_add(CA_CERTIFICATE_TAG,
|
||||||
|
TLS_CREDENTIAL_CA_CERTIFICATE,
|
||||||
|
ca_certificate,
|
||||||
|
sizeof(ca_certificate));
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to register public certificate: %d",
|
||||||
|
ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
port = HTTPS_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
(void)connect_socket(AF_INET, SERVER_ADDR4, port,
|
||||||
|
&sock4, (struct sockaddr *)&addr4,
|
||||||
|
sizeof(addr4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
(void)connect_socket(AF_INET6, SERVER_ADDR6, port,
|
||||||
|
&sock6, (struct sockaddr *)&addr6,
|
||||||
|
sizeof(addr6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 < 0 && sock6 < 0) {
|
||||||
|
LOG_ERR("Cannot create HTTP connection.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
struct http_request req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_GET;
|
||||||
|
req.url = "/";
|
||||||
|
req.host = SERVER_ADDR4;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv4;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv4);
|
||||||
|
|
||||||
|
ret = http_client_req(sock4, &req, timeout, "IPv4 GET");
|
||||||
|
|
||||||
|
close(sock4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock6 >= 0 && IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
struct http_request req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_GET;
|
||||||
|
req.url = "/";
|
||||||
|
req.host = SERVER_ADDR6;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv6;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv6);
|
||||||
|
|
||||||
|
ret = http_client_req(sock6, &req, timeout, "IPv6 GET");
|
||||||
|
|
||||||
|
close(sock6);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock4 = -1;
|
||||||
|
sock6 = -1;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
(void)connect_socket(AF_INET, SERVER_ADDR4, port,
|
||||||
|
&sock4, (struct sockaddr *)&addr4,
|
||||||
|
sizeof(addr4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
(void)connect_socket(AF_INET6, SERVER_ADDR6, port,
|
||||||
|
&sock6, (struct sockaddr *)&addr6,
|
||||||
|
sizeof(addr6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 < 0 && sock6 < 0) {
|
||||||
|
LOG_ERR("Cannot create HTTP connection.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
struct http_request req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_POST;
|
||||||
|
req.url = "/foobar";
|
||||||
|
req.host = SERVER_ADDR4;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.payload = "foobar";
|
||||||
|
req.payload_len = strlen(req.payload);
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv4;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv4);
|
||||||
|
|
||||||
|
ret = http_client_req(sock4, &req, timeout, "IPv4 POST");
|
||||||
|
|
||||||
|
close(sock4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock6 >= 0 && IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
struct http_request req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_POST;
|
||||||
|
req.url = "/";
|
||||||
|
req.host = SERVER_ADDR6;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.payload = "foobar";
|
||||||
|
req.payload_len = strlen(req.payload);
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv6;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv6);
|
||||||
|
|
||||||
|
ret = http_client_req(sock6, &req, timeout, "IPv6 POST");
|
||||||
|
|
||||||
|
close(sock6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do a chunked POST request */
|
||||||
|
|
||||||
|
sock4 = -1;
|
||||||
|
sock6 = -1;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
(void)connect_socket(AF_INET, SERVER_ADDR4, port,
|
||||||
|
&sock4, (struct sockaddr *)&addr4,
|
||||||
|
sizeof(addr4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
(void)connect_socket(AF_INET6, SERVER_ADDR6, port,
|
||||||
|
&sock6, (struct sockaddr *)&addr6,
|
||||||
|
sizeof(addr6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 < 0 && sock6 < 0) {
|
||||||
|
LOG_ERR("Cannot create HTTP connection.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||||
|
struct http_request req;
|
||||||
|
const char *headers[] = {
|
||||||
|
"Transfer-Encoding: chunked\r\n",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_POST;
|
||||||
|
req.url = "/chunked-test";
|
||||||
|
req.host = SERVER_ADDR4;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.payload_cb = payload_cb;
|
||||||
|
req.header_fields = headers;
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv4;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv4);
|
||||||
|
|
||||||
|
ret = http_client_req(sock4, &req, timeout, "IPv4 POST");
|
||||||
|
|
||||||
|
close(sock4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock6 >= 0 && IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||||
|
struct http_request req;
|
||||||
|
const char *headers[] = {
|
||||||
|
"Transfer-Encoding: chunked\r\n",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
req.method = HTTP_POST;
|
||||||
|
req.url = "/chunked-test";
|
||||||
|
req.host = SERVER_ADDR6;
|
||||||
|
req.protocol = "HTTP/1.1";
|
||||||
|
req.payload_cb = payload_cb;
|
||||||
|
req.header_fields = headers;
|
||||||
|
req.response = response_cb;
|
||||||
|
req.recv_buf = recv_buf_ipv6;
|
||||||
|
req.recv_buf_len = sizeof(recv_buf_ipv6);
|
||||||
|
|
||||||
|
ret = http_client_req(sock6, &req, timeout, "IPv6 POST");
|
||||||
|
|
||||||
|
close(sock6);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_FOREVER);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue