zephyr/samples/net/echo_server/src/echo-server.c
Jukka Rissanen 2dab1d7371 net: apps: Ignore multicast context get fails in echo-server
The echo-server should work just fine even if the multicast
context cannot be get. By default there are only two contexts
so the multicast would fail always anyway and the program
would not run properly.

Change-Id: Ia9737cbda4a933a208aae020f055f0b6062b4f47
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
2016-05-27 06:15:22 +00:00

317 lines
7.4 KiB
C

/* echo.c - Networking echo server */
/*
* Copyright (c) 2015 Intel Corporation.
*
* 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.
*/
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else
#include <misc/printk.h>
#define PRINT printk
#endif
#include <zephyr.h>
#include <sections.h>
#include <errno.h>
#include <net/ip_buf.h>
#include <net/net_core.h>
#include <net/net_socket.h>
#include <bluetooth/bluetooth.h>
#include <gatt/ipss.h>
#if defined(CONFIG_NET_TESTING)
#include <net_testing.h>
#else
#if defined(CONFIG_NETWORKING_WITH_IPV6)
#include <contiki/ipv6/uip-ds6.h>
#else
#include <contiki/ip/uipaddr.h>
#endif /* IPv6 */
#endif /* CONFIG_NET_TESTING */
#if defined(CONFIG_NETWORKING_WITH_IPV6)
/* admin-local, dynamically allocated multicast address */
#define MCAST_IPADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
/* Define my IP address where to expect messages */
#if !defined(CONFIG_NET_TESTING)
#define MY_IPADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }
#define MY_PREFIX_LEN 64
#endif
#if defined(CONFIG_NET_TESTING)
static const struct in6_addr in6addr_my = IN6ADDR_ANY_INIT;
#else
static const struct in6_addr in6addr_my = MY_IPADDR;
#endif
#else /* IPv6 */
/* Organization-local 239.192.0.0/14 */
#define MCAST_IPADDR { { { 239, 192, 0, 2 } } }
#if !defined(CONFIG_NET_TESTING)
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
#define UIP_IPADDR0 192
#define UIP_IPADDR1 0
#define UIP_IPADDR2 2
#define UIP_IPADDR3 1
#define UIP_DRIPADDR0 UIP_IPADDR0
#define UIP_DRIPADDR1 UIP_IPADDR1
#define UIP_DRIPADDR2 UIP_IPADDR2
#define UIP_DRIPADDR3 42
#define MY_IPADDR { { { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, UIP_IPADDR3 } } }
uip_ipaddr_t uip_hostaddr = { { UIP_IPADDR0, UIP_IPADDR1,
UIP_IPADDR2, UIP_IPADDR3 } };
uip_ipaddr_t uip_draddr = { { UIP_DRIPADDR0, UIP_DRIPADDR1,
UIP_DRIPADDR2, UIP_DRIPADDR3 } };
uip_ipaddr_t uip_netmask = { { 255, 255, 255, 0 } };
#endif /* CONFIG_NET_TESTING */
#endif /* IPv6 */
#define MY_PORT 4242
static inline void init_app(void)
{
PRINT("%s: run echo server\n", __func__);
#if defined(CONFIG_NET_TESTING)
net_testing_setup();
#else
#if defined(CONFIG_NETWORKING_WITH_IPV6)
uip_ds6_prefix_add((uip_ipaddr_t *)&in6addr_my, MY_PREFIX_LEN, 0);
#endif
#endif
}
static inline void reverse(unsigned char *buf, int len)
{
int i, last = len - 1;
for (i = 0; i < len / 2; i++) {
unsigned char tmp = buf[i];
buf[i] = buf[last - i];
buf[last - i] = tmp;
}
}
static inline struct net_buf *prepare_reply(const char *name,
const char *type,
struct net_buf *buf,
int proto)
{
PRINT("%s: %sreceived %d bytes data\n", name, type,
ip_buf_appdatalen(buf));
if (proto != IPPROTO_TCP) {
/* In this test we reverse the received bytes.
* We could just pass the data back as is but
* this way it is possible to see how the app
* can manipulate the received data.
*/
reverse(ip_buf_appdata(buf), ip_buf_appdatalen(buf));
}
#if defined(CONFIG_NET_TESTING)
net_testing_set_reply_address(buf);
#endif
return buf;
}
/* How many tics to wait for a network packet */
#if 1
#define WAIT_TIME 0
#define WAIT_TICKS (WAIT_TIME * sys_clock_ticks_per_sec / 10)
#else
#define WAIT_TICKS TICKS_UNLIMITED
#endif
struct nano_fifo *net_context_get_queue(struct net_context *context);
static inline void receive_and_reply(const char *name,
struct net_context *udp_recv,
struct net_context *tcp_recv,
struct net_context *mcast_recv)
{
struct net_buf *buf;
buf = net_receive(udp_recv, WAIT_TICKS);
if (buf) {
prepare_reply(name, "unicast ", buf, IPPROTO_UDP);
if (net_reply(udp_recv, buf)) {
ip_buf_unref(buf);
}
return;
}
buf = net_receive(mcast_recv, WAIT_TICKS);
if (buf) {
prepare_reply(name, "multicast ", buf, IPPROTO_UDP);
if (net_reply(mcast_recv, buf)) {
ip_buf_unref(buf);
}
return;
}
#if defined(CONFIG_NETWORKING_WITH_TCP)
if (tcp_recv) {
static struct net_buf *tcpbuf;
if (tcpbuf) {
int ret;
reply:
ret = net_reply(tcp_recv, tcpbuf);
if (ret && ret != -EAGAIN) {
ip_buf_unref(tcpbuf);
tcpbuf = NULL;
} else if (!ret) {
tcpbuf = NULL;
} else {
PRINT("Retrying to send packet %p\n", tcpbuf);
}
} else {
tcpbuf = net_receive(tcp_recv, WAIT_TICKS);
if (tcpbuf) {
PRINT("Received packet %p len %d\n",
tcpbuf, ip_buf_appdatalen(tcpbuf));
prepare_reply(name, "tcp ", tcpbuf, IPPROTO_TCP);
goto reply;
}
}
}
#endif
fiber_sleep(50);
}
static inline bool get_context(struct net_context **udp_recv,
struct net_context **tcp_recv,
struct net_context **mcast_recv)
{
static struct net_addr mcast_addr;
static struct net_addr any_addr;
static struct net_addr my_addr;
#if defined(CONFIG_NETWORKING_WITH_IPV6)
static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
static const struct in6_addr in6addr_mcast = MCAST_IPADDR;
mcast_addr.in6_addr = in6addr_mcast;
mcast_addr.family = AF_INET6;
any_addr.in6_addr = in6addr_any;
any_addr.family = AF_INET6;
my_addr.in6_addr = in6addr_my;
my_addr.family = AF_INET6;
#else
static const struct in_addr in4addr_any = { { { 0 } } };
static struct in_addr in4addr_my = MY_IPADDR;
static struct in_addr in4addr_mcast = MCAST_IPADDR;
mcast_addr.in_addr = in4addr_mcast;
mcast_addr.family = AF_INET;
any_addr.in_addr = in4addr_any;
any_addr.family = AF_INET;
my_addr.in_addr = in4addr_my;
my_addr.family = AF_INET;
#endif
*udp_recv = net_context_get(IPPROTO_UDP,
&any_addr, 0,
&my_addr, MY_PORT);
if (!*udp_recv) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
#if defined(CONFIG_NETWORKING_WITH_TCP)
if (tcp_recv) {
*tcp_recv = net_context_get(IPPROTO_TCP,
&any_addr, 0,
&my_addr, MY_PORT);
if (!*tcp_recv) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
}
#endif
*mcast_recv = net_context_get(IPPROTO_UDP,
&any_addr, 0,
&mcast_addr, MY_PORT);
if (!*mcast_recv) {
PRINT("%s: Cannot get receiving mcast network context\n",
__func__);
}
return true;
}
#if defined(CONFIG_NANOKERNEL)
#define STACKSIZE 2000
char __noinit __stack fiberStack[STACKSIZE];
#endif
void receive(void)
{
static struct net_context *udp_recv, *tcp_recv;
static struct net_context *mcast_recv;
if (!get_context(&udp_recv, &tcp_recv, &mcast_recv)) {
PRINT("%s: Cannot get network contexts\n", __func__);
return;
}
while (1) {
receive_and_reply(__func__, udp_recv, tcp_recv, mcast_recv);
}
}
void main(void)
{
net_init();
init_app();
#if defined(CONFIG_NETWORKING_WITH_BT)
if (bt_enable(NULL)) {
PRINT("Bluetooth init failed\n");
return;
}
ipss_init();
ipss_advertise();
#endif
#if defined(CONFIG_MICROKERNEL)
receive();
#else
task_fiber_start (&fiberStack[0], STACKSIZE,
(nano_fiber_entry_t)receive, 0, 0, 7, 0);
#endif
}