I'm trying to build an HTTPS server application using zephyr http library, but the client connection is always being rejected. Can anyone help?
here is the logs
SEGGER J-Link V8.44 - Real time terminal output SEGGER J-Link V10.1, SN=600115917 Process: JLinkGDBServerCLExe [00:00:00.004,000] <inf> wifi_nrf_bus: SPIM spi@40013000: freq = 8 MHz [00:00:00.004,000] <inf> wifi_nrf_bus: SPIM spi@40013000: latency = 0 [00:00:00.272,000] <inf> wifi_nrf: Management buffer offload enabled *** Booting Zephyr OS build v4.1.0 *** [00:00:00.398,000] <inf> MAIN_CPP: Starting Zephyr HTTP Server [00:00:00.398,000] <inf> wifi_supplicant: wpa_supplicant initialized [00:00:01.398,000] <inf> WIFI_MANAGER: WiFi manager initialized successfully [00:00:01.398,000] <inf> MAIN_CPP: WiFi Manager initialized, starting in STA mode [00:00:01.398,000] <inf> WIFI_MANAGER: Starting WiFi in Station mode [00:00:01.398,000] <inf> WIFI_MANAGER: Connecting to SSID: Qwerty [00:00:03.401,000] <inf> WIFI_MANAGER: Connected to Qwerty [00:00:07.443,000] <inf> net_dhcpv4: Received: 192.168.19.80 [00:00:12.001,000] <dbg> net_http_server: http_server_init: Initialized HTTP Service 192.168.19.80:8080 [00:00:12.001,000] <dbg> net_http_server: http_server_start: Starting HTTP server [13] accept failed (-23) [00:00:19.023,000] <dbg> net_http_server: http_server_run: accept: -23 [00:00:19.032,000] <err> net_tcp: conn: 0x2004d2b8, new bytes 248 during TIME-WAIT state sending reset RTT:0>
#include <stdio.h>
#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>
#include <zephyr/net/http/service.h>
#include <zephyr/logging/log.h>
#include <zephyr/data/json.h>
#include <zephyr/net/socket.h>
#include <string.h>
#include <stdio.h>
#include "WifiManager.hpp"
#include <zephyr/net/tls_credentials.h>
#define APP_SEC_TAG 42
LOG_MODULE_REGISTER(MAIN_CPP, LOG_LEVEL_INF);
static const sec_tag_t tls_sec_tags[] = { APP_SEC_TAG };
static const uint8_t psk[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
static const char psk_id[] = "mydevice-01";
static int register_psk(void)
{
int ret;
ret = tls_credential_add(APP_SEC_TAG, TLS_CREDENTIAL_PSK,
psk, sizeof(psk));
if (ret < 0) { return ret; }
ret = tls_credential_add(APP_SEC_TAG, TLS_CREDENTIAL_PSK_ID,
psk_id, strlen(psk_id));
return ret;
}
static uint16_t http_service_port = 8080;
HTTPS_SERVICE_DEFINE(
api,
"192.168.19.80",
&http_service_port,
1,
1,
NULL,
NULL,
tls_sec_tags,
sizeof(tls_sec_tags)
);
struct device_status {
uint32_t uptime_ms;
int32_t temperature_c;
bool wifi_connected;
};
struct device_config {
int sample_rate_hz;
bool enabled;
char name[16];
};
static struct device_config g_cfg = {
.sample_rate_hz = 10, .enabled = true, .name = "U5+nRF7002"
};
static const struct json_obj_descr status_descr[] = {
JSON_OBJ_DESCR_PRIM(struct device_status, uptime_ms, JSON_TOK_NUMBER),
JSON_OBJ_DESCR_PRIM(struct device_status, temperature_c, JSON_TOK_NUMBER),
JSON_OBJ_DESCR_PRIM(struct device_status, wifi_connected,JSON_TOK_TRUE),
};
static const struct json_obj_descr config_descr[] = {
JSON_OBJ_DESCR_PRIM(struct device_config, sample_rate_hz, JSON_TOK_NUMBER),
JSON_OBJ_DESCR_PRIM(struct device_config, enabled, JSON_TOK_TRUE),
JSON_OBJ_DESCR_PRIM(struct device_config, name, JSON_TOK_STRING),
};
static const struct http_header JSON_HDRS[] = {
{ .name = "Content-Type", .value = "application/json" },
{ .name = "Cache-Control", .value = "no-store" },
};
#define MAX_REQ_BODY 512
static char req_buf[MAX_REQ_BODY];
static int status_cb(struct http_client_ctx *client,
enum http_data_status status,
const struct http_request_ctx *req,
struct http_response_ctx *rsp,
void *user_data)
{
ARG_UNUSED(client); ARG_UNUSED(req); ARG_UNUSED(user_data);
if (status != HTTP_SERVER_DATA_FINAL) {
return 0;
}
struct device_status st = {
.uptime_ms = (uint32_t)k_uptime_get(),
.temperature_c = 25,
.wifi_connected = true,
};
static char out[160];
int n = json_obj_encode_buf(status_descr, ARRAY_SIZE(status_descr), &st, out, sizeof(out));
if (n < 0) {
rsp->status = HTTP_500_INTERNAL_SERVER_ERROR;
rsp->body = reinterpret_cast<const uint8_t*>("{\"error\":\"encode\"}");
rsp->body_len = strlen(reinterpret_cast<const char*>(rsp->body));
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->final_chunk = true;
return 0;
}
rsp->status = HTTP_200_OK;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<uint8_t*>(out);
rsp->body_len = sizeof(out);
rsp->final_chunk = true;
return 0;
}
/* --------- /api/config (GET/PUT) --------- */
static int config_cb(struct http_client_ctx *client,
enum http_data_status status,
const struct http_request_ctx *req,
struct http_response_ctx *rsp,
void *user_data)
{
ARG_UNUSED(user_data);
const enum http_method m = client->method;
if (m == HTTP_GET) {
if (status != HTTP_SERVER_DATA_FINAL) {
return 0;
}
static char out[160];
int n = json_obj_encode_buf(config_descr, ARRAY_SIZE(config_descr), &g_cfg, out, sizeof(out));
if (n < 0) {
rsp->status = HTTP_500_INTERNAL_SERVER_ERROR;
rsp->body = reinterpret_cast<const uint8_t*>("{\"error\":\"encode\"}");
rsp->body_len = strlen(reinterpret_cast<const char*>(rsp->body));
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->final_chunk = true;
return 0;
}
rsp->status = HTTP_200_OK;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<uint8_t*>(out);
rsp->body_len = sizeof(out);
rsp->final_chunk = true;
return 0;
}
if (m == HTTP_PUT) {
static size_t acc = 0;
if (status == HTTP_SERVER_DATA_ABORTED) { acc = 0; return 0; }
/* accumulate request body */
if (req->data && req->data_len) {
size_t room = sizeof(req_buf) - acc;
size_t to_copy = MIN(room, req->data_len);
memcpy(req_buf + acc, req->data, to_copy);
acc += to_copy;
}
if (status != HTTP_SERVER_DATA_FINAL) {
return 0; /* wait for the final chunk */
}
/* Parse JSON in-place (json_obj_parse modifies buffer) */
struct device_config cfg_tmp = {0};
int ret = json_obj_parse(req_buf, acc, config_descr, ARRAY_SIZE(config_descr), &cfg_tmp);
acc = 0;
if (ret < 0) {
rsp->status = HTTP_400_BAD_REQUEST;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<const uint8_t*>("{\"error\":\"bad json\"}");
rsp->body_len = strlen(reinterpret_cast<const char*>(rsp->body));
rsp->final_chunk = true;
return 0;
}
/* Persist: copy string field; ints/bools already copied */
/* cfg_tmp.name points inside req_buf -> copy to g_cfg.name */
if (cfg_tmp.name) {
snprintk(g_cfg.name, sizeof(g_cfg.name), "%s", cfg_tmp.name);
}
g_cfg.sample_rate_hz = cfg_tmp.sample_rate_hz;
g_cfg.enabled = cfg_tmp.enabled;
rsp->status = HTTP_204_NO_CONTENT; /* No Content */
rsp->headers = JSON_HDRS;
rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->final_chunk = true;
return 0;
}
/* Method not allowed for this resource */
rsp->status = HTTP_405_METHOD_NOT_ALLOWED;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<const uint8_t*>("{\"error\":\"method not allowed\"}");
rsp->body_len = strlen(reinterpret_cast<const char*>(rsp->body));
rsp->final_chunk = true;
return 0;
}
/* --------- /api/command (POST) --------- */
struct cmd_req { const char *action; };
static const struct json_obj_descr cmd_req_descr[] = {
JSON_OBJ_DESCR_PRIM(struct cmd_req, action, JSON_TOK_STRING),
};
static int command_cb(struct http_client_ctx *client,
enum http_data_status status,
const struct http_request_ctx *req,
struct http_response_ctx *rsp,
void *user_data)
{
ARG_UNUSED(client); ARG_UNUSED(user_data);
static size_t acc = 0;
if (status == HTTP_SERVER_DATA_ABORTED) { acc = 0; return 0; }
/* accumulate body */
if (req->data && req->data_len) {
size_t room = sizeof(req_buf) - acc;
size_t to_copy = MIN(room, req->data_len);
memcpy(req_buf + acc, req->data, to_copy);
acc += to_copy;
}
if (status != HTTP_SERVER_DATA_FINAL) {
return 0;
}
/* parse and act */
struct cmd_req cmd = {0};
int ret = json_obj_parse(req_buf, acc, cmd_req_descr, ARRAY_SIZE(cmd_req_descr), &cmd);
acc = 0;
if (ret < 0 || cmd.action == NULL) {
rsp->status = HTTP_400_BAD_REQUEST;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<const uint8_t*>("{\"error\":\"bad json\"}");
rsp->body_len = strlen(reinterpret_cast<const char*>(rsp->body));
rsp->final_chunk = true;
return 0;
}
/* Example actions */
bool ok = true;
if (!strcmp(cmd.action, "reboot")) {
/* sys_reboot(SYS_REBOOT_WARM); // if you want */
ok = true;
} else if (!strcmp(cmd.action, "factory_reset")) {
/* TODO: wipe config */
ok = true;
} else {
ok = false;
}
static char out[64];
int n = snprintk(out, sizeof(out), "{\"ok\":%s}", ok ? "true" : "false");
rsp->status = ok ? HTTP_200_OK : HTTP_422_UNPROCESSABLE_ENTITY;
rsp->headers = JSON_HDRS; rsp->header_count = ARRAY_SIZE(JSON_HDRS);
rsp->body = reinterpret_cast<uint8_t*>(out);
rsp->body_len = sizeof(out);
rsp->final_chunk = true;
return 0;
}
static struct http_resource_detail_dynamic status_detail = {
.common = {
.bitmask_of_supported_http_methods = BIT(HTTP_GET),
.type = HTTP_RESOURCE_TYPE_DYNAMIC,
},
.cb = status_cb,
};
HTTP_RESOURCE_DEFINE(api_status, api, "/api/status", &status_detail);
static struct http_resource_detail_dynamic config_detail = {
.common = {
.bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_PUT),
.type = HTTP_RESOURCE_TYPE_DYNAMIC,
},
.cb = config_cb,
};
HTTP_RESOURCE_DEFINE(api_config, api, "/api/config", &config_detail);
static struct http_resource_detail_dynamic command_detail = {
.common = {
.bitmask_of_supported_http_methods = BIT(HTTP_POST),
.type = HTTP_RESOURCE_TYPE_DYNAMIC,
},
.cb = command_cb,
};
HTTP_RESOURCE_DEFINE(api_command, api, "/api/command", &command_detail);
int main(void)
{
LOG_INF("Starting Zephyr HTTP Server");
WiFiManager wifitask;
NetworkSetupParams::currentNetParams.station.StaSsid = "Qwerty";
NetworkSetupParams::currentNetParams.station.Psk = "12345678";
wifi_manager_state wifiManagerResult = wifitask.initialize();
if (wifiManagerResult == wifi_manager_state::success) {
LOG_INF("WiFi Manager initialized, starting in STA mode");
wifitask.start(wifi_mode::sta);
k_sleep(K_SECONDS(10));
} else {
LOG_ERR("WiFi Manager initialization failed going to sleep....\n");
}
if (register_psk() < 0) {
LOG_ERR("Failed to register PSK credentials");
}
http_server_start();
while (1) {
k_sleep(K_SECONDS(1));
}
return 0;
}CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_REQUIRES_FULL_LIBCPP=y CONFIG_NETWORKING=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=n CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_SOCKOPT_TLS=y # WiFi Configuration CONFIG_WIFI=y CONFIG_WIFI_NRF70=y CONFIG_NET_L2_WIFI_MGMT=y CONFIG_NET_DHCPV4=y # TLS Configuration CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y CONFIG_MBEDTLS_TLS_VERSION_1_2=y CONFIG_HTTP_SERVER=y CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y CONFIG_HTTP_SERVER_SAMPLE_PEER_VERIFICATION_REQUIRE=n # Logging CONFIG_LOG=y CONFIG_NET_LOG=y CONFIG_LOG_DEFAULT_LEVEL=3 # Memory CONFIG_MAIN_STACK_SIZE=8192 CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_NET_IF_MAX_IPV6_COUNT=2 CONFIG_NET_IF_MAX_IPV4_COUNT=2 CONFIG_NET_DEFAULT_IF_WIFI=y CONFIG_NET_DHCPV4_SERVER=n CONFIG_NRF70_AP_MODE=n CONFIG_WIFI_NM_WPA_SUPPLICANT_AP=n CONFIG_WIFI_NM_WPA_SUPPLICANT_THREAD_STACK_SIZE=20480 CONFIG_WIFI_SCAN_DWELL_TIME_ACTIVE=50 CONFIG_WIFI_SCAN_DWELL_TIME_PASSIVE=130 CONFIG_UART_CONSOLE=n CONFIG_RTT_CONSOLE=y CONFIG_USE_SEGGER_RTT=y CONFIG_JSON_LIBRARY=y CONFIG_HTTP_SERVER_SAMPLE_PEER_VERIFICATION_REQUIRE=n CONFIG_NET_CONNECTION_MANAGER=y CONFIG_WIFI_CREDENTIALS=y CONFIG_WIFI_CREDENTIALS_STATIC=y CONFIG_WIFI_CREDENTIALS_STATIC_SSID="Qwerty" CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="12345678" CONFIG_POSIX_API=y CONFIG_EVENTFD=y CONFIG_ZVFS_OPEN_MAX=16 CONFIG_ZVFS_POLL_MAX=16 CONFIG_ZVFS_EVENTFD_MAX=2 CONFIG_HTTP_SERVER_STACK_SIZE=16384 CONFIG_NET_HTTP_SERVER_LOG_LEVEL_DBG=y CONFIG_NET_MAX_CONTEXTS=24