mirror of
https://github.com/Dasharo/zephyr.git
synced 2026-03-06 14:57:20 -08:00
Merge "Merge net branch into master"
This commit is contained in:
@@ -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,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user