Skip to content

Commit

Permalink
emb6: add conn_udp wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
miri64 committed Feb 7, 2016
1 parent a0c703f commit 6c713a2
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ ifneq (,$(filter posix_semaphore,$(USEMODULE)))
USEMODULE += xtimer
endif

ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
USEMODULE += emb6_sock
endif

ifneq (,$(filter emb6_%,$(USEMODULE)))
USEMODULE += emb6
endif
Expand Down
4 changes: 4 additions & 0 deletions pkg/emb6/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ ifneq (,$(filter emb6_contrib,$(USEMODULE)))
DIRS += $(EMB6_CONTRIB)
endif

ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
DIRS += $(EMB6_CONTRIB)/conn/udp
endif

ifneq (,$(filter emb6_ipv6,$(USEMODULE)))
DIRS += $(EMB6_DIR)/emb6/src/net/ipv6
USEMODULE_INCLUDES += $(EMB6_DIR)/emb6/inc/net/ipv6
Expand Down
3 changes: 3 additions & 0 deletions pkg/emb6/contrib/conn/udp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = emb6_conn_udp

include $(RIOTBASE)/Makefile.base
193 changes: 193 additions & 0 deletions pkg/emb6/contrib/conn/udp/emb6_conn_udp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* 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.
*/

/**
* @{
*
* @file
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/

#include <assert.h>
#include <errno.h>

#include "msg.h"
#include "net/af.h"
#include "net/conn/udp.h"
#include "net/ipv6/hdr.h"
#include "sched.h"
#include "uip.h"

#define _MSG_TYPE_CLOSE (0x4123)
#define _MSG_TYPE_RCV (0x4124)

static void _input_callback(struct udp_socket *c, void *ptr,
const uip_ipaddr_t *src_addr, uint16_t src_port,
const uip_ipaddr_t *dst_addr, uint16_t dst_port,
const uint8_t *data, uint16_t datalen);

static int _reg_and_bind(struct udp_socket *c, void *ptr,
udp_socket_input_callback_t cb, uint16_t port)
{
if (udp_socket_register(c, ptr, cb) < 0) {
return -EMFILE;
}
if (udp_socket_bind(c, port) < 0) {
return -EALREADY;
}
return 0;
}

int conn_udp_create(conn_udp_t *conn, const void *addr, size_t addr_len,
int family, uint16_t port)
{
int res;

(void)addr;
(void)addr_len;
if (family != AF_INET6) {
return -EAFNOSUPPORT;
}
if (conn->sock.input_callback != NULL) {
return -EINVAL;
}
mutex_init(&conn->mutex);
mutex_lock(&conn->mutex);
if ((res = _reg_and_bind(&conn->sock, conn, _input_callback, port)) < 0) {
mutex_unlock(&conn->mutex);
return res;
}
conn->waiting_thread = KERNEL_PID_UNDEF;
mutex_unlock(&conn->mutex);
return 0;
}

void conn_udp_close(conn_udp_t *conn)
{
if (conn->sock.input_callback != NULL) {
mutex_lock(&conn->mutex);
if (conn->waiting_thread != KERNEL_PID_UNDEF) {
msg_t msg;
msg.type = _MSG_TYPE_CLOSE;
msg.content.ptr = (char *)conn;
mutex_unlock(&conn->mutex);
msg_send(&msg, conn->waiting_thread);
mutex_lock(&conn->mutex);
}
udp_socket_close(&conn->sock);
conn->sock.input_callback = NULL;
mutex_unlock(&conn->mutex);
}
}

int conn_udp_getlocaladdr(conn_udp_t *conn, void *addr, uint16_t *port)
{
if (conn->sock.input_callback != NULL) {
mutex_lock(&conn->mutex);
memset(addr, 0, sizeof(ipv6_addr_t));
*port = NTOHS(conn->sock.udp_conn->lport);
mutex_unlock(&conn->mutex);
return sizeof(ipv6_addr_t);
}
return -EBADF;
}

int conn_udp_recvfrom(conn_udp_t *conn, void *data, size_t max_len, void *addr,
size_t *addr_len, uint16_t *port)
{
int res = -EIO;
msg_t msg;

if (conn->sock.input_callback == NULL) {
return -ENOTSOCK;
}
mutex_lock(&conn->mutex);
if (conn->waiting_thread != KERNEL_PID_UNDEF) {
mutex_unlock(&conn->mutex);
return -EALREADY;
}
conn->waiting_thread = sched_active_pid;
mutex_unlock(&conn->mutex);
msg_receive(&msg);
if (msg.type == _MSG_TYPE_CLOSE) {
conn->waiting_thread = KERNEL_PID_UNDEF;
return -EINTR;
}
else if (msg.type == _MSG_TYPE_RCV) {
mutex_lock(&conn->mutex);
if (msg.content.ptr == (char *)conn) {
if (max_len < conn->recv_info.datalen) {
conn->waiting_thread = KERNEL_PID_UNDEF;
mutex_unlock(&conn->mutex);
return -ENOBUFS;
}
memcpy(data, conn->recv_info.data, conn->recv_info.datalen);
memcpy(addr, conn->recv_info.src, sizeof(ipv6_addr_t));
*addr_len = sizeof(ipv6_addr_t);
*port = conn->recv_info.src_port;
res = (int)conn->recv_info.datalen;
}
conn->waiting_thread = KERNEL_PID_UNDEF;
mutex_unlock(&conn->mutex);
}
return res;
}

int conn_udp_sendto(const void *data, size_t len, const void *src, size_t src_len,
const void *dst, size_t dst_len, int family, uint16_t sport,
uint16_t dport)
{
int res;
struct udp_socket sock;

(void)src;
(void)src_len;
(void)dst_len;
if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
(len > UINT16_MAX)) {
return -EMSGSIZE;
}
if ((dst_len > sizeof(ipv6_addr_t)) || (family != AF_INET6)) {
return -EAFNOSUPPORT;
}
if ((res = _reg_and_bind(&sock, NULL, NULL, sport)) < 0) {
return res;
}
if ((res = udp_socket_sendto(&sock, data, (uint16_t)len, dst, dport)) < 0) {
return -EIO;
}
return res;
}

static void _input_callback(struct udp_socket *c, void *ptr,
const uip_ipaddr_t *src_addr, uint16_t src_port,
const uip_ipaddr_t *dst_addr, uint16_t dst_port,
const uint8_t *data, uint16_t datalen)
{
conn_udp_t *conn = ptr;

(void)dst_addr;
(void)dst_port;
mutex_lock(&conn->mutex);
if (conn->waiting_thread != KERNEL_PID_UNDEF) {
msg_t msg;
conn->recv_info.src_port = src_port;
conn->recv_info.src = (const ipv6_addr_t *)src_addr;
conn->recv_info.data = data;
conn->recv_info.datalen = datalen - sizeof(ipv6_hdr_t);
msg.type = _MSG_TYPE_RCV;
msg.content.ptr = (char *)conn;
mutex_unlock(&conn->mutex);
msg_send(&msg, conn->waiting_thread);
}
else {
mutex_unlock(&conn->mutex);
}
}

/** @} */
53 changes: 53 additions & 0 deletions pkg/emb6/include/emb6/conn/udp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* 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.
*/

/**
* @defgroup emb6_conn_udp udp_conn wrapper for emb6
* @ingroup emb6
* @brief UDP conn for emb6
* @{
*
* @file
* @brief UDP conn definitions
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef EMB6_CONN_UDP_H_
#define EMB6_CONN_UDP_H_

#include <stdint.h>

#include "kernel_types.h"
#include "mutex.h"
#include "net/ipv6/addr.h"

#include "uip.h"
#include "udp-socket.h"

#ifdef __cplusplus
extern "C" {
#endif

struct conn_udp {
struct udp_socket sock;
mutex_t mutex;
kernel_pid_t waiting_thread;
struct {
uint16_t src_port;
const ipv6_addr_t *src;
const void *data;
size_t datalen;
} recv_info;
};

#ifdef __cplusplus
}
#endif

#endif /* EMB6_CONN_UDP_H_ */
/** @} */
4 changes: 4 additions & 0 deletions sys/include/net/conn/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#include "net/gnrc/conn.h"
#endif

#ifdef MODULE_EMB6_CONN_UDP
#include "emb6/conn/udp.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down

0 comments on commit 6c713a2

Please sign in to comment.