Merge "Merge net branch into master"
This commit is contained in:
commit
8bde07dfae
@ -76,8 +76,7 @@ The frdm_k64f board configuration supports the following hardware features:
|
||||
+-----------+------------+-------------------------------------+
|
||||
| SPI | on-chip | spi |
|
||||
+-----------+------------+-------------------------------------+
|
||||
| ETHERNET | on-chip | ethernet (work in progress, known |
|
||||
| | | issues exist, see below) |
|
||||
| ETHERNET | on-chip | ethernet |
|
||||
+-----------+------------+-------------------------------------+
|
||||
| UART | on-chip | serial port-polling; |
|
||||
| | | serial port-interrupt |
|
||||
@ -224,13 +223,6 @@ the following message:
|
||||
|
||||
Hello World! arm
|
||||
|
||||
Work in progress and known issues
|
||||
*********************************
|
||||
|
||||
Ethernet PHY is currently initialized only at the application startup.
|
||||
For successful initialization, a network cable must be connected between
|
||||
the board and a host/router. If a cable is not connected when the board
|
||||
is powered on or reset, the startup will be aborted with an error message.
|
||||
|
||||
.. _FRDM-K64F Website:
|
||||
http://www.nxp.com/products/software-and-tools/hardware-development-tools/freedom-development-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F
|
||||
|
||||
@ -15,6 +15,13 @@ menuconfig ETH_MCUX
|
||||
configuration change.
|
||||
|
||||
if ETH_MCUX
|
||||
config ETH_MCUX_PHY_TICK_MS
|
||||
int "PHY poll period (ms)"
|
||||
default 1000
|
||||
range 100 30000
|
||||
help
|
||||
Set the PHY status polling period.
|
||||
|
||||
config ETH_MCUX_RX_BUFFERS
|
||||
int "Number of MCUX RX buffers"
|
||||
depends on ETH_MCUX
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
/* MCUX Ethernet Driver
|
||||
*
|
||||
* Copyright (c) 2016 ARM Ltd
|
||||
* Copyright (c) 2016-2017 ARM Ltd
|
||||
* Copyright (c) 2016 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* The driver performs one shot PHY setup. There is no support for
|
||||
* PHY disconnect, reconnect or configuration change. The PHY setup,
|
||||
* implemented via MCUX contains polled code that can block the
|
||||
* initialization thread for a few seconds.
|
||||
/* Driver Limitations:
|
||||
*
|
||||
* There is no statistics collection for either normal operation or
|
||||
* error behaviour.
|
||||
@ -30,11 +27,27 @@
|
||||
#include "fsl_phy.h"
|
||||
#include "fsl_port.h"
|
||||
|
||||
enum eth_mcux_phy_state {
|
||||
eth_mcux_phy_state_initial,
|
||||
eth_mcux_phy_state_reset,
|
||||
eth_mcux_phy_state_autoneg,
|
||||
eth_mcux_phy_state_restart,
|
||||
eth_mcux_phy_state_read_status,
|
||||
eth_mcux_phy_state_read_duplex,
|
||||
eth_mcux_phy_state_wait
|
||||
};
|
||||
|
||||
struct eth_context {
|
||||
struct net_if *iface;
|
||||
enet_handle_t enet_handle;
|
||||
struct k_sem tx_buf_sem;
|
||||
enum eth_mcux_phy_state phy_state;
|
||||
bool link_up;
|
||||
phy_duplex_t phy_duplex;
|
||||
phy_speed_t phy_speed;
|
||||
uint8_t mac_addr[6];
|
||||
struct k_work phy_work;
|
||||
struct k_delayed_work delayed_phy_work;
|
||||
/* TODO: FIXME. This Ethernet frame sized buffer is used for
|
||||
* interfacing with MCUX. How it works is that hardware uses
|
||||
* DMA scatter buffers to receive a frame, and then public
|
||||
@ -70,6 +83,137 @@ rx_buffer[CONFIG_ETH_MCUX_RX_BUFFERS][ETH_MCUX_BUFFER_SIZE];
|
||||
static uint8_t __aligned(ENET_BUFF_ALIGNMENT)
|
||||
tx_buffer[CONFIG_ETH_MCUX_TX_BUFFERS][ETH_MCUX_BUFFER_SIZE];
|
||||
|
||||
static void eth_mcux_decode_duplex_and_speed(uint32_t status,
|
||||
phy_duplex_t *p_phy_duplex,
|
||||
phy_speed_t *p_phy_speed)
|
||||
{
|
||||
switch (status & PHY_CTL1_SPEEDUPLX_MASK) {
|
||||
case PHY_CTL1_10FULLDUPLEX_MASK:
|
||||
*p_phy_duplex = kPHY_FullDuplex;
|
||||
*p_phy_speed = kPHY_Speed10M;
|
||||
break;
|
||||
case PHY_CTL1_100FULLDUPLEX_MASK:
|
||||
*p_phy_duplex = kPHY_FullDuplex;
|
||||
*p_phy_speed = kPHY_Speed100M;
|
||||
break;
|
||||
case PHY_CTL1_100HALFDUPLEX_MASK:
|
||||
*p_phy_duplex = kPHY_HalfDuplex;
|
||||
*p_phy_speed = kPHY_Speed100M;
|
||||
break;
|
||||
case PHY_CTL1_10HALFDUPLEX_MASK:
|
||||
*p_phy_duplex = kPHY_HalfDuplex;
|
||||
*p_phy_speed = kPHY_Speed10M;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void eth_mcux_phy_event(struct eth_context *context)
|
||||
{
|
||||
uint32_t status;
|
||||
bool link_up;
|
||||
phy_duplex_t phy_duplex = kPHY_FullDuplex;
|
||||
phy_speed_t phy_speed = kPHY_Speed100M;
|
||||
const uint32_t phy_addr = 0;
|
||||
|
||||
SYS_LOG_DBG("phy_state=%d", context->phy_state);
|
||||
|
||||
switch (context->phy_state) {
|
||||
case eth_mcux_phy_state_initial:
|
||||
/* Reset the PHY. */
|
||||
ENET_StartSMIWrite(ENET, phy_addr, PHY_BASICCONTROL_REG,
|
||||
kENET_MiiWriteValidFrame,
|
||||
PHY_BCTL_RESET_MASK);
|
||||
context->phy_state = eth_mcux_phy_state_reset;
|
||||
break;
|
||||
case eth_mcux_phy_state_reset:
|
||||
/* Setup PHY autonegotiation. */
|
||||
ENET_StartSMIWrite(ENET, phy_addr, PHY_AUTONEG_ADVERTISE_REG,
|
||||
kENET_MiiWriteValidFrame,
|
||||
(PHY_100BASETX_FULLDUPLEX_MASK |
|
||||
PHY_100BASETX_HALFDUPLEX_MASK |
|
||||
PHY_10BASETX_FULLDUPLEX_MASK |
|
||||
PHY_10BASETX_HALFDUPLEX_MASK | 0x1U));
|
||||
context->phy_state = eth_mcux_phy_state_autoneg;
|
||||
break;
|
||||
case eth_mcux_phy_state_autoneg:
|
||||
/* Setup PHY autonegotiation. */
|
||||
ENET_StartSMIWrite(ENET, phy_addr, PHY_BASICCONTROL_REG,
|
||||
kENET_MiiWriteValidFrame,
|
||||
(PHY_BCTL_AUTONEG_MASK |
|
||||
PHY_BCTL_RESTART_AUTONEG_MASK));
|
||||
context->phy_state = eth_mcux_phy_state_restart;
|
||||
break;
|
||||
case eth_mcux_phy_state_wait:
|
||||
case eth_mcux_phy_state_restart:
|
||||
/* Start reading the PHY basic status. */
|
||||
ENET_StartSMIRead(ENET, phy_addr, PHY_BASICSTATUS_REG,
|
||||
kENET_MiiReadValidFrame);
|
||||
context->phy_state = eth_mcux_phy_state_read_status;
|
||||
break;
|
||||
case eth_mcux_phy_state_read_status:
|
||||
/* PHY Basic status is available. */
|
||||
status = ENET_ReadSMIData(ENET);
|
||||
link_up = status & PHY_BSTATUS_LINKSTATUS_MASK;
|
||||
if (link_up && !context->link_up) {
|
||||
/* Start reading the PHY control register. */
|
||||
ENET_StartSMIRead(ENET, phy_addr, PHY_CONTROL1_REG,
|
||||
kENET_MiiReadValidFrame);
|
||||
context->link_up = link_up;
|
||||
context->phy_state = eth_mcux_phy_state_read_duplex;
|
||||
} else if (!link_up && context->link_up) {
|
||||
SYS_LOG_INF("Link down");
|
||||
context->link_up = link_up;
|
||||
k_delayed_work_submit(&context->delayed_phy_work,
|
||||
CONFIG_ETH_MCUX_PHY_TICK_MS);
|
||||
context->phy_state = eth_mcux_phy_state_wait;
|
||||
} else {
|
||||
k_delayed_work_submit(&context->delayed_phy_work,
|
||||
CONFIG_ETH_MCUX_PHY_TICK_MS);
|
||||
context->phy_state = eth_mcux_phy_state_wait;
|
||||
}
|
||||
|
||||
break;
|
||||
case eth_mcux_phy_state_read_duplex:
|
||||
/* PHY control register is available. */
|
||||
status = ENET_ReadSMIData(ENET);
|
||||
eth_mcux_decode_duplex_and_speed(status,
|
||||
&phy_duplex,
|
||||
&phy_speed);
|
||||
if (phy_speed != context->phy_speed ||
|
||||
phy_duplex != context->phy_duplex) {
|
||||
context->phy_speed = phy_speed;
|
||||
context->phy_duplex = phy_duplex;
|
||||
ENET_SetMII(ENET,
|
||||
(enet_mii_speed_t) phy_speed,
|
||||
(enet_mii_duplex_t) phy_duplex);
|
||||
}
|
||||
|
||||
SYS_LOG_INF("Enabled %sM %s-duplex mode.",
|
||||
(phy_speed ? "100" : "10"),
|
||||
(phy_duplex ? "full" : "half"));
|
||||
k_delayed_work_submit(&context->delayed_phy_work,
|
||||
CONFIG_ETH_MCUX_PHY_TICK_MS);
|
||||
context->phy_state = eth_mcux_phy_state_wait;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void eth_mcux_phy_work(struct k_work *item)
|
||||
{
|
||||
struct eth_context *context =
|
||||
CONTAINER_OF(item, struct eth_context, phy_work);
|
||||
|
||||
eth_mcux_phy_event(context);
|
||||
}
|
||||
|
||||
static void eth_mcux_delayed_phy_work(struct k_work *item)
|
||||
{
|
||||
struct eth_context *context =
|
||||
CONTAINER_OF(item, struct eth_context, delayed_phy_work);
|
||||
|
||||
eth_mcux_phy_event(context);
|
||||
}
|
||||
|
||||
static int eth_tx(struct net_if *iface, struct net_buf *buf)
|
||||
{
|
||||
struct eth_context *context = iface->dev->driver_data;
|
||||
@ -265,9 +409,6 @@ static int eth_0_init(struct device *dev)
|
||||
struct eth_context *context = dev->driver_data;
|
||||
enet_config_t enet_config;
|
||||
uint32_t sys_clock;
|
||||
const uint32_t phy_addr = 0x0;
|
||||
bool link;
|
||||
status_t status;
|
||||
enet_buffer_config_t buffer_config = {
|
||||
.rxBdNumber = CONFIG_ETH_MCUX_RX_BUFFERS,
|
||||
.txBdNumber = CONFIG_ETH_MCUX_TX_BUFFERS,
|
||||
@ -281,34 +422,24 @@ static int eth_0_init(struct device *dev)
|
||||
|
||||
k_sem_init(&context->tx_buf_sem,
|
||||
CONFIG_ETH_MCUX_TX_BUFFERS, CONFIG_ETH_MCUX_TX_BUFFERS);
|
||||
k_work_init(&context->phy_work, eth_mcux_phy_work);
|
||||
k_delayed_work_init(&context->delayed_phy_work,
|
||||
eth_mcux_delayed_phy_work);
|
||||
|
||||
sys_clock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
|
||||
|
||||
ENET_GetDefaultConfig(&enet_config);
|
||||
enet_config.interrupt |= kENET_RxFrameInterrupt;
|
||||
enet_config.interrupt |= kENET_TxFrameInterrupt;
|
||||
|
||||
status = PHY_Init(ENET, phy_addr, sys_clock);
|
||||
if (status) {
|
||||
SYS_LOG_ERR("PHY_Init() failed: %d", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PHY_GetLinkStatus(ENET, phy_addr, &link);
|
||||
if (link) {
|
||||
phy_speed_t phy_speed;
|
||||
phy_duplex_t phy_duplex;
|
||||
|
||||
PHY_GetLinkSpeedDuplex(ENET, phy_addr, &phy_speed, &phy_duplex);
|
||||
enet_config.miiSpeed = (enet_mii_speed_t) phy_speed;
|
||||
enet_config.miiDuplex = (enet_mii_duplex_t) phy_duplex;
|
||||
|
||||
SYS_LOG_INF("Enabled %dM %s-duplex mode.",
|
||||
(phy_speed ? 100 : 10),
|
||||
(phy_duplex ? "full" : "half"));
|
||||
} else {
|
||||
SYS_LOG_INF("Link down.");
|
||||
}
|
||||
enet_config.interrupt |= kENET_MiiInterrupt;
|
||||
/* FIXME: Workaround for lack of driver API support for multicast
|
||||
* management. So, instead we want to receive all multicast
|
||||
* frames "by default", or otherwise basic IPv6 features, like
|
||||
* address resolution, don't work. On Kinetis Ethernet controller,
|
||||
* that translates to enabling promiscuous mode. The real
|
||||
* fix depends on https://jira.zephyrproject.org/browse/ZEP-1673.
|
||||
*/
|
||||
enet_config.macSpecialConfig |= kENET_ControlPromiscuousEnable;
|
||||
|
||||
#if defined(CONFIG_ETH_MCUX_0_RANDOM_MAC)
|
||||
generate_mac(context->mac_addr);
|
||||
@ -321,6 +452,8 @@ static int eth_0_init(struct device *dev)
|
||||
context->mac_addr,
|
||||
sys_clock);
|
||||
|
||||
ENET_SetSMI(ENET, sys_clock, false);
|
||||
|
||||
SYS_LOG_DBG("MAC %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
context->mac_addr[0], context->mac_addr[1],
|
||||
context->mac_addr[2], context->mac_addr[3],
|
||||
@ -329,6 +462,9 @@ static int eth_0_init(struct device *dev)
|
||||
ENET_SetCallback(&context->enet_handle, eth_callback, dev);
|
||||
eth_0_config_func();
|
||||
ENET_ActiveRead(ENET);
|
||||
|
||||
k_work_submit(&context->phy_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -367,11 +503,17 @@ static void eth_mcux_error_isr(void *p)
|
||||
{
|
||||
struct device *dev = p;
|
||||
struct eth_context *context = dev->driver_data;
|
||||
uint32_t pending = ENET_GetInterruptStatus(ENET);
|
||||
|
||||
ENET_ErrorIRQHandler(ENET, &context->enet_handle);
|
||||
if (pending & ENET_EIR_MII_MASK) {
|
||||
k_work_submit(&context->phy_work);
|
||||
ENET_ClearInterruptStatus(ENET, kENET_MiiInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct eth_context eth_0_context = {
|
||||
.phy_duplex = kPHY_FullDuplex,
|
||||
.phy_speed = kPHY_Speed100M,
|
||||
.mac_addr = {
|
||||
/* Freescale's OUI */
|
||||
0x00,
|
||||
|
||||
91
ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h
Normal file
91
ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Minimal configuration for TLS 1.1 (RFC 4346)
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Minimal configuration for TLS 1.1 (RFC 4346), implementing only the
|
||||
* required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
*
|
||||
* See README.txt for usage instructions.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
|
||||
#define MBEDTLS_PLATFORM_EXIT_ALT
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||
#define MBEDTLS_PLATFORM_PRINTF_ALT
|
||||
|
||||
#if !defined(CONFIG_ARM)
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_TEST)
|
||||
#define MBEDTLS_SELF_TEST
|
||||
#define MBEDTLS_DEBUG_C
|
||||
#else
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#endif
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
|
||||
/* For test certificates */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
|
||||
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
||||
@ -28,7 +28,6 @@
|
||||
enum net_dhcpv4_state {
|
||||
NET_DHCPV4_INIT,
|
||||
NET_DHCPV4_DISCOVER,
|
||||
NET_DHCPV4_OFFER,
|
||||
NET_DHCPV4_REQUEST,
|
||||
NET_DHCPV4_RENEWAL,
|
||||
NET_DHCPV4_ACK,
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief mqtt_app MQTT application type
|
||||
* MQTT application type
|
||||
*/
|
||||
enum mqtt_app {
|
||||
/** Publisher and Subscriber application */
|
||||
@ -31,9 +31,9 @@ enum mqtt_app {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief struct mqtt_ctx MQTT context structure
|
||||
* @details
|
||||
* Context structure for the MQTT high-level API with support for QoS.
|
||||
* MQTT context structure
|
||||
*
|
||||
* @details Context structure for the MQTT high-level API with support for QoS.
|
||||
*
|
||||
* This API is designed for asynchronous operation, so callbacks are
|
||||
* executed when some events must be addressed outside the MQTT routines.
|
||||
@ -74,84 +74,66 @@ struct mqtt_ctx {
|
||||
|
||||
/** Callback executed when a #MQTT_APP_PUBLISHER application receives
|
||||
* a MQTT PUBxxxx msg.
|
||||
* If type is MQTT_PUBACK, MQTT_PUBCOMP or MQTT_PUBREC, this callback
|
||||
* must return 0 if pkt_id matches the packet id of a previously
|
||||
* received MQTT_PUBxxx message. If this callback returns 0, the caller
|
||||
* will continue.
|
||||
* Any other value will stop the QoS handshake and the caller will
|
||||
* return -EINVAL. The application must discard all the messages
|
||||
* already processed.
|
||||
*
|
||||
* <b>Note: this callback must be not NULL</b>
|
||||
*
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] pkt_id Packet Identifier for the input MQTT msg
|
||||
* @param [in] type Packet type
|
||||
* @return If this callback returns 0, the caller will
|
||||
* continue.
|
||||
*
|
||||
* @return If type is MQTT_PUBACK, MQTT_PUBCOMP or
|
||||
* MQTT_PUBREC, this callback must return 0 if
|
||||
* pkt_id matches the packet id of a previously
|
||||
* received MQTT_PUBxxx message.
|
||||
*
|
||||
* @return <b>Note: the application must discard all the
|
||||
* messages already processed</b>
|
||||
*
|
||||
* @return Any other value will stop the QoS handshake
|
||||
* and the caller will return -EINVAL
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] pkt_id Packet Identifier for the input MQTT msg
|
||||
* @param [in] type Packet type
|
||||
*/
|
||||
int (*publish_tx)(struct mqtt_ctx *ctx, uint16_t pkt_id,
|
||||
enum mqtt_packet type);
|
||||
|
||||
/** Callback executed when a MQTT_APP_SUBSCRIBER,
|
||||
* MQTT_APP_PUBLISHER_SUBSCRIBER or MQTT_APP_SERVER application receive
|
||||
* a MQTT PUBxxxx msg.
|
||||
* MQTT_APP_PUBLISHER_SUBSCRIBER or MQTT_APP_SERVER applications receive
|
||||
* a MQTT PUBxxxx msg. If this callback returns 0, the caller will
|
||||
* continue. If type is MQTT_PUBREL this callback must return 0 if
|
||||
* pkt_id matches the packet id of a previously received MQTT_PUBxxx
|
||||
* message. Any other value will stop the QoS handshake and the caller
|
||||
* will return -EINVAL
|
||||
*
|
||||
* <b>Note: this callback must be not NULL</b>
|
||||
*
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] msg Publish message, this parameter is only used
|
||||
* when the type is MQTT_PUBLISH
|
||||
* @param [in] pkt_id Packet Identifier for the input msg
|
||||
* @param [in] type Packet type
|
||||
* @return If this callback returns 0, the caller will
|
||||
* continue.
|
||||
*
|
||||
* @return If type is MQTT_PUBREL this callback must return
|
||||
* 0 if pkt_id matches the packet id of a
|
||||
* previously received MQTT_PUBxxx message.
|
||||
*
|
||||
* @return <b>Note: the application must discard all the
|
||||
* messages already processed</b>
|
||||
*
|
||||
* @return Any other value will stop the QoS handshake
|
||||
* and the caller will return -EINVAL
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] msg Publish message, this parameter is only used
|
||||
* when the type is MQTT_PUBLISH
|
||||
* @param [in] pkt_id Packet Identifier for the input msg
|
||||
* @param [in] type Packet type
|
||||
*/
|
||||
int (*publish_rx)(struct mqtt_ctx *ctx, struct mqtt_publish_msg *msg,
|
||||
uint16_t pkt_id, enum mqtt_packet type);
|
||||
|
||||
/** Callback executed when a MQTT_APP_SUBSCRIBER or
|
||||
* MQTT_APP_PUBLISHER_SUBSCRIBER receives the MQTT SUBACK message
|
||||
* If this callback returns 0, the caller will continue. Any other
|
||||
* value will make the caller return -EINVAL.
|
||||
*
|
||||
* <b>Note: this callback must be not NULL</b>
|
||||
*
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg
|
||||
* @param [in] items Number of elements in the qos array
|
||||
* @param [in] qos Array of QoS values
|
||||
* @return If this callback returns 0, the caller will
|
||||
* continue
|
||||
* @return Any other value will make the caller return
|
||||
* -EINVAL
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg
|
||||
* @param [in] items Number of elements in the qos array
|
||||
* @param [in] qos Array of QoS values
|
||||
*/
|
||||
int (*subscribe)(struct mqtt_ctx *ctx, uint16_t pkt_id,
|
||||
uint8_t items, enum mqtt_qos qos[]);
|
||||
|
||||
/** Callback executed when a MQTT_APP_SUBSCRIBER or
|
||||
* MQTT_APP_PUBLISHER_SUBSCRIBER receives the MQTT UNSUBACK message
|
||||
* If this callback returns 0, the caller will continue. Any other value
|
||||
* will make the caller return -EINVAL
|
||||
*
|
||||
* <b>Note: this callback must be not NULL</b>
|
||||
*
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg
|
||||
* @return If this callback returns 0, the caller will
|
||||
* continue
|
||||
* @return Any other value will make the caller return
|
||||
* -EINVAL
|
||||
*/
|
||||
int (*unsubscribe)(struct mqtt_ctx *ctx, uint16_t pkt_id);
|
||||
|
||||
@ -182,219 +164,253 @@ struct mqtt_ctx {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief mqtt_init Initializes the MQTT context structure
|
||||
* @param ctx MQTT context structure
|
||||
* @param app_type See enum mqtt_app
|
||||
* @return 0, always.
|
||||
* Initializes the MQTT context structure
|
||||
*
|
||||
* @param ctx MQTT context structure
|
||||
* @param app_type See enum mqtt_app
|
||||
* @retval 0, always.
|
||||
*/
|
||||
int mqtt_init(struct mqtt_ctx *ctx, enum mqtt_app app_type);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_connect Sends the MQTT CONNECT message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] msg MQTT CONNECT msg
|
||||
* @return 0 on success
|
||||
* @return -EIO on network error
|
||||
* @return -ENOMEM if no data/tx buffer is available
|
||||
* @return -EINVAL if invalid data was passed to this
|
||||
* routine
|
||||
* Sends the MQTT CONNECT message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] msg MQTT CONNECT msg
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EIO
|
||||
* @retval -ENOMEM
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_tx_connect(struct mqtt_ctx *ctx, struct mqtt_connect_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_disconnect Send the MQTT DISCONNECT message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @return 0 on success
|
||||
* @return -EIO on network error
|
||||
* @return -ENOMEM if no data/tx buffer is available
|
||||
* @return -EINVAL if invalid data was passed to this
|
||||
* routine
|
||||
* Send the MQTT DISCONNECT message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EIO
|
||||
* @retval -ENOMEM
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_tx_disconnect(struct mqtt_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_puback Sends the MQTT PUBACK message with the given
|
||||
* packet id
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PUBACK message with the given packet id
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_puback(struct mqtt_ctx *ctx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_pubcomp Sends the MQTT PUBCOMP message with the given
|
||||
* packet id
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PUBCOMP message with the given packet id
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_pubcomp(struct mqtt_ctx *ctx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_pubrec Sends the MQTT PUBREC message with the given
|
||||
* packet id
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PUBREC message with the given packet id
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_pubrec(struct mqtt_ctx *ctx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_pubrel Sends the MQTT PUBREL message with the given
|
||||
* packet id
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PUBREL message with the given packet id
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] id MQTT Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_pubrel(struct mqtt_ctx *ctx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_publish Sends the MQTT PUBLISH message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] msg MQTT PUBLISH msg
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PUBLISH message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] msg MQTT PUBLISH msg
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_publish(struct mqtt_ctx *ctx, struct mqtt_publish_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_pingreq Sends the MQTT PINGREQ message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT PINGREQ message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_pingreq(struct mqtt_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_subscribe Sends the MQTT SUBSCRIBE message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] pkt_id Packet identifier for the MQTT SUBSCRIBE msg
|
||||
* @param [in] items Number of elements in 'topics' and 'qos' arrays
|
||||
* @param [in] topics Array of 'items' elements containing C strings.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
* @param [in] qos Array of 'items' elements containing MQTT QoS
|
||||
* values: MQTT_QoS0, MQTT_QoS1, MQTT_QoS2. For
|
||||
* example for the 'topics' array above the
|
||||
* following QoS may be used:
|
||||
* {MQTT_QoS0, MQTT_QoS2, MQTT_QoS1}, indicating
|
||||
* that the subscription to 'lights' must be done
|
||||
* with MQTT_QoS2
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Sends the MQTT SUBSCRIBE message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] pkt_id Packet identifier for the MQTT SUBSCRIBE msg
|
||||
* @param [in] items Number of elements in 'topics' and 'qos' arrays
|
||||
* @param [in] topics Array of 'items' elements containing C strings.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
* @param [in] qos Array of 'items' elements containing MQTT QoS values:
|
||||
* MQTT_QoS0, MQTT_QoS1, MQTT_QoS2. For example for the 'topics'
|
||||
* array above the following QoS may be used: {MQTT_QoS0,
|
||||
* MQTT_QoS2, MQTT_QoS1}, indicating that the subscription to
|
||||
* 'lights' must be done with MQTT_QoS2
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_subscribe(struct mqtt_ctx *ctx, uint16_t pkt_id, uint8_t items,
|
||||
const char *topics[], const enum mqtt_qos qos[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_unsubscribe Sends the MQTT UNSUBSCRIBE message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] pkt_id Packet identifier for the MQTT UNSUBSCRIBE msg
|
||||
* @param [in] items Number of elements in the 'topics' array
|
||||
* @param [in] topics Array of 'items' elements containing C strings
|
||||
* @return
|
||||
* Sends the MQTT UNSUBSCRIBE message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] pkt_id Packet identifier for the MQTT UNSUBSCRIBE msg
|
||||
* @param [in] items Number of elements in the 'topics' array
|
||||
* @param [in] topics Array of 'items' elements containing C strings
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
* @retval -EIO
|
||||
*/
|
||||
int mqtt_tx_unsubscribe(struct mqtt_ctx *ctx, uint16_t pkt_id, uint8_t items,
|
||||
const char *topics[]);
|
||||
|
||||
|
||||
/**
|
||||
* Parses and validates the MQTT CONNACK msg
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @param [in] clean_session MQTT clean session parameter
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_connack(struct mqtt_ctx *ctx, struct net_buf *rx,
|
||||
int clean_session);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_puback Parses and validates the MQTT PUBACK message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses and validates the MQTT PUBACK message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_puback(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_pubcomp Parses and validates the MQTT PUBCOMP message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses and validates the MQTT PUBCOMP message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_pubcomp(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_pubrec Parses and validates the MQTT PUBREC message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses and validates the MQTT PUBREC message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_pubrec(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_pubrel Parses and validates the MQTT PUBREL message
|
||||
* @details rx is an RX buffer from the IP stack
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses and validates the MQTT PUBREL message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_pubrel(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_pingresp Parses the MQTT PINGRESP message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses the MQTT PINGRESP message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_pingresp(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_suback Parses the MQTT SUBACK message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses the MQTT SUBACK message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_suback(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_unsuback Parses the MQTT UNSUBACK message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses the MQTT UNSUBACK message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_rx_unsuback(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_publish Parses the MQTT PUBLISH message
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* @return -ENOMEM if no data buffer is available
|
||||
* Parses the MQTT PUBLISH message
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx Data buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_rx_publish(struct mqtt_ctx *ctx, struct net_buf *rx);
|
||||
|
||||
|
||||
@ -147,16 +147,18 @@ struct zoap_reply;
|
||||
struct zoap_resource;
|
||||
|
||||
/**
|
||||
* Type of the callback being called when a resource's method is invoked by
|
||||
* remote entity.
|
||||
* @typedef zoap_method_t
|
||||
* @brief Type of the callback being called when a resource's method is
|
||||
* invoked by the remote entity.
|
||||
*/
|
||||
typedef int (*zoap_method_t)(struct zoap_resource *resource,
|
||||
struct zoap_packet *request,
|
||||
const struct sockaddr *from);
|
||||
|
||||
/**
|
||||
* Type of the callback being called when a resource's has observers to be
|
||||
* informed when an update happens.
|
||||
* @typedef zoap_notify_t
|
||||
* @brief Type of the callback being called when a resource's has observers
|
||||
* to be informed when an update happens.
|
||||
*/
|
||||
typedef void (*zoap_notify_t)(struct zoap_resource *resource,
|
||||
struct zoap_observer *observer);
|
||||
@ -168,6 +170,7 @@ typedef void (*zoap_notify_t)(struct zoap_resource *resource,
|
||||
* them, by fetching their state or requesting updates to them.
|
||||
*/
|
||||
struct zoap_resource {
|
||||
/** Which function to be called for each CoAP method */
|
||||
zoap_method_t get, post, put, del;
|
||||
zoap_notify_t notify;
|
||||
const char * const *path;
|
||||
@ -177,7 +180,7 @@ struct zoap_resource {
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a remote device that is observing a local resource.
|
||||
* @brief Represents a remote device that is observing a local resource.
|
||||
*/
|
||||
struct zoap_observer {
|
||||
sys_snode_t list;
|
||||
@ -187,7 +190,7 @@ struct zoap_observer {
|
||||
};
|
||||
|
||||
/**
|
||||
* Representation of a CoAP packet.
|
||||
* @brief Representation of a CoAP packet.
|
||||
*/
|
||||
struct zoap_packet {
|
||||
struct net_buf *buf;
|
||||
@ -196,7 +199,8 @@ struct zoap_packet {
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to be called when a response matches the
|
||||
* @typedef zoap_reply_t
|
||||
* @brief Helper function to be called when a response matches the
|
||||
* a pending request.
|
||||
*/
|
||||
typedef int (*zoap_reply_t)(const struct zoap_packet *response,
|
||||
@ -204,7 +208,7 @@ typedef int (*zoap_reply_t)(const struct zoap_packet *response,
|
||||
const struct sockaddr *from);
|
||||
|
||||
/**
|
||||
* Represents a request awaiting for an acknowledgment (ACK).
|
||||
* @brief Represents a request awaiting for an acknowledgment (ACK).
|
||||
*/
|
||||
struct zoap_pending {
|
||||
struct zoap_packet request;
|
||||
@ -212,8 +216,8 @@ struct zoap_pending {
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the handler for the reply of a request, it is also used when
|
||||
* observing resources.
|
||||
* @brief Represents the handler for the reply of a request, it is
|
||||
* also used when observing resources.
|
||||
*/
|
||||
struct zoap_reply {
|
||||
zoap_reply_t reply;
|
||||
@ -224,48 +228,76 @@ struct zoap_reply {
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates that the remote device referenced by @a addr, with @a request,
|
||||
* wants to observe a resource.
|
||||
* @brief Indicates that the remote device referenced by @a addr, with
|
||||
* @a request, wants to observe a resource.
|
||||
*
|
||||
* @param observer Observer to be initialized
|
||||
* @param request Request on which the observer will be based
|
||||
* @param addr Address of the remote device
|
||||
*/
|
||||
void zoap_observer_init(struct zoap_observer *observer,
|
||||
const struct zoap_packet *request,
|
||||
const struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* After the observer is initialized, associate the observer with an resource.
|
||||
* Returns whether this is the first observer added to this resource.
|
||||
* @brief After the observer is initialized, associate the observer
|
||||
* with an resource.
|
||||
*
|
||||
* @param resource Resource to add an observer
|
||||
* @param observer Observer to be added
|
||||
*
|
||||
* @return true if this is the first observer added to this resource.
|
||||
*/
|
||||
bool zoap_register_observer(struct zoap_resource *resource,
|
||||
struct zoap_observer *observer);
|
||||
|
||||
/**
|
||||
* Remove this observer from the list of registered observers of
|
||||
* that resource.
|
||||
* @brief Remove this observer from the list of registered observers
|
||||
* of that resource.
|
||||
*
|
||||
* @param resource Resource in which to remove the observer
|
||||
* @param observer Observer to be removed
|
||||
*/
|
||||
void zoap_remove_observer(struct zoap_resource *resource,
|
||||
struct zoap_observer *observer);
|
||||
|
||||
/**
|
||||
* Returns the observer that matches address @a addr.
|
||||
* @brief Returns the observer that matches address @a addr.
|
||||
*
|
||||
* @param observers Pointer to the array of observers
|
||||
* @param len Size of the array of observers
|
||||
* @param addr Address of the endpoint observing a resource
|
||||
*
|
||||
* @return A pointer to a observer if a match is found, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
struct zoap_observer *zoap_find_observer_by_addr(
|
||||
struct zoap_observer *observers, size_t len,
|
||||
const struct sockaddr *addr);
|
||||
|
||||
/**
|
||||
* Returns the next available observer representation.
|
||||
* @brief Returns the next available observer representation.
|
||||
*
|
||||
* @param observers Pointer to the array of observers
|
||||
* @param len Size of the array of observers
|
||||
*
|
||||
* @return A pointer to a observer if there's an available observer,
|
||||
* NULL otherwise.
|
||||
*/
|
||||
struct zoap_observer *zoap_observer_next_unused(
|
||||
struct zoap_observer *observers, size_t len);
|
||||
|
||||
/**
|
||||
* Indicates that a reply is expected for @a request.
|
||||
* @brief Indicates that a reply is expected for @a request.
|
||||
*
|
||||
* @param reply Reply structure to be initialized
|
||||
* @param request Request from which @a reply will be based
|
||||
*/
|
||||
void zoap_reply_init(struct zoap_reply *reply,
|
||||
const struct zoap_packet *request);
|
||||
|
||||
/**
|
||||
* Represents the value of a CoAP option.
|
||||
* @brief Represents the value of a CoAP option.
|
||||
*
|
||||
* To be used with zoap_find_options().
|
||||
*/
|
||||
@ -275,51 +307,97 @@ struct zoap_option {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the CoAP packet in @a buf, validating it and initializing @a pkt.
|
||||
* @a buf must remain valid while @a pkt is used. Used when receiving packets.
|
||||
* @brief Parses the CoAP packet in @a buf, validating it and
|
||||
* initializing @a pkt. @a buf must remain valid while @a pkt is used.
|
||||
*
|
||||
* @param pkt Packet to be initialized from received @a buf.
|
||||
* @param buf Buffer containing a CoAP packet, its @a data pointer is
|
||||
* positioned on the start of the CoAP packet.
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_packet_parse(struct zoap_packet *pkt, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* Creates a new CoAP packet from a net_buf. @a buf must remain valid while
|
||||
* @a pkt is used. Used when creating packets to be sent.
|
||||
* @brief Creates a new CoAP packet from a net_buf. @a buf must remain
|
||||
* valid while @a pkt is used.
|
||||
*
|
||||
* @param pkt New packet to be initialized using the storage from @a
|
||||
* buf.
|
||||
* @param buf Buffer that will contain a CoAP packet
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_packet_init(struct zoap_packet *pkt, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* Initialize a pending request with a request. The request's fields are
|
||||
* copied into the pending struct, so @a request doesn't have to live for as
|
||||
* long as the pending struct lives, but net_buf needs to live for at least
|
||||
* that long.
|
||||
* @brief Initialize a pending request with a request.
|
||||
*
|
||||
* The request's fields are copied into the pending struct, so @a
|
||||
* request doesn't have to live for as long as the pending struct
|
||||
* lives, but net_buf needs to live for at least that long.
|
||||
*
|
||||
* @param pending Structure representing the waiting for a
|
||||
* confirmation message, initialized with data from @a request
|
||||
* @param request Message waiting for confirmation
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_pending_init(struct zoap_pending *pending,
|
||||
const struct zoap_packet *request);
|
||||
|
||||
/**
|
||||
* Returns the next available pending struct, that can be used to track
|
||||
* the retransmission status of a request.
|
||||
* @brief Returns the next available pending struct, that can be used
|
||||
* to track the retransmission status of a request.
|
||||
*
|
||||
* @param pendings Pointer to the array of #zoap_pending structures
|
||||
* @param len Size of the array of #zoap_pending structures
|
||||
*
|
||||
* @return pointer to a free #zoap_pending structure, NULL in case
|
||||
* none could be found.
|
||||
*/
|
||||
struct zoap_pending *zoap_pending_next_unused(
|
||||
struct zoap_pending *pendings, size_t len);
|
||||
|
||||
/**
|
||||
* Returns the next available reply struct, so it can be used to track replies
|
||||
* and notifications received.
|
||||
* @brief Returns the next available reply struct, so it can be used
|
||||
* to track replies and notifications received.
|
||||
*
|
||||
* @param replies Pointer to the array of #zoap_reply structures
|
||||
* @param len Size of the array of #zoap_reply structures
|
||||
*
|
||||
* @return pointer to a free #zoap_reply structure, NULL in case
|
||||
* none could be found.
|
||||
*/
|
||||
struct zoap_reply *zoap_reply_next_unused(
|
||||
struct zoap_reply *replies, size_t len);
|
||||
|
||||
/**
|
||||
* After a response is received, clear all pending retransmissions related to
|
||||
* that response.
|
||||
* @brief After a response is received, clear all pending
|
||||
* retransmissions related to that response.
|
||||
*
|
||||
* @param response The received response
|
||||
* @param pendings Pointer to the array of #zoap_reply structures
|
||||
* @param len Size of the array of #zoap_reply structures
|
||||
*
|
||||
* @return pointer to the associated #zoap_pending structure, NULL in
|
||||
* case none could be found.
|
||||
*/
|
||||
struct zoap_pending *zoap_pending_received(
|
||||
const struct zoap_packet *response,
|
||||
struct zoap_pending *pendings, size_t len);
|
||||
|
||||
/**
|
||||
* After a response is received, clear all pending retransmissions related to
|
||||
* that response.
|
||||
* @brief After a response is received, clear all pending
|
||||
* retransmissions related to that response.
|
||||
*
|
||||
* @param response A response received
|
||||
* @param from Address from which the response was received
|
||||
* @param replies Pointer to the array of #zoap_reply structures
|
||||
* @param len Size of the array of #zoap_reply structures
|
||||
*
|
||||
* @return Pointer to the reply matching the packet received, NULL if
|
||||
* none could be found.
|
||||
*/
|
||||
struct zoap_reply *zoap_response_received(
|
||||
const struct zoap_packet *response,
|
||||
@ -327,91 +405,170 @@ struct zoap_reply *zoap_response_received(
|
||||
struct zoap_reply *replies, size_t len);
|
||||
|
||||
/**
|
||||
* Returns the next pending about to expire, pending->timeout informs how many
|
||||
* ms to next expiration.
|
||||
* @brief Returns the next pending about to expire, pending->timeout
|
||||
* informs how many ms to next expiration.
|
||||
*
|
||||
* @param pendings Pointer to the array of #zoap_pending structures
|
||||
* @param len Size of the array of #zoap_pending structures
|
||||
*
|
||||
* @return The next #zoap_pending to expire, NULL if none is about to
|
||||
* expire.
|
||||
*/
|
||||
struct zoap_pending *zoap_pending_next_to_expire(
|
||||
struct zoap_pending *pendings, size_t len);
|
||||
|
||||
/**
|
||||
* After a request is sent, user may want to cycle the pending retransmission
|
||||
* so the timeout is updated. Returns false if this is the last
|
||||
* retransmission.
|
||||
* @brief After a request is sent, user may want to cycle the pending
|
||||
* retransmission so the timeout is updated.
|
||||
*
|
||||
* @param pending Pending representation to have its timeout updated
|
||||
*
|
||||
* @return false if this is the last retransmission.
|
||||
*/
|
||||
bool zoap_pending_cycle(struct zoap_pending *pending);
|
||||
|
||||
/**
|
||||
* Cancels the pending retransmission, so it again becomes available.
|
||||
* @brief Cancels the pending retransmission, so it again becomes
|
||||
* available.
|
||||
*
|
||||
* @param pending Pending representation to be canceled
|
||||
*/
|
||||
void zoap_pending_clear(struct zoap_pending *pending);
|
||||
|
||||
/**
|
||||
* Cancels awaiting for this reply, so it becomes available again.
|
||||
* @brief Cancels awaiting for this reply, so it becomes available
|
||||
* again.
|
||||
*
|
||||
* @param reply The reply to be cancelled
|
||||
*/
|
||||
void zoap_reply_clear(struct zoap_reply *reply);
|
||||
|
||||
/**
|
||||
* When a request is received, call the appropriate methods of the
|
||||
* matching resources.
|
||||
* @brief When a request is received, call the appropriate methods of
|
||||
* the matching resources.
|
||||
*
|
||||
* @param pkt Packet received
|
||||
* @param resources Array of known resources
|
||||
* @param from Address from which the packet was received
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_handle_request(struct zoap_packet *pkt,
|
||||
struct zoap_resource *resources,
|
||||
const struct sockaddr *from);
|
||||
|
||||
/**
|
||||
* Indicates that this resource was updated and that the @a notify callback
|
||||
* should be called for every registered observer.
|
||||
* @brief Indicates that this resource was updated and that the @a
|
||||
* notify callback should be called for every registered observer.
|
||||
*
|
||||
* @param resource Resource that was updated
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_resource_notify(struct zoap_resource *resource);
|
||||
|
||||
/**
|
||||
* Returns if this request is enabling observing a resource.
|
||||
* @brief Returns if this request is enabling observing a resource.
|
||||
*
|
||||
* @param request Request to be checked
|
||||
*
|
||||
* @return True if the request is enabling observing a resource, False
|
||||
* otherwise
|
||||
*/
|
||||
bool zoap_request_is_observe(const struct zoap_packet *request);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the start of the payload, and how much memory
|
||||
* is available (to the payload), it will also insert the
|
||||
* COAP_MARKER (0xFF). When the payload is already set, for example,
|
||||
* for incoming packets, it will return how many bytes the payload
|
||||
* occupies.
|
||||
* @brief Returns a pointer to the start of the payload and its size
|
||||
*
|
||||
* It will insert the COAP_MARKER (0xFF), if its not set, and return the
|
||||
* available size for the payload.
|
||||
*
|
||||
* @param pkt Packet to get (or insert) the payload
|
||||
* @param len Amount of space for the payload
|
||||
*
|
||||
* @return pointer to the start of the payload, NULL in case of error.
|
||||
*/
|
||||
uint8_t *zoap_packet_get_payload(struct zoap_packet *pkt, uint16_t *len);
|
||||
|
||||
/**
|
||||
* Returns the internal buffer of the CoAP packet, appending the
|
||||
* COAP_MARKER to the buffer if necessary.
|
||||
* @brief Returns the internal buffer of the CoAP packet, appending
|
||||
* the COAP_MARKER to the buffer if necessary.
|
||||
*
|
||||
* @param pkt Packet to get (or insert) the payload
|
||||
*
|
||||
* @return pointer to the net_buf storing the payload.
|
||||
*/
|
||||
struct net_buf *zoap_packet_get_buf(struct zoap_packet *pkt);
|
||||
|
||||
/**
|
||||
* Sets how much space was used by the payload.
|
||||
* @brief Sets how much space was used by the payload.
|
||||
*
|
||||
* Used for outgoing packets, after zoap_packet_get_payload(), to
|
||||
* update the internal representation with the amount of data that was
|
||||
* added to the packet.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param len Amount of data that was added to the payload
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_packet_set_used(struct zoap_packet *pkt, uint16_t len);
|
||||
|
||||
/**
|
||||
* Adds an option to the packet. Note that options must be added
|
||||
* in numeric order of their codes.
|
||||
* @brief Adds an option to the packet.
|
||||
*
|
||||
* Note: ptions must be added in numeric order of their codes.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param code Option code to add to the packet, see #zoap_option_num
|
||||
* @param value Pointer to the value of the option, will be copied to the packet
|
||||
* @param len Size of the data to be added
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_option(struct zoap_packet *pkt, uint16_t code,
|
||||
const void *value, uint16_t len);
|
||||
|
||||
/**
|
||||
* Converts an option to its integer representation. It assumes that
|
||||
* the number is encoded in the network byte order in the option.
|
||||
* @brief Converts an option to its integer representation.
|
||||
*
|
||||
* Assumes that the number is encoded in the network byte order in the
|
||||
* option.
|
||||
*
|
||||
* @param option Pointer to the option value, retrieved by
|
||||
* zoap_find_options()
|
||||
*
|
||||
* @return The integer representation of the option
|
||||
*/
|
||||
unsigned int zoap_option_value_to_int(const struct zoap_option *option);
|
||||
|
||||
/**
|
||||
* Adds an integer value option to the packet. The option must be
|
||||
* added in numeric order of their codes, and the least amount of
|
||||
* bytes will be used to encode the value.
|
||||
* @brief Adds an integer value option to the packet.
|
||||
*
|
||||
* The option must be added in numeric order of their codes, and the
|
||||
* least amount of bytes will be used to encode the value.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param code Option code to add to the packet, see #zoap_option_num
|
||||
* @param val Integer value to be added
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_option_int(struct zoap_packet *pkt, uint16_t code,
|
||||
unsigned int val);
|
||||
|
||||
/**
|
||||
* Return the values associated with the option of value @a code.
|
||||
* @brief Return the values associated with the option of value @a
|
||||
* code.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param code Option number to look for
|
||||
* @param options Array of #zoap_option where to store the value
|
||||
* of the options found
|
||||
* @param veclen Number of elements in the options array
|
||||
*
|
||||
* @return The number of options found in packet matching code,
|
||||
* negative on error.
|
||||
*/
|
||||
int zoap_find_options(const struct zoap_packet *pkt, uint16_t code,
|
||||
struct zoap_option *options, uint16_t veclen);
|
||||
@ -435,7 +592,12 @@ enum zoap_block_size {
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for converting the enumeration to the size expressed in bytes.
|
||||
* @brief Helper for converting the enumeration to the size expressed
|
||||
* in bytes.
|
||||
*
|
||||
* @param block_size The block size to be converted
|
||||
*
|
||||
* @return The size in bytes that the block_size represents
|
||||
*/
|
||||
static inline uint16_t zoap_block_size_to_bytes(
|
||||
enum zoap_block_size block_size)
|
||||
@ -444,7 +606,7 @@ static inline uint16_t zoap_block_size_to_bytes(
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the current state of a block-wise transaction.
|
||||
* @brief Represents the current state of a block-wise transaction.
|
||||
*/
|
||||
struct zoap_block_context {
|
||||
size_t total_size;
|
||||
@ -453,103 +615,186 @@ struct zoap_block_context {
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the context of a block-wise transfer.
|
||||
* @brief Initializes the context of a block-wise transfer.
|
||||
*
|
||||
* @param ctx The context to be initialized
|
||||
* @param block_size The size of the block
|
||||
* @param total_size The total size of the transfer, if known
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_block_transfer_init(struct zoap_block_context *ctx,
|
||||
enum zoap_block_size block_size,
|
||||
size_t total_size);
|
||||
enum zoap_block_size block_size,
|
||||
size_t total_size);
|
||||
|
||||
/**
|
||||
* Add BLOCK1 option to the packet.
|
||||
* @brief Add BLOCK1 option to the packet.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param ctx Block context from which to retrieve the
|
||||
* information for the Block1 option
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_block1_option(struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Add BLOCK2 option to the packet.
|
||||
* @brief Add BLOCK2 option to the packet.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param ctx Block context from which to retrieve the
|
||||
* information for the Block2 option
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_block2_option(struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Add SIZE1 option to the packet.
|
||||
* @brief Add SIZE1 option to the packet.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param ctx Block context from which to retrieve the
|
||||
* information for the Size1 option
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_size1_option(struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Add SIZE2 option to the packet.
|
||||
* @brief Add SIZE2 option to the packet.
|
||||
*
|
||||
* @param pkt Packet to be updated
|
||||
* @param ctx Block context from which to retrieve the
|
||||
* information for the Size2 option
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_add_size2_option(struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Retrieves BLOCK{1,2} and SIZE{1,2} from @a pkt and updates
|
||||
* @brief Retrieves BLOCK{1,2} and SIZE{1,2} from @a pkt and updates
|
||||
* @a ctx accordingly.
|
||||
*
|
||||
* Returns an error if the packet contains invalid options.
|
||||
* @param pkt Packet in which to look for block-wise transfers options
|
||||
* @param ctx Block context to be updated
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_update_from_block(struct zoap_packet *pkt,
|
||||
int zoap_update_from_block(const struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Updates @a ctx so after this is called the current entry
|
||||
* @brief Updates @a ctx so after this is called the current entry
|
||||
* indicates the correct offset in the body of data being
|
||||
* transferred.
|
||||
*
|
||||
* @param ctx Block context to be updated
|
||||
*
|
||||
* @return The offset in the block-wise transfer, 0 if the transfer
|
||||
* has finished.
|
||||
*/
|
||||
size_t zoap_next_block(struct zoap_block_context *ctx);
|
||||
|
||||
/**
|
||||
* Returns the version present in a CoAP packet.
|
||||
* @brief Returns the version present in a CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
*
|
||||
* @return the CoAP version in packet
|
||||
*/
|
||||
uint8_t zoap_header_get_version(const struct zoap_packet *pkt);
|
||||
|
||||
/**
|
||||
* Returns the type of the packet present in the CoAP packet.
|
||||
* @brief Returns the type of the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
*
|
||||
* @return the type of the packet
|
||||
*/
|
||||
uint8_t zoap_header_get_type(const struct zoap_packet *pkt);
|
||||
|
||||
/**
|
||||
* Returns the token associated with a CoAP packet.
|
||||
* @brief Returns the token (if any) in the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param len Where to store the length of the token
|
||||
*
|
||||
* @return pointer to the start of the token in the CoAP packet.
|
||||
*/
|
||||
const uint8_t *zoap_header_get_token(const struct zoap_packet *pkt,
|
||||
uint8_t *len);
|
||||
|
||||
/**
|
||||
* Returns the code present in the header of a CoAP packet.
|
||||
* @brief Returns the code of the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
*
|
||||
* @return the code present in the packet
|
||||
*/
|
||||
uint8_t zoap_header_get_code(const struct zoap_packet *pkt);
|
||||
|
||||
/**
|
||||
* Returns the message id associated with a CoAP packet.
|
||||
* @brief Returns the message id associated with the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
*
|
||||
* @return the message id present in the packet
|
||||
*/
|
||||
uint16_t zoap_header_get_id(const struct zoap_packet *pkt);
|
||||
|
||||
/**
|
||||
* Sets the CoAP version present in the CoAP header of a packet.
|
||||
* @brief Sets the version of the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param ver The CoAP version to set in the packet
|
||||
*/
|
||||
void zoap_header_set_version(struct zoap_packet *pkt, uint8_t ver);
|
||||
|
||||
/**
|
||||
* Sets the type of a CoAP message.
|
||||
* @brief Sets the type of the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param type The packet type to set
|
||||
*/
|
||||
void zoap_header_set_type(struct zoap_packet *pkt, uint8_t type);
|
||||
|
||||
/**
|
||||
* Sets the token present in the CoAP header of a packet.
|
||||
* @brief Sets the token in the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param token Token to set in the packet, will be copied
|
||||
* @param tokenlen Size of the token to be set, 8 bytes maximum
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int zoap_header_set_token(struct zoap_packet *pkt, const uint8_t *token,
|
||||
uint8_t tokenlen);
|
||||
|
||||
/**
|
||||
* Sets the code present in the header of a CoAP packet.
|
||||
* @brief Sets the code present in the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param code The code set in the packet
|
||||
*/
|
||||
void zoap_header_set_code(struct zoap_packet *pkt, uint8_t code);
|
||||
|
||||
/**
|
||||
* Sets the message id associated with a CoAP packet.
|
||||
* @brief Sets the message id present in the CoAP packet.
|
||||
*
|
||||
* @param pkt CoAP packet representation
|
||||
* @param id The message id to set in the packet
|
||||
*/
|
||||
void zoap_header_set_id(struct zoap_packet *pkt, uint16_t id);
|
||||
|
||||
/**
|
||||
* @brief Helper to generate message ids
|
||||
*
|
||||
* @return a new message id
|
||||
*/
|
||||
static inline uint16_t zoap_next_id(void)
|
||||
{
|
||||
static uint16_t message_id;
|
||||
@ -558,8 +803,10 @@ static inline uint16_t zoap_next_id(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a randomly generated array of 8 bytes, that can be used as a
|
||||
* message's token.
|
||||
* @brief Returns a randomly generated array of 8 bytes, that can be
|
||||
* used as a message's token.
|
||||
*
|
||||
* @return a 8-byte pseudo-random token.
|
||||
*/
|
||||
uint8_t *zoap_next_token(void);
|
||||
|
||||
|
||||
10
lib/libc/minimal/include/time.h
Normal file
10
lib/libc/minimal/include/time.h
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/* Dummy time.h to fulfill the requirements of certain libraries
|
||||
* i.e. mbedTLS
|
||||
*/
|
||||
@ -29,5 +29,5 @@ CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2"
|
||||
|
||||
26
samples/net/echo_client/prj_qemu_cortex_m3.conf
Normal file
26
samples/net/echo_client/prj_qemu_cortex_m3.conf
Normal file
@ -0,0 +1,26 @@
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
CONFIG_NET_NBUF_RX_COUNT=14
|
||||
CONFIG_NET_NBUF_TX_COUNT=14
|
||||
CONFIG_NET_NBUF_DATA_COUNT=30
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.2"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.1"
|
||||
27
samples/net/echo_server/prj_qemu_cortex_m3.conf
Normal file
27
samples/net/echo_server/prj_qemu_cortex_m3.conf
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
CONFIG_NET_NBUF_RX_COUNT=16
|
||||
CONFIG_NET_NBUF_TX_COUNT=16
|
||||
CONFIG_NET_NBUF_DATA_COUNT=40
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
|
||||
CONFIG_NET_MAX_CONTEXTS=16
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2"
|
||||
@ -109,7 +109,6 @@ Refer to the board documentation in Zephyr, :ref:`frdm_k64f`,
|
||||
for more information about this board and how to access the FRDM
|
||||
serial console under other operating systems.
|
||||
|
||||
|
||||
Sample Output
|
||||
=============
|
||||
|
||||
@ -223,6 +222,60 @@ and this is the HTML message that wget will save:
|
||||
<body><h1><center>404 Not Found</center></h1></body>
|
||||
</html>
|
||||
|
||||
HTTPS Server
|
||||
============
|
||||
|
||||
The sample code also includes a HTTPS (HTTP over TLS) server example
|
||||
running side by side with the HTTP server, this server runs on qemu.
|
||||
In order to compile and run the code execute:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make BOARD=qemu_x86 run
|
||||
|
||||
The sample code supports only one hard-coded valid URL (index.html) and
|
||||
will return 404 code for other requests.
|
||||
|
||||
Sample Output
|
||||
=============
|
||||
|
||||
The app will show the following on the screen:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Zephyr HTTP Server
|
||||
Address: 192.0.2.1, port: 80
|
||||
Zephyr HTTPS Server
|
||||
Address: 192.0.2.1, port: 443
|
||||
failed
|
||||
! mbedtls_ssl_handshake returned -29312
|
||||
|
||||
Now execute the following command on a different terminal window
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
wget https://192.0.2.1 --no-check-certificate
|
||||
|
||||
This will be shown on the screen
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Connecting to 192.0.2.1:443... connected.
|
||||
WARNING: cannot verify 192.0.2.1's certificate
|
||||
Unable to locally verify the issuer's authority.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: unspecified [text/html]
|
||||
Saving to: ‘index.html’
|
||||
|
||||
index.html [ <=> ]
|
||||
|
||||
The inspection of the file index.html will show
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
<h2>Zephyr TLS Test Server</h2>
|
||||
<p>Successful connection</p>
|
||||
|
||||
Known Issues and Limitations
|
||||
============================
|
||||
|
||||
@ -230,3 +283,5 @@ Known Issues and Limitations
|
||||
chunk transfer mode.
|
||||
- Clients must close the connection to allow the HTTP server to release
|
||||
the network context and accept another connection.
|
||||
- The use of mbedTLS and IPv6 takes more than the available ram for the
|
||||
emulation platform, so only IPv4 works for now in QEMU.
|
||||
|
||||
34
samples/net/http_server/prj_qemu_x86.conf
Normal file
34
samples/net/http_server/prj_qemu_x86.conf
Normal file
@ -0,0 +1,34 @@
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=16
|
||||
CONFIG_NET_NBUF_TX_COUNT=16
|
||||
CONFIG_NET_NBUF_DATA_COUNT=16
|
||||
|
||||
CONFIG_NET_IPV6_RA_RDNSS=y
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
|
||||
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
CONFIG_HTTP_PARSER=y
|
||||
|
||||
# Enable IPv6 support
|
||||
CONFIG_NET_IPV6=n
|
||||
# Enable IPv4 support
|
||||
CONFIG_NET_IPV4=y
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
|
||||
|
||||
CONFIG_NET_MAX_CONTEXTS=16
|
||||
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_MBEDTLS_BUILTIN=y
|
||||
CONFIG_MBEDTLS_CFG_FILE="config-mini-tls1_2.h"
|
||||
@ -8,3 +8,8 @@ obj-y += main.o
|
||||
obj-y += http_utils.o
|
||||
obj-y += http_server.o
|
||||
obj-y += http_write_utils.o
|
||||
ifdef CONFIG_MBEDTLS
|
||||
obj-y += https_server.o ssl_utils.o
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@ -25,4 +25,8 @@
|
||||
|
||||
#define APP_SLEEP_MSECS 500
|
||||
|
||||
#ifdef CONFIG_MBEDTLS
|
||||
#define SERVER_PORT 443
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -21,6 +21,32 @@
|
||||
|
||||
NET_BUF_POOL_DEFINE(http_msg_pool, HTTP_BUF_CTR, HTTP_BUF_SIZE, 0, NULL);
|
||||
|
||||
void http_accept_cb(struct net_context *net_ctx, struct sockaddr *addr,
|
||||
socklen_t addr_len, int status, void *data)
|
||||
{
|
||||
struct http_server_ctx *http_ctx = NULL;
|
||||
|
||||
ARG_UNUSED(addr_len);
|
||||
ARG_UNUSED(data);
|
||||
|
||||
if (status != 0) {
|
||||
net_context_put(net_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
print_client_banner(addr);
|
||||
|
||||
http_ctx = http_ctx_get();
|
||||
if (!http_ctx) {
|
||||
net_context_put(net_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
http_ctx_set(http_ctx, net_ctx);
|
||||
|
||||
net_context_recv(net_ctx, http_rx_tx, K_NO_WAIT, http_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief http_ctx_release Releases an HTTP context
|
||||
* @return 0, future versions may return error codes
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
|
||||
#include <net/net_context.h>
|
||||
|
||||
/* Callback executed when a new connection is accepted */
|
||||
void http_accept_cb(struct net_context *net_ctx, struct sockaddr *addr,
|
||||
socklen_t addr_len, int status, void *data);
|
||||
|
||||
/**
|
||||
* @brief http_rx_tx Reads the HTTP request from the `rx` buffer
|
||||
* and writes an HTTP 1.1 200 OK response with client
|
||||
|
||||
406
samples/net/http_server/src/https_server.c
Normal file
406
samples/net/http_server/src/https_server.c
Normal file
@ -0,0 +1,406 @@
|
||||
/* Minimal TLS server.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include CONFIG_MBEDTLS_CFG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define mbedtls_time_t time_t
|
||||
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
|
||||
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/net_if.h>
|
||||
#include "config.h"
|
||||
#include "ssl_utils.h"
|
||||
#include "test_certs.h"
|
||||
|
||||
#include "mbedtls/ssl_cookie.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
#include "mbedtls/debug.h"
|
||||
#define DEBUG_THRESHOLD 0
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
|
||||
#include "mbedtls/memory_buffer_alloc.h"
|
||||
static unsigned char heap[12000];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hardcoded values for server host and port
|
||||
*/
|
||||
|
||||
static const char *pers = "tls_server";
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct in6_addr server_addr;
|
||||
#else
|
||||
static struct in_addr server_addr;
|
||||
#endif
|
||||
|
||||
struct parsed_url {
|
||||
const char *url;
|
||||
uint16_t url_len;
|
||||
};
|
||||
|
||||
#define HTTP_RESPONSE \
|
||||
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
|
||||
"<h2>Zephyr TLS Test Server</h2>\r\n" \
|
||||
"<p>Successful connection</p>\r\n"
|
||||
|
||||
#define HTTP_NOT_FOUND \
|
||||
"HTTP/1.0 404 NOT FOUND\r\nContent-Type: text/html\r\n\r\n" \
|
||||
"<h2>Zephyr TLS page not found </h2>\r\n" \
|
||||
"<p>Successful connection</p>\r\n"
|
||||
|
||||
static void my_debug(void *ctx, int level,
|
||||
const char *file, int line, const char *str)
|
||||
{
|
||||
const char *p, *basename;
|
||||
|
||||
ARG_UNUSED(ctx);
|
||||
|
||||
/* Extract basename from file */
|
||||
for (p = basename = file; *p != '\0'; p++) {
|
||||
if (*p == '/' || *p == '\\') {
|
||||
basename = p + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str);
|
||||
}
|
||||
|
||||
static int entropy_source(void *data, unsigned char *output, size_t len,
|
||||
size_t *olen)
|
||||
{
|
||||
uint32_t seed;
|
||||
|
||||
ARG_UNUSED(data);
|
||||
|
||||
seed = sys_rand32_get();
|
||||
|
||||
if (len > sizeof(seed)) {
|
||||
len = sizeof(seed);
|
||||
}
|
||||
|
||||
memcpy(output, &seed, len);
|
||||
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int on_url(struct http_parser *parser, const char *at, size_t length)
|
||||
{
|
||||
struct parsed_url *req = (struct parsed_url *)parser->data;
|
||||
|
||||
req->url = at;
|
||||
req->url_len = length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char payload[256];
|
||||
|
||||
void https_server(void)
|
||||
{
|
||||
struct ssl_context ctx;
|
||||
struct parsed_url request;
|
||||
int ret, len = 0;
|
||||
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt srvcert;
|
||||
mbedtls_pk_context pkey;
|
||||
|
||||
mbedtls_platform_set_printf(printk);
|
||||
|
||||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
|
||||
mbedtls_memory_buffer_alloc_init(heap, sizeof(heap));
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold(DEBUG_THRESHOLD);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);
|
||||
#endif
|
||||
mbedtls_x509_crt_init(&srvcert);
|
||||
mbedtls_pk_init(&pkey);
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
/*
|
||||
* 1. Load the certificates and private RSA key
|
||||
*/
|
||||
|
||||
ret = mbedtls_x509_crt_parse(&srvcert, rsa_example_cert_der,
|
||||
rsa_example_cert_der_len);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_x509_crt_parse returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_pk_parse_key(&pkey, rsa_example_keypair_der,
|
||||
rsa_example_keypair_der_len, NULL, 0);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_pk_parse_key returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 3. Seed the RNG
|
||||
*/
|
||||
|
||||
mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
|
||||
MBEDTLS_ENTROPY_MAX_GATHER,
|
||||
MBEDTLS_ENTROPY_SOURCE_STRONG);
|
||||
|
||||
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *)pers, strlen(pers));
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ctr_drbg_seed returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4. Setup stuff
|
||||
*/
|
||||
ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ssl_config_defaults returned %d\n\n",
|
||||
ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
|
||||
ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ssl_conf_own_cert returned %d\n\n",
|
||||
ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_setup(&ssl, &conf);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ssl_setup returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 3. Wait until a client connects
|
||||
*/
|
||||
ret = ssl_init(&ctx, &server_addr);
|
||||
if (ret != 0) {
|
||||
mbedtls_printf(" failed\n ! ssl_init returned %d\n\n", ret);
|
||||
goto exit;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 4. Prepare http parser
|
||||
*/
|
||||
http_parser_init(&ctx.parser, HTTP_REQUEST);
|
||||
http_parser_settings_init(&ctx.parser_settings);
|
||||
ctx.parser.data = &request;
|
||||
ctx.parser_settings.on_url = on_url;
|
||||
|
||||
mbedtls_printf("Zephyr HTTPS Server\n");
|
||||
mbedtls_printf("Address: %s, port: %d\n", ZEPHYR_ADDR, SERVER_PORT);
|
||||
reset:
|
||||
mbedtls_ssl_session_reset(&ssl);
|
||||
mbedtls_ssl_set_bio(&ssl, &ctx, ssl_tx, ssl_rx, NULL);
|
||||
/*
|
||||
* 5. Handshake
|
||||
*/
|
||||
do {
|
||||
ret = mbedtls_ssl_handshake(&ssl);
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
if (ret < 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ssl_handshake returned %d\n\n",
|
||||
ret);
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
} while (ret != 0);
|
||||
|
||||
/*
|
||||
* 6. Read the HTTPS Request
|
||||
*/
|
||||
mbedtls_printf("Read HTTPS request\n");
|
||||
do {
|
||||
len = sizeof(payload) - 1;
|
||||
memset(payload, 0, sizeof(payload));
|
||||
ret = mbedtls_ssl_read(&ssl, payload, len);
|
||||
|
||||
if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
switch (ret) {
|
||||
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
||||
mbedtls_printf(" connection was"
|
||||
" closed gracefully\n");
|
||||
goto close;
|
||||
|
||||
case MBEDTLS_ERR_NET_CONN_RESET:
|
||||
mbedtls_printf(" connection was"
|
||||
" reset by peer\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
mbedtls_printf
|
||||
(" mbedtls_ssl_read returned -0x%x\n",
|
||||
-ret);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
len = ret;
|
||||
ret = http_parser_execute(&ctx.parser, &ctx.parser_settings,
|
||||
payload, len);
|
||||
if (ret < 0) {
|
||||
}
|
||||
} while (ret < 0);
|
||||
|
||||
/*
|
||||
* 7. Write the Response
|
||||
*/
|
||||
mbedtls_printf("Write HTTPS response\n");
|
||||
|
||||
if (!strncmp("/index.html", request.url, request.url_len)) {
|
||||
len = snprintf((char *)payload, sizeof(payload),
|
||||
HTTP_RESPONSE);
|
||||
} else {
|
||||
|
||||
len = snprintf((char *)payload, sizeof(payload),
|
||||
HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
do {
|
||||
ret = mbedtls_ssl_write(&ssl, payload, len);
|
||||
if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" peer closed the connection\n");
|
||||
goto reset;
|
||||
}
|
||||
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
if (ret < 0) {
|
||||
mbedtls_printf(" failed\n !"
|
||||
" mbedtls_ssl_write"
|
||||
" returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
} while (ret <= 0);
|
||||
|
||||
close:
|
||||
|
||||
mbedtls_ssl_close_notify(&ssl);
|
||||
ret = 0;
|
||||
goto reset;
|
||||
|
||||
exit:
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
if (ret != 0) {
|
||||
mbedtls_strerror(ret, payload, 100);
|
||||
mbedtls_printf("Last error was: %d - %s\n", ret, payload);
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
}
|
||||
|
||||
#define STACK_SIZE 8192
|
||||
uint8_t stack[STACK_SIZE];
|
||||
|
||||
static inline int init_app(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (net_addr_pton(AF_INET6, ZEPHYR_ADDR, &server_addr) < 0) {
|
||||
mbedtls_printf("Invalid IPv6 address %s", ZEPHYR_ADDR);
|
||||
}
|
||||
|
||||
if (!net_if_ipv6_addr_add(net_if_get_default(), &server_addr,
|
||||
NET_ADDR_MANUAL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
#else
|
||||
if (net_addr_pton(AF_INET, ZEPHYR_ADDR, &server_addr) < 0) {
|
||||
mbedtls_printf("Invalid IPv4 address %s", ZEPHYR_ADDR);
|
||||
}
|
||||
|
||||
if (!net_if_ipv4_addr_add(net_if_get_default(), &server_addr,
|
||||
NET_ADDR_MANUAL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void https_server_start(void)
|
||||
{
|
||||
if (init_app() != 0) {
|
||||
printk("Cannot initialize network\n");
|
||||
return;
|
||||
}
|
||||
|
||||
k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) https_server,
|
||||
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
|
||||
}
|
||||
@ -15,82 +15,53 @@
|
||||
#include "http_write_utils.h"
|
||||
#include "config.h"
|
||||
|
||||
static void network_setup(void);
|
||||
/* Sets the network parameters */
|
||||
static
|
||||
int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb,
|
||||
const char *addr, uint16_t port);
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
#include "ssl_utils.h"
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct net_context *net_ctx = NULL;
|
||||
|
||||
http_ctx_init();
|
||||
|
||||
http_url_default_handler(http_write_soft_404_not_found);
|
||||
http_url_add("/headers", HTTP_URL_STANDARD, http_write_header_fields);
|
||||
http_url_add("/index.html", HTTP_URL_STANDARD, http_write_it_works);
|
||||
|
||||
network_setup();
|
||||
network_setup(&net_ctx, http_accept_cb, ZEPHYR_ADDR, ZEPHYR_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief connection_cb Callback executed when a connection is accepted
|
||||
* @param ctx Network context
|
||||
* @param addr Client's address
|
||||
* @param addr_len Address length
|
||||
* @param status Status code, 0 on success, < 0 otherwise
|
||||
* @param data User-provided data
|
||||
*/
|
||||
void connection_cb(struct net_context *net_ctx, struct sockaddr *addr,
|
||||
socklen_t addr_len, int status, void *data)
|
||||
static
|
||||
int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb,
|
||||
const char *addr, uint16_t port)
|
||||
{
|
||||
struct http_server_ctx *http_ctx = NULL;
|
||||
|
||||
ARG_UNUSED(addr_len);
|
||||
ARG_UNUSED(data);
|
||||
|
||||
if (status != 0) {
|
||||
printk("Status code: %d\n", status);
|
||||
net_context_put(net_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
print_client_banner(addr);
|
||||
|
||||
http_ctx = http_ctx_get();
|
||||
if (!http_ctx) {
|
||||
printk("Unable to get free HTTP context\n");
|
||||
net_context_put(net_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
http_ctx_set(http_ctx, net_ctx);
|
||||
|
||||
net_context_recv(net_ctx, http_rx_tx, 0, http_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief network_setup This routine configures the HTTP server.
|
||||
* It puts the application in listening mode and
|
||||
* installs the accept connection callback.
|
||||
*/
|
||||
static void network_setup(void)
|
||||
{
|
||||
struct net_context *ctx = NULL;
|
||||
struct sockaddr local_sock;
|
||||
void *ptr;
|
||||
int rc;
|
||||
|
||||
*net_ctx = NULL;
|
||||
|
||||
#ifdef CONFIG_NET_IPV6
|
||||
net_sin6(&local_sock)->sin6_port = htons(ZEPHYR_PORT);
|
||||
sock_addr.family = AF_INET6;
|
||||
net_sin6(&local_sock)->sin6_port = htons(port);
|
||||
local_sock.family = AF_INET6;
|
||||
ptr = &(net_sin6(&local_sock)->sin6_addr);
|
||||
rc = net_addr_pton(AF_INET6, ZEPHYR_ADDR, ptr);
|
||||
rc = net_addr_pton(AF_INET6, addr, ptr);
|
||||
#else
|
||||
net_sin(&local_sock)->sin_port = htons(ZEPHYR_PORT);
|
||||
net_sin(&local_sock)->sin_port = htons(port);
|
||||
local_sock.family = AF_INET;
|
||||
ptr = &(net_sin(&local_sock)->sin_addr);
|
||||
rc = net_addr_pton(AF_INET, ZEPHYR_ADDR, ptr);
|
||||
rc = net_addr_pton(AF_INET, addr, ptr);
|
||||
#endif
|
||||
|
||||
if (rc) {
|
||||
printk("Invalid IP address/Port: %s, %d\n",
|
||||
ZEPHYR_ADDR, ZEPHYR_PORT);
|
||||
printk("Invalid IP address/Port: %s, %d\n", addr, port);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPV6
|
||||
@ -102,41 +73,46 @@ static void network_setup(void)
|
||||
&net_sin(&local_sock)->sin_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif
|
||||
print_server_banner(&local_sock);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &ctx);
|
||||
rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, net_ctx);
|
||||
#else
|
||||
rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx);
|
||||
rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, net_ctx);
|
||||
#endif
|
||||
if (rc != 0) {
|
||||
printk("net_context_get error\n");
|
||||
return;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = net_context_bind(ctx, (const struct sockaddr *)&local_sock,
|
||||
rc = net_context_bind(*net_ctx, (const struct sockaddr *)&local_sock,
|
||||
sizeof(local_sock));
|
||||
if (rc != 0) {
|
||||
printk("net_context_bind error\n");
|
||||
goto lb_error;
|
||||
}
|
||||
|
||||
rc = net_context_listen(ctx, 0);
|
||||
rc = net_context_listen(*net_ctx, 0);
|
||||
if (rc != 0) {
|
||||
printk("[%s:%d] net_context_listen %d, <%s>\n",
|
||||
__func__, __LINE__, rc, RC_STR(rc));
|
||||
printk("net_context_listen error\n");
|
||||
goto lb_error;
|
||||
}
|
||||
|
||||
rc = net_context_accept(ctx, connection_cb, 0, NULL);
|
||||
rc = net_context_accept(*net_ctx, accept_cb, 0, NULL);
|
||||
if (rc != 0) {
|
||||
printk("[%s:%d] net_context_accept %d, <%s>\n",
|
||||
__func__, __LINE__, rc, RC_STR(rc));
|
||||
printk("net_context_accept error\n");
|
||||
goto lb_error;
|
||||
}
|
||||
|
||||
return;
|
||||
print_server_banner(&local_sock);
|
||||
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
https_server_start();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
lb_error:
|
||||
net_context_put(ctx);
|
||||
net_context_put(*net_ctx);
|
||||
*net_ctx = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
295
samples/net/http_server/src/ssl_utils.c
Normal file
295
samples/net/http_server/src/ssl_utils.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include CONFIG_MBEDTLS_CFG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/ssl.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "ssl_utils.h"
|
||||
|
||||
#define RX_FIFO_DEPTH 4
|
||||
|
||||
K_MEM_POOL_DEFINE(rx_pkts, 4, 64, RX_FIFO_DEPTH, 4);
|
||||
|
||||
static void ssl_received(struct net_context *context,
|
||||
struct net_buf *buf, int status, void *user_data)
|
||||
{
|
||||
struct ssl_context *ctx = user_data;
|
||||
struct rx_fifo_block *rx_data = NULL;
|
||||
struct k_mem_block block;
|
||||
|
||||
ARG_UNUSED(context);
|
||||
ARG_UNUSED(status);
|
||||
|
||||
if (!net_nbuf_appdatalen(buf)) {
|
||||
net_nbuf_unref(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
k_mem_pool_alloc(&rx_pkts, &block,
|
||||
sizeof(struct rx_fifo_block), K_FOREVER);
|
||||
rx_data = block.data;
|
||||
rx_data->buf = buf;
|
||||
|
||||
/* For freeing memory later */
|
||||
memcpy(&rx_data->block, &block, sizeof(struct k_mem_block));
|
||||
k_fifo_put(&ctx->rx_fifo, (void *)rx_data);
|
||||
}
|
||||
|
||||
static inline void ssl_sent(struct net_context *context,
|
||||
int status, void *token, void *user_data)
|
||||
{
|
||||
struct ssl_context *ctx = user_data;
|
||||
|
||||
k_sem_give(&ctx->tx_sem);
|
||||
}
|
||||
|
||||
int ssl_tx(void *context, const unsigned char *buf, size_t size)
|
||||
{
|
||||
struct ssl_context *ctx = context;
|
||||
struct net_context *net_ctx;
|
||||
struct net_buf *send_buf;
|
||||
|
||||
int rc, len;
|
||||
|
||||
net_ctx = ctx->net_ctx;
|
||||
|
||||
send_buf = net_nbuf_get_tx(net_ctx, K_NO_WAIT);
|
||||
if (!send_buf) {
|
||||
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
|
||||
if (!rc) {
|
||||
net_nbuf_unref(send_buf);
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
len = net_buf_frags_len(send_buf);
|
||||
|
||||
rc = net_context_send(send_buf, ssl_sent, K_NO_WAIT, NULL, ctx);
|
||||
|
||||
if (rc < 0) {
|
||||
net_nbuf_unref(send_buf);
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
k_sem_take(&ctx->tx_sem, K_FOREVER);
|
||||
return len;
|
||||
}
|
||||
|
||||
int ssl_rx(void *context, unsigned char *buf, size_t size)
|
||||
{
|
||||
struct ssl_context *ctx = context;
|
||||
uint16_t read_bytes;
|
||||
struct rx_fifo_block *rx_data;
|
||||
uint8_t *ptr;
|
||||
int pos;
|
||||
int len;
|
||||
int rc = 0;
|
||||
|
||||
if (ctx->frag == NULL) {
|
||||
rx_data = k_fifo_get(&ctx->rx_fifo, K_FOREVER);
|
||||
ctx->rx_nbuf = rx_data->buf;
|
||||
k_mem_pool_free(&rx_data->block);
|
||||
|
||||
read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf);
|
||||
|
||||
ctx->remaining = read_bytes;
|
||||
ctx->frag = ctx->rx_nbuf->frags;
|
||||
ptr = net_nbuf_appdata(ctx->rx_nbuf);
|
||||
|
||||
len = ptr - ctx->frag->data;
|
||||
net_buf_pull(ctx->frag, len);
|
||||
} else {
|
||||
read_bytes = ctx->remaining;
|
||||
ptr = ctx->frag->data;
|
||||
}
|
||||
|
||||
len = ctx->frag->len;
|
||||
pos = 0;
|
||||
if (read_bytes > size) {
|
||||
while (ctx->frag) {
|
||||
read_bytes = len < (size - pos) ? len : (size - pos);
|
||||
memcpy(buf + pos, ptr, read_bytes);
|
||||
pos += read_bytes;
|
||||
if (pos < size) {
|
||||
ctx->frag = ctx->frag->frags;
|
||||
ptr = ctx->frag->data;
|
||||
len = ctx->frag->len;
|
||||
} else {
|
||||
if (read_bytes == len) {
|
||||
ctx->frag = ctx->frag->frags;
|
||||
} else {
|
||||
net_buf_pull(ctx->frag, read_bytes);
|
||||
}
|
||||
|
||||
ctx->remaining -= size;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (ctx->frag) {
|
||||
memcpy(buf + pos, ptr, len);
|
||||
pos += len;
|
||||
ctx->frag = ctx->frag->frags;
|
||||
if (!ctx->frag) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = ctx->frag->data;
|
||||
len = ctx->frag->len;
|
||||
}
|
||||
|
||||
net_nbuf_unref(ctx->rx_nbuf);
|
||||
ctx->rx_nbuf = NULL;
|
||||
ctx->frag = NULL;
|
||||
ctx->remaining = 0;
|
||||
|
||||
if (read_bytes != pos) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = read_bytes;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ssl_accepted(struct net_context *context,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen, int error, void *user_data)
|
||||
{
|
||||
int ret;
|
||||
struct ssl_context *ctx = user_data;
|
||||
|
||||
ctx->net_ctx = context;
|
||||
ret = net_context_recv(context, ssl_received, 0, user_data);
|
||||
if (ret < 0) {
|
||||
printk("Cannot receive TCP packet (family %d)",
|
||||
net_context_get_family(context));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
int ssl_init(struct ssl_context *ctx, void *addr)
|
||||
{
|
||||
struct net_context *tcp_ctx = { 0 };
|
||||
struct sockaddr_in6 my_addr = { 0 };
|
||||
struct in6_addr *server_addr = addr;
|
||||
int rc;
|
||||
|
||||
k_sem_init(&ctx->tx_sem, 0, UINT_MAX);
|
||||
k_fifo_init(&ctx->rx_fifo);
|
||||
|
||||
my_mcast_addr.sin6_family = AF_INET6;
|
||||
|
||||
net_ipaddr_copy(&my_addr.sin6_addr, server_addr);
|
||||
my_addr.sin6_family = AF_INET6;
|
||||
my_addr.sin6_port = htons(SERVER_PORT);
|
||||
|
||||
rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx);
|
||||
if (rc < 0) {
|
||||
printk("Cannot get network context for IPv6 TCP (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (rc < 0) {
|
||||
printk("Cannot bind IPv6 TCP port %d (%d)", SERVER_PORT, rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctx->rx_nbuf = NULL;
|
||||
ctx->remaining = 0;
|
||||
ctx->net_ctx = tcp_ctx;
|
||||
|
||||
rc = net_context_listen(ctx->net_ctx, 0);
|
||||
if (rc < 0) {
|
||||
printk("Cannot listen IPv6 TCP (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx);
|
||||
if (rc < 0) {
|
||||
printk("Cannot accept IPv4 (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
net_context_put(tcp_ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#else
|
||||
int ssl_init(struct ssl_context *ctx, void *addr)
|
||||
{
|
||||
struct net_context *tcp_ctx = { 0 };
|
||||
struct sockaddr_in my_addr4 = { 0 };
|
||||
struct in_addr *server_addr = addr;
|
||||
int rc;
|
||||
|
||||
k_sem_init(&ctx->tx_sem, 0, UINT_MAX);
|
||||
k_fifo_init(&ctx->rx_fifo);
|
||||
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, server_addr);
|
||||
my_addr4.sin_family = AF_INET;
|
||||
my_addr4.sin_port = htons(SERVER_PORT);
|
||||
|
||||
rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx);
|
||||
if (rc < 0) {
|
||||
printk("Cannot get network context for IPv4 TCP (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (rc < 0) {
|
||||
printk("Cannot bind IPv4 TCP port %d (%d)", SERVER_PORT, rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctx->rx_nbuf = NULL;
|
||||
ctx->remaining = 0;
|
||||
ctx->net_ctx = tcp_ctx;
|
||||
|
||||
rc = net_context_listen(ctx->net_ctx, 0);
|
||||
if (rc < 0) {
|
||||
printk("Cannot listen IPv4 (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx);
|
||||
if (rc < 0) {
|
||||
printk("Cannot accept IPv4 (%d)", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
net_context_put(tcp_ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
37
samples/net/http_server/src/ssl_utils.h
Normal file
37
samples/net/http_server/src/ssl_utils.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SSL_UTILS_H_
|
||||
#define _SSL_UTILS_H_
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/http_parser.h>
|
||||
|
||||
struct rx_fifo_block {
|
||||
sys_snode_t snode;
|
||||
struct k_mem_block block;
|
||||
struct net_buf *buf;
|
||||
};
|
||||
|
||||
struct ssl_context {
|
||||
struct net_context *net_ctx;
|
||||
struct net_buf *rx_nbuf;
|
||||
struct net_buf *frag;
|
||||
struct k_sem tx_sem;
|
||||
struct k_fifo rx_fifo;
|
||||
struct http_parser_settings parser_settings;
|
||||
struct http_parser parser;
|
||||
|
||||
int remaining;
|
||||
};
|
||||
|
||||
int ssl_init(struct ssl_context *ctx, void *addr);
|
||||
int ssl_tx(void *ctx, const unsigned char *buf, size_t size);
|
||||
int ssl_rx(void *ctx, unsigned char *buf, size_t size);
|
||||
|
||||
void https_server_start(void);
|
||||
|
||||
#endif
|
||||
92
samples/net/http_server/src/test_certs.h
Normal file
92
samples/net/http_server/src/test_certs.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __TEST_CERTS_H__
|
||||
#define __TEST_CERTS_H__
|
||||
|
||||
static const unsigned char rsa_example_keypair_der[] = {
|
||||
0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0x9b, 0xfc,
|
||||
0x66, 0x90, 0x79, 0x84, 0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8,
|
||||
0xde, 0x15, 0x12, 0xe5, 0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1,
|
||||
0xe1, 0x9e, 0x26, 0xbb, 0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85,
|
||||
0x02, 0xdd, 0x15, 0x69, 0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c,
|
||||
0x1e, 0x1b, 0x2b, 0x8f, 0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac,
|
||||
0x53, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x1b, 0x4a, 0xf7,
|
||||
0x7b, 0x31, 0xf7, 0xe5, 0x61, 0x46, 0xd6, 0xd1, 0x86, 0x69, 0x43, 0xab,
|
||||
0x40, 0x0e, 0xb5, 0x73, 0x26, 0x88, 0x23, 0x9d, 0xd9, 0x76, 0x00, 0x91,
|
||||
0xd4, 0x85, 0x3c, 0x6f, 0x1e, 0xc0, 0x51, 0xeb, 0xe6, 0x90, 0x5b, 0x41,
|
||||
0x7f, 0xe6, 0xaa, 0x31, 0x6b, 0xac, 0x59, 0x53, 0x96, 0x26, 0xf1, 0xae,
|
||||
0xda, 0xbe, 0x55, 0xa4, 0x75, 0x40, 0x22, 0x5f, 0x27, 0x17, 0xa0, 0xd2,
|
||||
0x91, 0x02, 0x21, 0x00, 0xc8, 0xc4, 0x27, 0x7c, 0xd5, 0x61, 0xad, 0xbf,
|
||||
0x32, 0x8e, 0x1e, 0xcb, 0xe8, 0x94, 0xf4, 0x9f, 0x55, 0x77, 0xe5, 0xa8,
|
||||
0xc9, 0x70, 0xd0, 0x0f, 0x81, 0x04, 0xb7, 0x09, 0xb2, 0x1b, 0x53, 0xe9,
|
||||
0x02, 0x21, 0x00, 0xc6, 0xe6, 0x65, 0xbe, 0x10, 0xc8, 0x6d, 0xb7, 0x1e,
|
||||
0xee, 0x8e, 0x41, 0xbc, 0xe8, 0x67, 0x09, 0x9d, 0x8d, 0xee, 0x46, 0x1b,
|
||||
0xd5, 0x90, 0xb9, 0xee, 0x0d, 0xc5, 0xf9, 0xc6, 0xc9, 0xc9, 0x6f, 0x02,
|
||||
0x21, 0x00, 0x9b, 0xb0, 0x31, 0x87, 0x06, 0xda, 0x36, 0xa8, 0x9c, 0x85,
|
||||
0xc5, 0xb0, 0x0e, 0xee, 0xe4, 0x3c, 0x63, 0x45, 0x15, 0x1d, 0xad, 0x09,
|
||||
0x04, 0xef, 0xe0, 0xf7, 0x4d, 0x12, 0x01, 0xc2, 0x5b, 0x71, 0x02, 0x20,
|
||||
0x46, 0xd1, 0x25, 0x8c, 0x84, 0xa1, 0x38, 0x1f, 0x29, 0x0e, 0x3a, 0xec,
|
||||
0x40, 0xfc, 0x66, 0x23, 0x50, 0x4b, 0x86, 0x78, 0xc3, 0xd4, 0x48, 0x51,
|
||||
0x4a, 0xe6, 0xf0, 0x84, 0x3c, 0x39, 0x00, 0x55, 0x02, 0x21, 0x00, 0x8d,
|
||||
0x03, 0x6e, 0x29, 0x0e, 0xd7, 0x4e, 0x1f, 0x27, 0x70, 0xb5, 0x20, 0x79,
|
||||
0xfb, 0x31, 0x6a, 0x14, 0xb7, 0xe6, 0x55, 0x9a, 0x65, 0x40, 0xcf, 0xe0,
|
||||
0xe6, 0x46, 0xf8, 0xb2, 0x8e, 0xf4, 0x63, 0x0a
|
||||
};
|
||||
|
||||
static const unsigned int rsa_example_keypair_der_len = 320;
|
||||
|
||||
static const unsigned char rsa_example_cert_der[] = {
|
||||
0x30, 0x82, 0x02, 0x12, 0x30, 0x82, 0x01, 0x7b, 0x02, 0x02, 0x0d, 0xfa,
|
||||
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
|
||||
0x05, 0x05, 0x00, 0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06,
|
||||
0x03, 0x55, 0x04, 0x08, 0x13, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68,
|
||||
0x75, 0x6f, 0x2d, 0x6b, 0x75, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
|
||||
0x04, 0x0a, 0x13, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44,
|
||||
0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x57,
|
||||
0x65, 0x62, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x75, 0x70, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x0f, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44, 0x20, 0x57, 0x65,
|
||||
0x62, 0x20, 0x43, 0x41, 0x31, 0x23, 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x73, 0x75, 0x70,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x40, 0x66, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x64,
|
||||
0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30,
|
||||
0x38, 0x32, 0x32, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34, 0x5a, 0x17, 0x0d,
|
||||
0x31, 0x37, 0x30, 0x38, 0x32, 0x31, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34,
|
||||
0x5a, 0x30, 0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
||||
0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04,
|
||||
0x08, 0x0c, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31, 0x11, 0x30, 0x0f,
|
||||
0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b,
|
||||
0x34, 0x44, 0x44, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
|
||||
0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9b, 0xfc, 0x66, 0x90, 0x79, 0x84,
|
||||
0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8, 0xde, 0x15, 0x12, 0xe5,
|
||||
0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1, 0xe1, 0x9e, 0x26, 0xbb,
|
||||
0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85, 0x02, 0xdd, 0x15, 0x69,
|
||||
0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c, 0x1e, 0x1b, 0x2b, 0x8f,
|
||||
0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac, 0x53, 0x07, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x14, 0xb6,
|
||||
0x4c, 0xbb, 0x81, 0x79, 0x33, 0xe6, 0x71, 0xa4, 0xda, 0x51, 0x6f, 0xcb,
|
||||
0x08, 0x1d, 0x8d, 0x60, 0xec, 0xbc, 0x18, 0xc7, 0x73, 0x47, 0x59, 0xb1,
|
||||
0xf2, 0x20, 0x48, 0xbb, 0x61, 0xfa, 0xfc, 0x4d, 0xad, 0x89, 0x8d, 0xd1,
|
||||
0x21, 0xeb, 0xd5, 0xd8, 0xe5, 0xba, 0xd6, 0xa6, 0x36, 0xfd, 0x74, 0x50,
|
||||
0x83, 0xb6, 0x0f, 0xc7, 0x1d, 0xdf, 0x7d, 0xe5, 0x2e, 0x81, 0x7f, 0x45,
|
||||
0xe0, 0x9f, 0xe2, 0x3e, 0x79, 0xee, 0xd7, 0x30, 0x31, 0xc7, 0x20, 0x72,
|
||||
0xd9, 0x58, 0x2e, 0x2a, 0xfe, 0x12, 0x5a, 0x34, 0x45, 0xa1, 0x19, 0x08,
|
||||
0x7c, 0x89, 0x47, 0x5f, 0x4a, 0x95, 0xbe, 0x23, 0x21, 0x4a, 0x53, 0x72,
|
||||
0xda, 0x2a, 0x05, 0x2f, 0x2e, 0xc9, 0x70, 0xf6, 0x5b, 0xfa, 0xfd, 0xdf,
|
||||
0xb4, 0x31, 0xb2, 0xc1, 0x4a, 0x9c, 0x06, 0x25, 0x43, 0xa1, 0xe6, 0xb4,
|
||||
0x1e, 0x7f, 0x86, 0x9b, 0x16, 0x40, 0x0a
|
||||
};
|
||||
|
||||
static const unsigned int rsa_example_cert_der_len = 535;
|
||||
|
||||
#endif
|
||||
@ -1,4 +1,4 @@
|
||||
[test]
|
||||
tags = net http
|
||||
build_only = true
|
||||
platform_whitelist = frdm_k64f
|
||||
platform_whitelist = frdm_k64f qemu_x86
|
||||
|
||||
@ -6,7 +6,6 @@ CONFIG_NET_L2_IEEE802154_ORFD_CHANNEL=20
|
||||
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_IEEE802154_CC2520=y
|
||||
CONFIG_ZOAP=y
|
||||
|
||||
65
samples/net/mqtt_publisher/prj_96b_nitrogen.conf
Normal file
65
samples/net/mqtt_publisher/prj_96b_nitrogen.conf
Normal file
@ -0,0 +1,65 @@
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_NETWORKING=y
|
||||
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_UDP=n
|
||||
CONFIG_NET_ARP=y
|
||||
CONFIG_NET_L2_BLUETOOTH=y
|
||||
CONFIG_NET_L2_BLUETOOTH_SEC_LEVEL=1
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_IPV6_RA_RDNSS=y
|
||||
CONFIG_NET_IPV4=n
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
|
||||
CONFIG_NET_MAX_CONTEXTS=5
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=16
|
||||
CONFIG_NET_NBUF_TX_COUNT=16
|
||||
CONFIG_NET_NBUF_DATA_SIZE=256
|
||||
CONFIG_NET_NBUF_DATA_COUNT=30
|
||||
|
||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
|
||||
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101"
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10"
|
||||
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=3
|
||||
|
||||
CONFIG_PRINTK=y
|
||||
|
||||
CONFIG_MQTT_LIB=y
|
||||
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
|
||||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_TIMER_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_BLUETOOTH_RX_STACK_SIZE=1024
|
||||
CONFIG_BLUETOOTH_DEVICE_NAME="Zephyr"
|
||||
|
||||
CONFIG_BLUETOOTH_L2CAP_TX_BUF_COUNT=3
|
||||
CONFIG_BLUETOOTH_L2CAP_TX_MTU=65
|
||||
CONFIG_BLUETOOTH_L2CAP_TX_USER_DATA_SIZE=4
|
||||
|
||||
CONFIG_BLUETOOTH_HCI_TX_STACK_SIZE=640
|
||||
CONFIG_BLUETOOTH_HCI_HOST=y
|
||||
CONFIG_BLUETOOTH_RECV_IS_RX_THREAD=y
|
||||
CONFIG_BLUETOOTH_HCI_CMD_COUNT=2
|
||||
CONFIG_BLUETOOTH_MAX_CMD_LEN=64
|
||||
CONFIG_BLUETOOTH_RX_BUF_COUNT=20
|
||||
CONFIG_BLUETOOTH_RX_BUF_LEN=1024
|
||||
CONFIG_BLUETOOTH_CONN=y
|
||||
CONFIG_BLUETOOTH_SIGNING=y
|
||||
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
|
||||
CONFIG_BLUETOOTH_DEBUG=y
|
||||
CONFIG_BLUETOOTH_DEBUG_LOG=y
|
||||
CONFIG_BLUETOOTH_DEBUG_COLOR=y
|
||||
|
||||
CONFIG_CONSOLE_SHELL=y
|
||||
CONFIG_CONSOLE_SHELL_STACKSIZE=2000
|
||||
CONFIG_CONSOLE_SHELL_MAX_CMD_QUEUED=3
|
||||
@ -6,3 +6,7 @@
|
||||
|
||||
obj-y += main.o
|
||||
|
||||
ifeq ($(CONFIG_NET_L2_BLUETOOTH), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/
|
||||
obj-y += ../../../bluetooth/gatt/ipss.o
|
||||
endif
|
||||
|
||||
@ -14,6 +14,12 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <gatt/ipss.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
@ -334,6 +340,29 @@ int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
static bool bt_connected;
|
||||
|
||||
static
|
||||
void bt_connect_cb(struct bt_conn *conn, uint8_t err)
|
||||
{
|
||||
bt_connected = true;
|
||||
}
|
||||
|
||||
static
|
||||
void bt_disconnect_cb(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
bt_connected = false;
|
||||
printk("bt disconnected (reason %u)\n", reason);
|
||||
}
|
||||
|
||||
static
|
||||
struct bt_conn_cb bt_conn_cb = {
|
||||
.connected = bt_connect_cb,
|
||||
.disconnected = bt_disconnect_cb,
|
||||
};
|
||||
#endif
|
||||
|
||||
int network_setup(struct net_context **net_ctx, const char *local_addr,
|
||||
const char *server_addr, uint16_t server_port)
|
||||
{
|
||||
@ -345,11 +374,37 @@ int network_setup(struct net_context **net_ctx, const char *local_addr,
|
||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||
sa_family_t family = AF_INET;
|
||||
#endif
|
||||
struct sockaddr local_sock;
|
||||
struct sockaddr server_sock;
|
||||
struct sockaddr server_sock, local_sock;
|
||||
void *p;
|
||||
int rc;
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
const char *progress_mark = "/-\\|";
|
||||
int i = 0;
|
||||
|
||||
rc = bt_enable(NULL);
|
||||
if (rc) {
|
||||
printk("bluetooth init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ipss_init();
|
||||
bt_conn_cb_register(&bt_conn_cb);
|
||||
rc = ipss_advertise();
|
||||
if (rc) {
|
||||
printk("advertising failed to start\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
printk("\nwaiting for bt connection: ");
|
||||
while (bt_connected == false) {
|
||||
k_sleep(250);
|
||||
printk("%c\b", progress_mark[i]);
|
||||
i = (i + 1) % (sizeof(progress_mark) - 1);
|
||||
}
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
rc = set_addr(&local_sock, local_addr, 0);
|
||||
if (rc) {
|
||||
printk("set_addr (local) error\n");
|
||||
|
||||
@ -2,3 +2,8 @@
|
||||
tags = net mqtt
|
||||
build_only = true
|
||||
platform_whitelist = frdm_k64f
|
||||
|
||||
[test_bt]
|
||||
tags = net mqtt bluetooth
|
||||
build_only = true
|
||||
platform_whitelist = 96b_nitrogen
|
||||
|
||||
@ -12,15 +12,20 @@ some adjustments to the configuration may be needed.
|
||||
The sample will listen for requests in the CoAP UDP port (5683) in the
|
||||
site-local IPv6 multicast address reserved for CoAP nodes.
|
||||
|
||||
The exported resource, with path '/test', will just respond any GET to
|
||||
that path with the the type, code and message identification retrieved
|
||||
from the request. The response will have this format:
|
||||
The sample exports the following resources:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
Type: <type>
|
||||
Code: <code>
|
||||
MID: <message id>
|
||||
/test
|
||||
/seg1/seg2/seg3
|
||||
/query
|
||||
/separate
|
||||
/large
|
||||
/location-query
|
||||
/large-update
|
||||
|
||||
These resources allow a good part of the ETSI testcases to be run
|
||||
against zoap-server.
|
||||
|
||||
Building And Running
|
||||
********************
|
||||
@ -37,6 +42,14 @@ It can be built and executed on QEMU as follows:
|
||||
|
||||
make run
|
||||
|
||||
|
||||
Use this command on the host to run the`libcoap`_ implementation of
|
||||
the ETSI testcases:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo ./examples/etsi_coaptest.sh -i tap0 2001:db8::1
|
||||
|
||||
To build the version supporting the TI CC2520 radio, use the supplied
|
||||
configuration file enabling IEEE 802.15.4:
|
||||
|
||||
@ -44,4 +57,7 @@ configuration file enabling IEEE 802.15.4:
|
||||
|
||||
make CONF_FILE=prj_cc2520.conf run
|
||||
|
||||
|
||||
.. _`net-tools`: https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree
|
||||
|
||||
.. _`libcoap`: https://github.com/obgm/libcoap
|
||||
|
||||
@ -6,7 +6,6 @@ CONFIG_NET_L2_IEEE802154_ORFD_CHANNEL=20
|
||||
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_IEEE802154_CC2520=y
|
||||
CONFIG_ZOAP=y
|
||||
|
||||
@ -3,7 +3,6 @@ CONFIG_NET_LOG=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_DHCPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
|
||||
@ -3,7 +3,6 @@ CONFIG_NET_LOG=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
CONFIG_NET_STATISTICS=y
|
||||
|
||||
@ -120,7 +120,6 @@ net_dhcpv4_state_name(enum net_dhcpv4_state state)
|
||||
static const char * const name[] = {
|
||||
"init",
|
||||
"discover",
|
||||
"offer",
|
||||
"request",
|
||||
"renewal",
|
||||
"ack"
|
||||
@ -316,6 +315,7 @@ static void setup_header(struct net_buf *buf)
|
||||
udp->src_port = htons(DHCPV4_CLIENT_PORT);
|
||||
udp->dst_port = htons(DHCPV4_SERVER_PORT);
|
||||
udp->len = htons(len);
|
||||
udp->chksum = 0;
|
||||
udp->chksum = ~net_calc_chksum_udp(buf);
|
||||
}
|
||||
|
||||
@ -709,7 +709,7 @@ static inline void handle_dhcpv4_reply(struct net_if *iface, uint8_t msg_type)
|
||||
* Rest of the replies are discarded.
|
||||
*/
|
||||
if (iface->dhcpv4.state == NET_DHCPV4_DISCOVER) {
|
||||
if (msg_type != NET_DHCPV4_OFFER) {
|
||||
if (msg_type != DHCPV4_MSG_TYPE_OFFER) {
|
||||
NET_DBG("Reply ignored");
|
||||
return;
|
||||
}
|
||||
@ -724,7 +724,7 @@ static inline void handle_dhcpv4_reply(struct net_if *iface, uint8_t msg_type)
|
||||
iface->dhcpv4.state == NET_DHCPV4_RENEWAL) {
|
||||
uint32_t timeout;
|
||||
|
||||
if (msg_type != NET_DHCPV4_ACK) {
|
||||
if (msg_type != DHCPV4_MSG_TYPE_ACK) {
|
||||
NET_DBG("Reply ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -80,8 +80,6 @@ static inline const char *dhcpv4state2str(enum net_dhcpv4_state state)
|
||||
return "init";
|
||||
case NET_DHCPV4_DISCOVER:
|
||||
return "discover";
|
||||
case NET_DHCPV4_OFFER:
|
||||
return "offer";
|
||||
case NET_DHCPV4_REQUEST:
|
||||
return "request";
|
||||
case NET_DHCPV4_RENEWAL:
|
||||
|
||||
@ -113,16 +113,16 @@ exit_disconnect:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mqtt_tx_pub_msgs Writes the MQTT PUBxxx msg indicated by pkt_type
|
||||
* with identifier 'id'
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] id MQTT packet identifier
|
||||
* @param [in] pkt_type MQTT packet type
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed to
|
||||
* this routine
|
||||
* @return -ENOMEM if a tx buffer is not available
|
||||
* @return -EIO on network error
|
||||
* Writes the MQTT PUBxxx msg indicated by pkt_type with identifier 'id'
|
||||
*
|
||||
* @param [in] ctx MQTT context
|
||||
* @param [in] id MQTT packet identifier
|
||||
* @param [in] pkt_type MQTT packet type
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM if a tx buffer is not available
|
||||
* @retval -EIO on network error
|
||||
*/
|
||||
static
|
||||
int mqtt_tx_pub_msgs(struct mqtt_ctx *ctx, uint16_t id,
|
||||
@ -421,16 +421,19 @@ exit_connect:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mqtt_rx_pub_msgs Parses and validates the MQTT PUBxxxx message
|
||||
* contained in the rx buffer. It validates against
|
||||
* message structure and Packet Identifier.
|
||||
* @details For the MQTT PUBREC and PUBREL messages, this
|
||||
* function writes the corresponding MQTT PUB msg.
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
* @param type MQTT Packet type
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Parses and validates the MQTT PUBxxxx message contained in the rx buffer.
|
||||
*
|
||||
*
|
||||
* @details It validates against message structure and Packet Identifier.
|
||||
* For the MQTT PUBREC and PUBREL messages, this function writes the
|
||||
* corresponding MQTT PUB msg.
|
||||
*
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
* @param type MQTT Packet type
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL on error
|
||||
*/
|
||||
static
|
||||
int mqtt_rx_pub_msgs(struct mqtt_ctx *ctx, struct net_buf *rx,
|
||||
@ -626,14 +629,15 @@ int mqtt_rx_publish(struct mqtt_ctx *ctx, struct net_buf *rx)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mqtt_linearize_buffer Linearize an IP fragmented buffer
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx RX IP stack buffer
|
||||
* @param [in] min_size Min message size allowed. This allows us
|
||||
* to exit if the rx buffer is shorter
|
||||
* than the expected msg size
|
||||
* @return Data buffer
|
||||
* @return NULL on error
|
||||
* Linearizes an IP fragmented buffer
|
||||
*
|
||||
* @param [in] ctx MQTT context structure
|
||||
* @param [in] rx RX IP stack buffer
|
||||
* @param [in] min_size Min message size allowed. This allows us to exit if the
|
||||
* rx buffer is shorter than the expected msg size
|
||||
*
|
||||
* @retval Data buffer
|
||||
* @retval NULL on error
|
||||
*/
|
||||
static
|
||||
struct net_buf *mqtt_linearize_buffer(struct mqtt_ctx *ctx, struct net_buf *rx,
|
||||
@ -673,18 +677,19 @@ exit_error:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mqtt_publisher_parser Calls the appropriate rx routine for the MQTT
|
||||
* message contained in rx
|
||||
* @details On error, this routine will execute the
|
||||
* 'ctx->malformed' callback (if defined)
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an unknown message is received
|
||||
* @return -ENOMEM if no data buffer is available
|
||||
* @return mqtt_rx_connack, mqtt_rx_puback, mqtt_rx_pubrec,
|
||||
* mqtt_rx_pubcomp, and mqtt_rx_pingresp
|
||||
* return codes
|
||||
* Calls the appropriate rx routine for the MQTT message contained in rx
|
||||
*
|
||||
* @details On error, this routine will execute the 'ctx->malformed' callback
|
||||
* (if defined)
|
||||
*
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL if an unknown message is received
|
||||
* @retval -ENOMEM if no data buffer is available
|
||||
* @retval mqtt_rx_connack, mqtt_rx_puback, mqtt_rx_pubrec, mqtt_rx_pubcomp
|
||||
* and mqtt_rx_pingresp return codes
|
||||
*/
|
||||
static
|
||||
int mqtt_publisher_parser(struct mqtt_ctx *ctx, struct net_buf *rx)
|
||||
@ -738,18 +743,19 @@ exit_parser:
|
||||
|
||||
|
||||
/**
|
||||
* @brief mqtt_subscriber_parser Calls the appropriate rx routine for the MQTT
|
||||
* message contained in rx
|
||||
* @details On error, this routine will execute the
|
||||
* 'ctx->malformed' callback (if defined)
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an unknown message is received
|
||||
* @return -ENOMEM if no data buffer is available
|
||||
* @return mqtt_rx_publish, mqtt_rx_pubrel, mqtt_rx_pubrel,
|
||||
* mqtt_rx_suback
|
||||
* return codes
|
||||
* Calls the appropriate rx routine for the MQTT message contained in rx
|
||||
*
|
||||
* @details On error, this routine will execute the 'ctx->malformed' callback
|
||||
* (if defined)
|
||||
*
|
||||
* @param ctx MQTT context
|
||||
* @param rx RX buffer
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL if an unknown message is received
|
||||
* @retval -ENOMEM if no data buffer is available
|
||||
* @retval mqtt_rx_publish, mqtt_rx_pubrel, mqtt_rx_pubrel and mqtt_rx_suback
|
||||
* return codes
|
||||
*/
|
||||
static
|
||||
int mqtt_subscriber_parser(struct mqtt_ctx *ctx, struct net_buf *rx)
|
||||
|
||||
@ -50,21 +50,22 @@
|
||||
QoS_SIZE)
|
||||
|
||||
/**
|
||||
* @brief mqtt_strlen Enhanced strlen function
|
||||
* @details This function is introduced to allow developers to
|
||||
* pass null strings to functions that compute the length
|
||||
* of strings.
|
||||
* strlen returns random values for null arguments, so
|
||||
* mqtt_strlen(NULL) is quite useful when optional strings
|
||||
* are allowed by mqtt-related functions. For example:
|
||||
* username in the MQTT CONNECT message is an optional
|
||||
* parameter, so connect(..., username = NULL, ...) will
|
||||
* work fine without passing an additional parameter like:
|
||||
* connect(.., is_username_present, username, ...) or
|
||||
* connect(.., username, username_len, ...).
|
||||
* @param str C-string or NULL
|
||||
* @return 0 for NULL
|
||||
* @return strlen otherwise
|
||||
* Enhanced strlen function
|
||||
*
|
||||
* @details This function is introduced to allow developers to pass null strings
|
||||
* to functions that compute the length of strings. strlen returns random values
|
||||
* for null arguments, so mqtt_strlen(NULL) is quite useful when optional
|
||||
* strings are allowed by mqtt-related functions. For example: username in the
|
||||
* MQTT CONNECT message is an optional parameter, so
|
||||
* connect(..., username = NULL, ...) will work fine without passing an
|
||||
* additional parameter like:
|
||||
* connect(.., is_username_present, username, ...) or
|
||||
* connect(.., username, username_len, ...).
|
||||
*
|
||||
* @param str C-string or NULL
|
||||
*
|
||||
* @retval 0 for NULL
|
||||
* @retval strlen otherwise
|
||||
*/
|
||||
static inline
|
||||
uint16_t mqtt_strlen(const char *str)
|
||||
@ -77,14 +78,13 @@ uint16_t mqtt_strlen(const char *str)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief compute_rlen_size Computes the amount of bytes needed to
|
||||
* codify the value stored in len
|
||||
* @details See MQTT 2.2.3, Table 2.4
|
||||
* @param [out] size Amount of bytes required to codify the value
|
||||
* stored in len
|
||||
* @param [in] len Value to be codified
|
||||
* @return 0 on success
|
||||
* @return -EINVAL is len is out of range
|
||||
* Computes the amount of bytes needed to codify the value stored in len.
|
||||
*
|
||||
* @param [out] size Amount of bytes required to codify the value stored in len
|
||||
* @param [in] len Value to be codified
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int compute_rlen_size(uint16_t *size, uint32_t len)
|
||||
@ -105,11 +105,12 @@ int compute_rlen_size(uint16_t *size, uint32_t len)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rlen_encode Remaining Length encoding algorithm
|
||||
* @details See MQTT 2.2.3 Remaining Length
|
||||
* @param [out] buf Buffer where the encoded value will be stored
|
||||
* @param [in] len Value to encode
|
||||
* @return 0 always
|
||||
* Remaining Length encoding algorithm. See MQTT 2.2.3 Remaining Length
|
||||
*
|
||||
* @param [out] buf Buffer where the encoded value will be stored
|
||||
* @param [in] len Value to encode
|
||||
*
|
||||
* @retval 0 always
|
||||
*/
|
||||
static int rlen_encode(uint8_t *buf, int len)
|
||||
{
|
||||
@ -133,15 +134,15 @@ static int rlen_encode(uint8_t *buf, int len)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rlen_decode Remaining Length decoding algorithm
|
||||
* @details See MQTT 2.2.3 Remaining Length
|
||||
* @param [out] rlen Remaining Length (decoded)
|
||||
* @param [out] rlen_size Number of bytes required to codify rlen's value
|
||||
* @param [in] buf Buffer where the codified Remaining Length
|
||||
* is codified
|
||||
* @param [in] size Buffer size
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Remaining Length decoding algorithm. See MQTT 2.2.3 Remaining Length
|
||||
*
|
||||
* @param [out] rlen Remaining Length (decoded)
|
||||
* @param [out] rlen_size Number of bytes required to codify rlen's value
|
||||
* @param [in] buf Buffer where the codified Remaining Length is codified
|
||||
* @param [in] size Buffer size
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
static int rlen_decode(uint16_t *rlen, uint16_t *rlen_size,
|
||||
uint8_t *buf, uint16_t size)
|
||||
@ -184,23 +185,22 @@ int mqtt_pack_connack(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pack_pkt_id Packs a message that only contains the
|
||||
* Packet Identifier as payload.
|
||||
* @details Many MQTT messages only codify the packet type,
|
||||
* reserved flags and the Packet Identifier as payload,
|
||||
* so this function is used by those MQTT messages.
|
||||
* Packs a message that only contains the Packet Identifier as payload.
|
||||
*
|
||||
* The total size of this message is always 4 bytes,
|
||||
* with a payload of only 2 bytes to codify the
|
||||
* identifier.
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] type MQTT Control Packet type
|
||||
* @details Many MQTT messages only codify the packet type, reserved flags and
|
||||
* the Packet Identifier as payload, so this function is used by those MQTT
|
||||
* messages. The total size of this message is always 4 bytes, with a payload
|
||||
* of only 2 bytes to codify the identifier.
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] type MQTT Control Packet type
|
||||
* @param [in] reserved Control Packet Reserved Flags. See MQTT 2.2.2 Flags
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
static
|
||||
int pack_pkt_id(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
@ -415,15 +415,15 @@ int mqtt_pack_connect(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief recover_value_len Recovers the length and sets val to point to
|
||||
* the beginning of the value
|
||||
* @param [in] buf Buffer where the length and value are stored
|
||||
* @param [in] length Buffer's length
|
||||
* @param [out] val Pointer to the beginning of the value
|
||||
* @param [out] val_len Recovered value's length
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Recovers the length and sets val to point to the beginning of the value
|
||||
*
|
||||
* @param [in] buf Buffer where the length and value are stored
|
||||
* @param [in] length Buffer's length
|
||||
* @param [out] val Pointer to the beginning of the value
|
||||
* @param [out] val_len Recovered value's length
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int recover_value_len(uint8_t *buf, uint16_t length, uint8_t **val,
|
||||
@ -568,17 +568,18 @@ int mqtt_unpack_connect(uint8_t *buf, uint16_t length,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief subscribe_size Computes the packet size for the SUBSCRIBE
|
||||
* and UNSUBSCRIBE messages without considering
|
||||
* the packet type field size (1 byte)
|
||||
* @param rlen_size Remaining length size
|
||||
* @param payload_size SUBSCRIBE or UNSUBSCRIBE payload size
|
||||
* @param items Number of topics
|
||||
* @param topics Array of C-strings containing the topics
|
||||
* to subscribe to
|
||||
* @param with_qos 0 for UNSUBSCRIBE, != 0 for SUBSCRIBE
|
||||
* @return 0 on success
|
||||
* @return -EINVAL on error
|
||||
* Computes the packet size for the SUBSCRIBE and UNSUBSCRIBE messages
|
||||
*
|
||||
* This routine does not consider the packet type field size (1 byte)
|
||||
*
|
||||
* @param rlen_size Remaining length size
|
||||
* @param payload_size SUBSCRIBE or UNSUBSCRIBE payload size
|
||||
* @param items Number of topics
|
||||
* @param topics Array of C-strings containing the topics to subscribe to
|
||||
* @param with_qos 0 for UNSUBSCRIBE, != 0 for SUBSCRIBE
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL on error
|
||||
*/
|
||||
static
|
||||
int subscribe_size(uint16_t *rlen_size, uint16_t *payload_size, uint8_t items,
|
||||
@ -607,19 +608,18 @@ int subscribe_size(uint16_t *rlen_size, uint16_t *payload_size, uint8_t items,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_subscribe_unsubscribe
|
||||
* @details Packs the SUBSCRIBE and UNSUBSCRIBE messages
|
||||
* @param buf Buffer where the message will be stored
|
||||
* @param pkt_id Packet Identifier
|
||||
* @param items Number of topics
|
||||
* @param topics Array of C-strings containing the topics
|
||||
* to subscribe to
|
||||
* @param qos Array of QoS' values, qos[i] is the QoS of topic[i]
|
||||
* @param type MQTT_SUBSCRIBE or MQTT_UNSUBSCRIBE
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if invalid parameters were passed as arguments
|
||||
* @return -ENOMEM if buf has no enough space to store the
|
||||
* resultant message
|
||||
* Packs the SUBSCRIBE and UNSUBSCRIBE messages
|
||||
*
|
||||
* @param buf Buffer where the message will be stored
|
||||
* @param pkt_id Packet Identifier
|
||||
* @param items Number of topics
|
||||
* @param topics Array of C-strings containing the topics to subscribe to
|
||||
* @param qos Array of QoS' values, qos[i] is the QoS of topic[i]
|
||||
* @param type MQTT_SUBSCRIBE or MQTT_UNSUBSCRIBE
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
static int mqtt_pack_subscribe_unsubscribe(uint8_t *buf, uint16_t *length,
|
||||
uint16_t size, uint16_t pkt_id,
|
||||
@ -969,19 +969,20 @@ int mqtt_unpack_connack(uint8_t *buf, uint16_t length, uint8_t *session,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pack_zerolen Packs a zero length message
|
||||
* @details This function packs MQTT messages with no
|
||||
* payload. No validations are made about the
|
||||
* input arguments, besides 'size' that must be
|
||||
* at least 2 bytes
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_type MQTT Control Packet Type. See MQTT 2.2.1
|
||||
* @param [in] reserved Reserved bits. See MQTT 2.2
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if buf has no enough reserved space
|
||||
* to store the resultant message
|
||||
* Packs a zero length message
|
||||
*
|
||||
* @details This function packs MQTT messages with no payload. No validations
|
||||
* are made about the input arguments, besides 'size' that must be at least
|
||||
* 2 bytes
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_type MQTT Control Packet Type. See MQTT 2.2.1
|
||||
* @param [in] reserved Reserved bits. See MQTT 2.2
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
static
|
||||
int pack_zerolen(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
@ -1014,16 +1015,16 @@ int mqtt_pack_disconnect(uint8_t *buf, uint16_t *length, uint16_t size)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unpack_pktid Unpacks a MQTT message with a Packet Id
|
||||
* as payload
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] type MQTT Control Packet type
|
||||
* @param [out] reserved Reserved flags
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks a MQTT message with a Packet Id as payload
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] type MQTT Control Packet type
|
||||
* @param [out] reserved Reserved flags
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int unpack_pktid(uint8_t *buf, uint16_t length, enum mqtt_packet *type,
|
||||
@ -1045,26 +1046,22 @@ int unpack_pktid(uint8_t *buf, uint16_t length, enum mqtt_packet *type,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unpack_pktid_validate Unpacks and validates a MQTT message
|
||||
* containing a Packet Identifier
|
||||
* @details The message codified in buf must contain a
|
||||
* 1) packet type, 2) reserved flags and
|
||||
* 3) packet identifier.
|
||||
* The user must provide the expected packet type
|
||||
* and expected reserved flags.
|
||||
* See MQTT 2.2.2 Flags.
|
||||
* If the message contains different values for
|
||||
* type and reserved flags than the ones passed as
|
||||
* arguments, the function will return -EINVAL
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @param [in] expected_type Expected MQTT Control Packet type
|
||||
* @param [in] expected_reserv Expected Reserved Flags
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* any test failed
|
||||
* Unpacks and validates a MQTT message containing a Packet Identifier
|
||||
*
|
||||
* @details The message codified in buf must contain a 1) packet type,
|
||||
* 2) reserved flags and 3) packet identifier. The user must provide the
|
||||
* expected packet type and expected reserved flags. See MQTT 2.2.2 Flags.
|
||||
* If the message contains different values for type and reserved flags
|
||||
* than the ones passed as arguments, the function will return -EINVAL
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @param [in] expected_type Expected MQTT Control Packet type
|
||||
* @param [in] expected_reserv Expected Reserved Flags
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int unpack_pktid_validate(uint8_t *buf, uint16_t length, uint16_t *pkt_id,
|
||||
@ -1117,14 +1114,15 @@ int mqtt_unpack_unsuback(uint8_t *buf, uint16_t length, uint16_t *pkt_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unpack_zerolen Unpacks a zero-length MQTT message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_type MQTT Control Packet type
|
||||
* @param [out] reserved Reserved flags
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks a zero-length MQTT message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_type MQTT Control Packet type
|
||||
* @param [out] reserved Reserved flags
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int unpack_zerolen(uint8_t *buf, uint16_t length, enum mqtt_packet *pkt_type,
|
||||
@ -1145,14 +1143,15 @@ int unpack_zerolen(uint8_t *buf, uint16_t length, enum mqtt_packet *pkt_type,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unpack_zerolen_validate Unpacks and validates a zero-len MQTT message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param expected_type Expected MQTT Control Packet type
|
||||
* @param expected_reserved Expected Reserved Flags
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks and validates a zero-len MQTT message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param expected_type Expected MQTT Control Packet type
|
||||
* @param expected_reserved Expected Reserved Flags
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
static
|
||||
int unpack_zerolen_validate(uint8_t *buf, uint16_t length,
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
* @brief MQTT v3.1.1 packet library, see:
|
||||
* http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
|
||||
*
|
||||
* This file is part of the Zephyr Project
|
||||
* http://www.zephyrproject.org
|
||||
* This file is part of the Zephyr Project
|
||||
* http://www.zephyrproject.org
|
||||
*/
|
||||
|
||||
#ifndef _MQTT_PKT_H_
|
||||
@ -25,368 +25,383 @@
|
||||
#define MQTT_PACKET_TYPE(first_byte) (((first_byte) & 0xF0) >> 4)
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_connack Packs the MQTT CONNACK message
|
||||
* @details See MQTT 3.2 CONNACK - Acknowledge connection
|
||||
* request
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] session_present Session Present parameter (0 for clean session)
|
||||
* @param [in] ret_code Connect return code. See MQTT 3.2.2.3
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT CONNACK message. See MQTT 3.2 CONNACK - Acknowledge
|
||||
* connection request
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] session_present Session Present parameter (0 for clean session)
|
||||
* @param [in] ret_code Connect return code. See MQTT 3.2.2.3
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_connack(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint8_t session_present, uint8_t ret_code);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_puback Packs the MQTT PUBACK message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet
|
||||
* Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT PUBACK message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_puback(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_pubrec Packs the MQTT PUBREC message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet
|
||||
* Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT PUBREC message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_pubrec(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_puback Packs the MQTT PUBREL message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet
|
||||
* Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT PUBREL message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_pubrel(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_pubcomp Packs the MQTT PUBCOMP message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet
|
||||
* Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT PUBCOMP message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_pubcomp(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_suback Packs the MQTT SUBACK message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] elements Number of elements in the granted_qos array
|
||||
* @param [in] granted_qos Array where the QoS values are stored
|
||||
* See MQTT 3.9 SUBACK, 3.9.3 Payload
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT SUBACK message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] elements Number of elements in the granted_qos array
|
||||
* @param [in] granted_qos Array where the QoS values are stored
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_suback(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id, uint8_t elements,
|
||||
enum mqtt_qos granted_qos[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_connect Packs the MQTT CONNECT message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] msg MQTT CONNECT msg
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT CONNECT message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] msg MQTT CONNECT msg
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_connect(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
struct mqtt_connect_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_connect Unpacks the MQTT CONNECT message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length MQTT CONNECT message's length
|
||||
* @param [out] msg MQTT CONNECT parameters
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT CONNECT message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length MQTT CONNECT message's length
|
||||
* @param [out] msg MQTT CONNECT parameters
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_connect(uint8_t *buf, uint16_t length,
|
||||
struct mqtt_connect_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_subscribe Packs the MQTT SUBSCRIBE message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] items Number of elements in topics
|
||||
* @param [in] topics Array of topics.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
* @param [in] qos Array of QoS values per topic. For example:
|
||||
{MQTT_QoS1, MQTT_QoS2, MQTT_QoS0}
|
||||
NOTE: qos and topics must have the same
|
||||
cardinality (# of items)
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT SUBSCRIBE message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] items Number of elements in topics
|
||||
* @param [in] topics Array of topics.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
* @param [in] qos Array of QoS values per topic.
|
||||
* For example: {MQTT_QoS1, MQTT_QoS2, MQTT_QoS0}
|
||||
* NOTE: qos and topics must have the same cardinality
|
||||
* (# of items)
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_subscribe(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id, uint8_t items, const char *topics[],
|
||||
const enum mqtt_qos qos[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_unsubscribe Packs the MQTT UNSUBSCRIBE message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] items Number of elements in topics
|
||||
* @param [in] topics Array of topics.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT UNSUBSCRIBE message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [in] items Number of elements in topics
|
||||
* @param [in] topics Array of topics.
|
||||
* For example: {"sensors", "lights", "doors"}
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_unsubscribe(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id, uint8_t items, const char *topics[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_subscribe Unpacks the MQTT SUBSCRIBE message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [out] items Number of recovered topics
|
||||
* @param [in] elements Max number of topics to recover from buf
|
||||
* @param [out] topics Array of topics. Each element in this array
|
||||
* points to the beginning of a topic in buf
|
||||
* @param [out] topic_len Array of topics' length. Each element in this
|
||||
* array contains the length of the
|
||||
* @param [out] qos Array of QoS,
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT SUBSCRIBE message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [out] items Number of recovered topics
|
||||
* @param [in] elements Max number of topics to recover from buf
|
||||
* @param [out] topics Array of topics. Each element in this array points to
|
||||
* the beginning of a topic in buf
|
||||
* @param [out] topic_len Array containing the length of each topic in topics
|
||||
* @param [out] qos Array of QoS values
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_subscribe(uint8_t *buf, uint16_t length, uint16_t *pkt_id,
|
||||
uint8_t *items, uint8_t elements, char *topics[],
|
||||
uint16_t topic_len[], enum mqtt_qos qos[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_suback Unpacks the MQTT SUBACK message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [out] items Number of recovered topics
|
||||
* @param [in] elements Max number of topics to recover from buf
|
||||
* @param [out] granted_qos Granted QoS values per topic. See MQTT 3.9
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT SUBACK message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1
|
||||
* @param [out] items Number of recovered topics
|
||||
* @param [in] elements Max number of topics to recover from buf
|
||||
* @param [out] granted_qos Granted QoS values per topic. See MQTT 3.9
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_suback(uint8_t *buf, uint16_t length, uint16_t *pkt_id,
|
||||
uint8_t *items, uint8_t elements,
|
||||
enum mqtt_qos granted_qos[]);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_publish Packs the MQTT PUBLISH message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] msg MQTT PUBLISH message
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT PUBLISH message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] msg MQTT PUBLISH message
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_publish(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
struct mqtt_publish_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_publish Unpacks the MQTT PUBLISH message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] msg MQTT PUBLISH message
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT PUBLISH message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] msg MQTT PUBLISH message
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_publish(uint8_t *buf, uint16_t length,
|
||||
struct mqtt_publish_msg *msg);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_connack Unpacks the MQTT CONNACK message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] session Session Present. See MQTT 3.2.2.2
|
||||
* @param [out] connect_rc CONNECT return code. See MQTT 3.2.2.3
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT CONNACK message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] session Session Present. See MQTT 3.2.2.2
|
||||
* @param [out] connect_rc CONNECT return code. See MQTT 3.2.2.3
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_connack(uint8_t *buf, uint16_t length, uint8_t *session,
|
||||
uint8_t *connect_rc);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_pingreq Packs the MQTT PINGREQ message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT PINGREQ message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_pingreq(uint8_t *buf, uint16_t *length, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_pingresp Packs the MQTT PINGRESP message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT PINGRESP message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_pingresp(uint8_t *buf, uint16_t *length, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_disconnect Packs the MQTT DISCONNECT message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if buf does not have enough reserved
|
||||
* space to store the resultant message
|
||||
* Packs the MQTT DISCONNECT message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM
|
||||
*/
|
||||
int mqtt_pack_disconnect(uint8_t *buf, uint16_t *length, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief mqtt_pack_unsuback Packs the MQTT UNSUBACK message
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer's size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet
|
||||
* Identifier
|
||||
* @return 0 on success
|
||||
* @return -ENOMEM if size < 4
|
||||
* Packs the MQTT UNSUBACK message
|
||||
*
|
||||
* @param [out] buf Buffer where the resultant message is stored
|
||||
* @param [out] length Number of bytes required to codify the message
|
||||
* @param [in] size Buffer size
|
||||
* @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOMEM if size < 4
|
||||
*/
|
||||
int mqtt_pack_unsuback(uint8_t *buf, uint16_t *length, uint16_t size,
|
||||
uint16_t pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_puback Unpacks the MQTT PUBACK message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* buf does not contain the desired msg
|
||||
* Unpacks the MQTT PUBACK message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_puback(uint8_t *buf, uint16_t length, uint16_t *pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_pubrec Unpacks the MQTT PUBREC message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* buf does not contain the desired msg
|
||||
* Unpacks the MQTT PUBREC message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_pubrec(uint8_t *buf, uint16_t length, uint16_t *pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_pubrel Unpacks the MQTT PUBREL message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* buf does not contain the desired msg
|
||||
* Unpacks the MQTT PUBREL message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_pubrel(uint8_t *buf, uint16_t length, uint16_t *pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_pubcomp Unpacks the MQTT PUBCOMP message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* buf does not contain the desired msg
|
||||
* Unpacks the MQTT PUBCOMP message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_pubcomp(uint8_t *buf, uint16_t length, uint16_t *pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_unsuback Unpacks the MQTT UNSUBACK message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine or if
|
||||
* buf does not contain the desired msg
|
||||
* Unpacks the MQTT UNSUBACK message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @param [out] pkt_id Packet Identifier
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_unsuback(uint8_t *buf, uint16_t length, uint16_t *pkt_id);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_pingreq Unpacks the MQTT PINGREQ message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT PINGREQ message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_pingreq(uint8_t *buf, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_pingresp Unpacks the MQTT PINGRESP message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT PINGRESP message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_pingresp(uint8_t *buf, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief mqtt_unpack_disconnect Unpacks the MQTT DISCONNECT message
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if an invalid parameter was passed
|
||||
* as an argument to this routine
|
||||
* Unpacks the MQTT DISCONNECT message
|
||||
*
|
||||
* @param [in] buf Buffer where the message is stored
|
||||
* @param [in] length Message's length
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL
|
||||
*/
|
||||
int mqtt_unpack_disconnect(uint8_t *buf, uint16_t length);
|
||||
|
||||
|
||||
@ -548,7 +548,7 @@ static zoap_method_t method_from_code(const struct zoap_resource *resource,
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_request(struct zoap_packet *pkt)
|
||||
static bool is_request(const struct zoap_packet *pkt)
|
||||
{
|
||||
uint8_t code = zoap_header_get_code(pkt);
|
||||
|
||||
@ -1210,15 +1210,16 @@ struct block_transfer {
|
||||
bool more;
|
||||
};
|
||||
|
||||
static unsigned int get_block_option(struct zoap_packet *pkt, uint16_t code)
|
||||
static int get_block_option(const struct zoap_packet *pkt, uint16_t code)
|
||||
{
|
||||
struct zoap_option option;
|
||||
unsigned int val;
|
||||
int count = 1;
|
||||
|
||||
count = zoap_find_options(pkt, code, &option, count);
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
if (count <= 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
val = zoap_option_value_to_int(&option);
|
||||
|
||||
@ -1230,15 +1231,15 @@ static int update_descriptive_block(struct zoap_block_context *ctx,
|
||||
{
|
||||
size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
|
||||
|
||||
if (block == 0) {
|
||||
return -ENOENT;
|
||||
if (block == -ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size && ctx->total_size && ctx->total_size != size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->block_size > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) {
|
||||
if (ctx->current > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1250,7 +1251,7 @@ static int update_descriptive_block(struct zoap_block_context *ctx,
|
||||
ctx->total_size = size;
|
||||
}
|
||||
ctx->current = new_current;
|
||||
ctx->block_size = GET_BLOCK_SIZE(block);
|
||||
ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1260,7 +1261,7 @@ static int update_control_block1(struct zoap_block_context *ctx,
|
||||
{
|
||||
size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
|
||||
|
||||
if (block == 0) {
|
||||
if (block == -ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1283,7 +1284,7 @@ static int update_control_block2(struct zoap_block_context *ctx,
|
||||
{
|
||||
size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
|
||||
|
||||
if (block == 0) {
|
||||
if (block == -ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1296,23 +1297,24 @@ static int update_control_block2(struct zoap_block_context *ctx,
|
||||
}
|
||||
|
||||
ctx->current = new_current;
|
||||
ctx->block_size = GET_BLOCK_SIZE(block);
|
||||
ctx->total_size = size;
|
||||
ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zoap_update_from_block(struct zoap_packet *pkt,
|
||||
int zoap_update_from_block(const struct zoap_packet *pkt,
|
||||
struct zoap_block_context *ctx)
|
||||
{
|
||||
unsigned int block1, block2, size1, size2;
|
||||
int r;
|
||||
int r, block1, block2, size1, size2;
|
||||
|
||||
block1 = get_block_option(pkt, ZOAP_OPTION_BLOCK1);
|
||||
block2 = get_block_option(pkt, ZOAP_OPTION_BLOCK2);
|
||||
size1 = get_block_option(pkt, ZOAP_OPTION_SIZE1);
|
||||
size2 = get_block_option(pkt, ZOAP_OPTION_SIZE2);
|
||||
|
||||
size1 = size1 == -ENOENT ? 0 : size1;
|
||||
size2 = size2 == -ENOENT ? 0 : size2;
|
||||
|
||||
if (is_request(pkt)) {
|
||||
r = update_control_block2(ctx, block2, size2);
|
||||
if (r) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user