samples: net: websocket: App for doing Websocket client requests
This is BSD sockets based application for connecting to Websocket server. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
6af987646f
commit
b031a5a163
8 changed files with 608 additions and 0 deletions
16
samples/net/sockets/websocket_client/CMakeLists.txt
Normal file
16
samples/net/sockets/websocket_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
|
||||
)
|
94
samples/net/sockets/websocket_client/README.rst
Normal file
94
samples/net/sockets/websocket_client/README.rst
Normal file
|
@ -0,0 +1,94 @@
|
|||
.. _sockets-websocket-client-sample:
|
||||
|
||||
Socket Websocket Client
|
||||
#######################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample application implements a Websocket client that will do an HTTP
|
||||
or HTTPS handshake request to HTTP server, then start to send data and wait for
|
||||
the responses from the Websocket server.
|
||||
|
||||
The source code for this sample application can be found at:
|
||||
:zephyr_file:`samples/net/sockets/websocket_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 websocket-client sample application like this:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/net/sockets/websocket_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/websocket_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/websocket_client/src/` directory.
|
||||
|
||||
|
||||
Running websocket-server in Linux Host
|
||||
======================================
|
||||
|
||||
You can run this ``websocket-client`` sample application in QEMU
|
||||
and run the ``zephyr-websocket-server.py`` (from net-tools) on a Linux host.
|
||||
Other alternative is to install `websocketd <http://websocketd.com/>`_ and
|
||||
use that.
|
||||
|
||||
To use QEMU for testing, follow the :ref:`networking_with_qemu` guide.
|
||||
|
||||
In a terminal window you can do either:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ./zephyr-websocket-server.py
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ websocketd --port=9001 cat
|
||||
|
||||
Run ``websocket-client`` application in QEMU:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/net/sockets/websocket_client
|
||||
:host-os: unix
|
||||
:board: qemu_x86
|
||||
:conf: prj.conf
|
||||
:goals: run
|
||||
:compact:
|
||||
|
||||
Note that ``zephyr-websocket-server.py`` or ``websocketd`` must be running in
|
||||
the Linux host terminal window before you start the ``websocket-client``
|
||||
application in QEMU. Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Current version of ``zephyr-websocket-server.py`` found in
|
||||
`net-tools <https://github.com/zephyrproject-rtos/net-tools>`_ project, does
|
||||
not support TLS.
|
13
samples/net/sockets/websocket_client/overlay-tls.conf
Normal file
13
samples/net/sockets/websocket_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
|
44
samples/net/sockets/websocket_client/prj.conf
Normal file
44
samples/net/sockets/websocket_client/prj.conf
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Networking config
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_SHELL=y
|
||||
CONFIG_NET_STATISTICS=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 & Websocket
|
||||
CONFIG_HTTP_CLIENT=y
|
||||
CONFIG_WEBSOCKET_CLIENT=y
|
||||
|
||||
# Network debug config
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_IMMEDIATE=y
|
||||
CONFIG_NET_LOG=y
|
||||
#CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y
|
||||
#CONFIG_NET_HTTP_LOG_LEVEL_DBG=y
|
||||
#CONFIG_NET_WEBSOCKET_LOG_LEVEL_DBG=y
|
||||
#CONFIG_NET_CONTEXT_LOG_LEVEL_DBG=y
|
||||
#CONFIG_NET_TCP_LOG_LEVEL_DBG=y
|
||||
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=1500
|
11
samples/net/sockets/websocket_client/sample.yaml
Normal file
11
samples/net/sockets/websocket_client/sample.yaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
common:
|
||||
tags: net http http_client websocket_client websocket
|
||||
min_ram: 35
|
||||
# Blacklist qemu_x86_64 because of SSE compile error, see #19066 for details
|
||||
platform_exclude: qemu_x86_64
|
||||
sample:
|
||||
description: Websocket client sample
|
||||
name: websocket_client
|
||||
tests:
|
||||
sample.net.sockets.websocket_client:
|
||||
harness: net
|
15
samples/net/sockets/websocket_client/src/ca_certificate.h
Normal file
15
samples/net/sockets/websocket_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/websocket_client/src/https-cert.der
Normal file
BIN
samples/net/sockets/websocket_client/src/https-cert.der
Normal file
Binary file not shown.
415
samples/net/sockets/websocket_client/src/main.c
Normal file
415
samples/net/sockets/websocket_client/src/main.c
Normal file
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(net_websocket_client_sample, LOG_LEVEL_DBG);
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/socket.h>
|
||||
#include <net/tls_credentials.h>
|
||||
#include <net/websocket.h>
|
||||
#include <shell/shell.h>
|
||||
|
||||
#include "ca_certificate.h"
|
||||
|
||||
#define PORT 9001
|
||||
|
||||
#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
|
||||
|
||||
/* Generated by http://www.lipsum.com/
|
||||
* 2 paragraphs, 178 words, 1160 bytes of Lorem Ipsum
|
||||
*/
|
||||
const char lorem_ipsum[] =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
|
||||
"Vestibulum ultricies sapien tellus, ac viverra dolor bibendum "
|
||||
"lacinia. Vestibulum et nisl tristique tellus finibus gravida "
|
||||
"vitae sit amet nunc. Suspendisse maximus justo mi, vitae porta "
|
||||
"risus suscipit vitae. Curabitur ut fringilla velit. Donec ac nisi "
|
||||
"in dui semper lobortis sed nec ante. Sed nec luctus dui. Sed ut "
|
||||
"ante nisi. Mauris congue euismod felis, et maximus ex pellentesque "
|
||||
"nec. Proin nibh nisl, semper at nunc in, mattis pharetra metus. Nam "
|
||||
"turpis risus, pulvinar sit amet varius ac, pellentesque quis purus."
|
||||
" "
|
||||
"Nam consequat purus in lacinia fringilla. Morbi volutpat, tellus "
|
||||
"nec tempus dapibus, ante sem aliquam dui, eu feugiat libero diam "
|
||||
"at leo. Sed suscipit egestas orci in ultrices. Integer in elementum "
|
||||
"ligula, vel sollicitudin velit. Nullam sit amet eleifend libero. "
|
||||
"Proin sit amet consequat tellus, vel vulputate arcu. Curabitur quis "
|
||||
"lobortis lacus. Sed faucibus vestibulum enim vel elementum. Vivamus "
|
||||
"enim nunc, auctor in purus at, aliquet pulvinar eros. Cras dapibus "
|
||||
"nec quam laoreet sagittis. Quisque dictum ante odio, at imperdiet "
|
||||
"est convallis a. Morbi mattis ut orci vitae volutpat."
|
||||
"\n";
|
||||
|
||||
#define MAX_RECV_BUF_LEN (sizeof(lorem_ipsum) - 1)
|
||||
|
||||
const int ipsum_len = MAX_RECV_BUF_LEN;
|
||||
|
||||
static u8_t recv_buf_ipv4[MAX_RECV_BUF_LEN];
|
||||
static u8_t recv_buf_ipv6[MAX_RECV_BUF_LEN];
|
||||
|
||||
/* We need to allocate bigger buffer for the websocket data we receive so that
|
||||
* the websocket header fits into it.
|
||||
*/
|
||||
#define EXTRA_BUF_SPACE 30
|
||||
|
||||
static u8_t temp_recv_buf_ipv4[MAX_RECV_BUF_LEN + EXTRA_BUF_SPACE];
|
||||
static u8_t temp_recv_buf_ipv6[MAX_RECV_BUF_LEN + EXTRA_BUF_SPACE];
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
static int connect_cb(int sock, struct http_request *req, void *user_data)
|
||||
{
|
||||
LOG_INF("Websocket %d for %s connected.", sock, (char *)user_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t how_much_to_send(size_t max_len)
|
||||
{
|
||||
size_t amount;
|
||||
|
||||
do {
|
||||
amount = sys_rand32_get() % max_len;
|
||||
} while (amount == 0U);
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
static ssize_t sendall_with_ws_api(int sock, const void *buf, size_t len)
|
||||
{
|
||||
return websocket_send_msg(sock, buf, len, WEBSOCKET_OPCODE_DATA_TEXT,
|
||||
true, true, K_FOREVER);
|
||||
}
|
||||
|
||||
static ssize_t sendall_with_bsd_api(int sock, const void *buf, size_t len)
|
||||
{
|
||||
return send(sock, buf, len, 0);
|
||||
}
|
||||
|
||||
static void recv_data_with_ws_api(int sock, size_t amount, u8_t *buf,
|
||||
size_t buf_len, const char *proto)
|
||||
{
|
||||
u32_t message_type;
|
||||
int remaining;
|
||||
int ret, read_pos;
|
||||
|
||||
remaining = amount - 1;
|
||||
read_pos = 0;
|
||||
|
||||
while (remaining > 0) {
|
||||
ret = websocket_recv_msg(sock, buf + read_pos,
|
||||
buf_len - read_pos,
|
||||
&message_type,
|
||||
NULL,
|
||||
K_NO_WAIT);
|
||||
if (ret <= 0) {
|
||||
if (ret == -EAGAIN) {
|
||||
k_sleep(K_MSEC(50));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_DBG("%s connection closed while "
|
||||
"waiting (%d/%d)", proto, ret, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
read_pos += ret;
|
||||
remaining -= ret;
|
||||
}
|
||||
|
||||
if (remaining <= 0 &&
|
||||
memcmp(lorem_ipsum, buf, amount - 1) != 0) {
|
||||
LOG_ERR("%s data recv failure %zd bytes", proto, amount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void recv_data_with_bsd_api(int sock, size_t amount, u8_t *buf,
|
||||
size_t buf_len, const char *proto)
|
||||
{
|
||||
int remaining = amount;
|
||||
int ret, read_pos;
|
||||
|
||||
remaining = amount - 1;
|
||||
read_pos = 0;
|
||||
|
||||
while (remaining >= 0) {
|
||||
ret = recv(sock, buf + read_pos, buf_len - read_pos, 0);
|
||||
if (ret <= 0) {
|
||||
if (errno == EAGAIN || errno == ETIMEDOUT) {
|
||||
k_sleep(K_MSEC(50));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_DBG("%s connection closed while "
|
||||
"waiting (%d/%d)", proto, ret, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
read_pos += ret;
|
||||
remaining -= ret;
|
||||
}
|
||||
|
||||
if (remaining <= 0 &&
|
||||
memcmp(lorem_ipsum, buf, amount - 1) != 0) {
|
||||
LOG_ERR("%s data recv failure %zd bytes", proto, amount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static bool send_and_wait_data(int sock, size_t amount, const char *proto,
|
||||
u8_t *buf, size_t buf_len)
|
||||
{
|
||||
static int count;
|
||||
int ret;
|
||||
|
||||
if (sock < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Terminate the sent data with \n so that we can use the
|
||||
* websocketd --port=9001 cat
|
||||
* command in server side.
|
||||
*/
|
||||
memcpy(buf, lorem_ipsum, amount);
|
||||
buf[amount] = '\n';
|
||||
|
||||
/* Send every 2nd message using dedicated websocket API and generic
|
||||
* BSD socket API. Real applications would not work like this but here
|
||||
* we want to test both APIs.
|
||||
*/
|
||||
if (count % 2) {
|
||||
ret = sendall_with_ws_api(sock, buf, amount);
|
||||
} else {
|
||||
ret = sendall_with_bsd_api(sock, buf, amount);
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s failed to send data using %s (%d)", proto,
|
||||
(count % 2) ? "ws API" : "socket API", ret);
|
||||
} else {
|
||||
LOG_DBG("%s connection closed", proto);
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
LOG_DBG("%s sent %d bytes", proto, ret);
|
||||
}
|
||||
|
||||
if (count % 2) {
|
||||
recv_data_with_ws_api(sock, amount, buf, buf_len, proto);
|
||||
} else {
|
||||
recv_data_with_bsd_api(sock, amount, buf, buf_len, proto);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
/* Just an example how to set extra headers */
|
||||
const char *extra_headers[] = {
|
||||
"Origin: http://foobar\r\n",
|
||||
NULL
|
||||
};
|
||||
int sock4 = -1, sock6 = -1;
|
||||
int websock4 = -1, websock6 = -1;
|
||||
s32_t timeout = K_SECONDS(3);
|
||||
struct sockaddr_in6 addr6;
|
||||
struct sockaddr_in addr4;
|
||||
size_t amount;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
||||
|
||||
if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
struct websocket_request req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.host = SERVER_ADDR4;
|
||||
req.url = "/";
|
||||
req.optional_headers = extra_headers;
|
||||
req.cb = connect_cb;
|
||||
req.tmp_buf = temp_recv_buf_ipv4;
|
||||
req.tmp_buf_len = sizeof(temp_recv_buf_ipv4);
|
||||
|
||||
websock4 = websocket_connect(sock4, &req, timeout, "IPv4");
|
||||
if (websock4 < 0) {
|
||||
LOG_ERR("Cannot connect to %s:%d", SERVER_ADDR4, PORT);
|
||||
close(sock4);
|
||||
}
|
||||
}
|
||||
|
||||
if (sock6 >= 0 && IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
struct websocket_request req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.host = SERVER_ADDR6;
|
||||
req.url = "/";
|
||||
req.optional_headers = extra_headers;
|
||||
req.cb = connect_cb;
|
||||
req.tmp_buf = temp_recv_buf_ipv6;
|
||||
req.tmp_buf_len = sizeof(temp_recv_buf_ipv6);
|
||||
|
||||
websock6 = websocket_connect(sock6, &req, timeout, "IPv6");
|
||||
if (websock6 < 0) {
|
||||
LOG_ERR("Cannot connect to [%s]:%d", SERVER_ADDR6,
|
||||
PORT);
|
||||
close(sock6);
|
||||
}
|
||||
}
|
||||
|
||||
if (websock4 < 0 && websock6 < 0) {
|
||||
LOG_ERR("No IPv4 or IPv6 connectivity");
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
||||
|
||||
LOG_INF("Websocket IPv4 %d IPv6 %d", websock4, websock6);
|
||||
|
||||
while (1) {
|
||||
amount = how_much_to_send(ipsum_len);
|
||||
|
||||
if (websock4 >= 0 &&
|
||||
!send_and_wait_data(websock4, amount, "IPv4",
|
||||
recv_buf_ipv4,
|
||||
sizeof(recv_buf_ipv4))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (websock6 >= 0 &&
|
||||
!send_and_wait_data(websock6, amount, "IPv6",
|
||||
recv_buf_ipv6,
|
||||
sizeof(recv_buf_ipv6))) {
|
||||
break;
|
||||
}
|
||||
|
||||
k_sleep(K_MSEC(250));
|
||||
}
|
||||
|
||||
if (websock4 >= 0) {
|
||||
close(websock4);
|
||||
}
|
||||
|
||||
if (websock6 >= 0) {
|
||||
close(websock6);
|
||||
}
|
||||
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue