Merge "Merge net branch into master"

This commit is contained in:
Anas Nashif
2017-02-14 11:08:14 +00:00
38 changed files with 2506 additions and 854 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View 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 */

View File

@@ -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

View 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
*/

View File

@@ -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"

View 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"

View 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"

View File

@@ -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.

View 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"

View File

@@ -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

View File

@@ -25,4 +25,8 @@
#define APP_SLEEP_MSECS 500
#ifdef CONFIG_MBEDTLS
#define SERVER_PORT 443
#endif
#endif

View File

@@ -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

View File

@@ -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

View 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);
}

View File

@@ -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;
}

View 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