Skip to content

Commit

Permalink
examples: add POSIX socket example
Browse files Browse the repository at this point in the history
  • Loading branch information
miri64 committed Sep 15, 2015
1 parent b97c747 commit 647a0af
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 0 deletions.
42 changes: 42 additions & 0 deletions examples/posix_sockets/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# name of your application
APPLICATION = posix_sockets

# If no BOARD is found in the environment, use this default:
BOARD ?= native

# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..

# TODO: select stack according to size of available memory (or by user?)

BOARD_INSUFFICIENT_MEMORY := airfy-beacon chronos msb-430 msb-430h nrf51dongle \
nrf6310 nucleo-f334 pca10000 pca10005 \
stm32f0discovery telosb wsn430-v1_3b wsn430-v1_4 \
yunjia-nrf51822 z1

BOARD_BLACKLIST := arduino-mega2560 spark-core
# arduino-mega2560: unknown error types (e.g. -EBADMSG)

# Include packages that pull up and auto-init the link layer.
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
USEMODULE += gnrc_netif_default
USEMODULE += auto_init_gnrc_netif
# Specify the mandatory networking modules for socket communication via UDP
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_udp
USEMODULE += gnrc_conn_udp
USEMODULE += posix_sockets
# Add also the shell, some shell commands
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps

# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
CFLAGS += -DDEVELHELP

# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

include $(RIOTBASE)/Makefile.include
58 changes: 58 additions & 0 deletions examples/posix_sockets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
examples/posix_sockets
======================
This application is a showcase for RIOT's POSIX socket support. To
keep things simple this application has only one-hop support and
no routing capabilities.

Usage
=====

Build, flash and start the application:
```
export BOARD=your_board
make
make flash
make term
```

The `term` make target starts a terminal emulator for your board. It
connects to a default port so you can interact with the shell, usually
that is `/dev/ttyUSB0`. If your port is named differently, the
`PORT=/dev/yourport` variable can be used to override this.


Example output
==============

The shell commands come with online help. Call `help` to see which commands
exist and what they do.

Running the `help` command on an iotlab-m3:
```
2014-05-06 13:14:38,508 - INFO # > help
```

Running the `ps` command on an iotlab-m3:

```
2014-05-09 17:38:33,388 - INFO # > ps
```

Start a UDP server:

```
> udp server start <port>
```

Stop a UDP server:

```
> udp server start <port>
```


Send a UDP package:

```
> udp send <ip_addr> <port> <content>
```
144 changes: 144 additions & 0 deletions examples/posix_sockets/udp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup examples
* @{
*
* @file
* @brief Demonstrating the sending and receiving of UDP data over POSIX sockets.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*
* @}
*/

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

static int server_socket = 0;

static void udp_send(char *addr_str, char *port_str, char *data, unsigned int num,
unsigned int delay)
{
struct sockaddr_in6 dst;
size_t data_len = strlen(data);
uint16_t port;
int s;
/* parse destination address */
if (inet_pton(AF_INET6, addr_str, &dst.sin6_addr) != 1) {
puts("Error: unable to parse destination address");
return;
}
/* parse port */
port = (uint16_t)atoi(port_str);
dst.sin6_port = htons(port);
s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
for (unsigned int i = 0; i < num; i++) {
sendto(s, data, data_len, 0, (struct sockaddr *)&dst, sizeof(dst));
printf("Success: send %u byte to %s:%u\n", (unsigned)data_len, addr_str, port);
usleep(delay);
}
close(s);
}

static void udp_start_server(char *port_str)
{
struct sockaddr_in6 dst;
size_t data_len = strlen(data);
uint16_t port;

/* check if server is already running */
if (server_socket != 0) {
puts("Error: server already running");
return;
}
/* parse port */
port = (uint16_t)atoi(port_str);
if (port == 0) {
puts("Error: invalid port specified");
return;
}
memset(&dst.sin6_addr, 0, sizeof(dst.sin6_addr));
dst.sin6_port = htons(port);
/* start server (which means registering pktdump for the chosen port) */
server_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
/* TODO: start server thread, if not running */
printf("Success: started UDP server on port %" PRIu16 "\n", port);
}

static void udp_stop_server(void)
{
/* check if server is running at all */
if (server_socket == 0) {
printf("Error: server was not running\n");
return;
}
/* stop server */
/* TODO: send stop command to server thread */
close(server_socket);
server_socket = 0;
puts("Success: stopped UDP server");
}

int udp_cmd(int argc, char **argv)
{
if (argc < 2) {
printf("usage: %s [send|server]\n", argv[0]);
return 1;
}

if (strcmp(argv[1], "send") == 0) {
uint32_t num = 1;
uint32_t delay = 1000000;
if (argc < 5) {
printf("usage: %s send <addr> <port> <data> [<num> [<delay in us>]]\n",
argv[0]);
return 1;
}
if (argc > 5) {
num = (uint32_t)atoi(argv[5]);
}
if (argc > 6) {
delay = (uint32_t)atoi(argv[6]);
}
udp_send(argv[2], argv[3], argv[4], num, delay);
}
else if (strcmp(argv[1], "server") == 0) {
if (argc < 3) {
printf("usage: %s server [start|stop]\n", argv[0]);
return 1;
}
if (strcmp(argv[2], "start") == 0) {
if (argc < 4) {
printf("usage %s server start <port>\n", argv[0]);
return 1;
}
udp_start_server(argv[3]);
}
else if (strcmp(argv[2], "stop") == 0) {
udp_stop_server();
}
else {
puts("error: invalid command");
}
}
else {
puts("error: invalid command");
}
return 0;
}

/** @} */

0 comments on commit 647a0af

Please sign in to comment.