mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
emb6: add conn_udp wrapper
This commit is contained in:
parent
0b0d3b18c1
commit
0ab8aae529
23
Makefile.dep
23
Makefile.dep
@ -357,6 +357,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
|
||||
@ -430,6 +434,25 @@ ifneq (,$(filter lwip_contrib,$(USEMODULE)))
|
||||
USEMODULE += sema
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6_%,$(USEMODULE)))
|
||||
USEMODULE += emb6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6,$(USEMODULE)))
|
||||
USEPKG += emb6
|
||||
USEMODULE += emb6_bsp
|
||||
USEMODULE += emb6_common
|
||||
USEMODULE += emb6_contrib
|
||||
USEMODULE += emb6_ipv6
|
||||
USEMODULE += emb6_ipv6_multicast
|
||||
USEMODULE += emb6_llsec
|
||||
USEMODULE += emb6_mac
|
||||
USEMODULE += emb6_netdev2
|
||||
USEMODULE += emb6_rpl
|
||||
USEMODULE += emb6_sicslowpan
|
||||
USEMODULE += emb6_utils
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sema,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
@ -22,6 +22,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
|
||||
INCLUDES += -I$(EMB6_DIR)/emb6/inc/net/ipv6
|
||||
|
3
pkg/emb6/contrib/conn/udp/Makefile
Normal file
3
pkg/emb6/contrib/conn/udp/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = emb6_conn_udp
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
244
pkg/emb6/contrib/conn/udp/emb6_conn_udp.c
Normal file
244
pkg/emb6/contrib/conn/udp/emb6_conn_udp.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 <stdbool.h>
|
||||
|
||||
#include "evproc.h"
|
||||
#include "msg.h"
|
||||
#include "mutex.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)
|
||||
|
||||
/* struct to describe a sendto command for emb6 thread */
|
||||
typedef struct {
|
||||
struct udp_socket sock;
|
||||
mutex_t mutex;
|
||||
const void *data;
|
||||
int res;
|
||||
uint16_t data_len;
|
||||
} _send_cmd_t;
|
||||
|
||||
extern uint16_t uip_slen;
|
||||
|
||||
static bool send_registered = false;
|
||||
|
||||
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 void _output_callback(c_event_t c_event, p_data_t p_data);
|
||||
|
||||
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) {
|
||||
udp_socket_close(c);
|
||||
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) {
|
||||
conn->sock.input_callback = NULL;
|
||||
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;
|
||||
_send_cmd_t send_cmd;
|
||||
|
||||
if (!send_registered) {
|
||||
if (evproc_regCallback(EVENT_TYPE_CONN_SEND, _output_callback) != E_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
else {
|
||||
send_registered = true;
|
||||
}
|
||||
}
|
||||
mutex_init(&send_cmd.mutex);
|
||||
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;
|
||||
}
|
||||
mutex_lock(&send_cmd.mutex);
|
||||
send_cmd.data = data;
|
||||
send_cmd.data_len = (uint16_t)len;
|
||||
if ((res = _reg_and_bind(&send_cmd.sock, NULL, NULL, sport)) < 0) {
|
||||
mutex_unlock(&send_cmd.mutex);
|
||||
return res;
|
||||
}
|
||||
udp_socket_connect(&send_cmd.sock, (uip_ipaddr_t *)dst, dport); /* can't fail at this point */
|
||||
/* change to emb6 thread context */
|
||||
if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_CONN_SEND, &send_cmd) != E_SUCCESS) {
|
||||
udp_socket_close(&send_cmd.sock);
|
||||
mutex_unlock(&send_cmd.mutex);
|
||||
return -EIO;
|
||||
}
|
||||
/* block thread until data was send */
|
||||
mutex_lock(&send_cmd.mutex);
|
||||
udp_socket_close(&send_cmd.sock);
|
||||
mutex_unlock(&send_cmd.mutex);
|
||||
|
||||
return send_cmd.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);
|
||||
}
|
||||
}
|
||||
|
||||
static void _output_callback(c_event_t c_event, p_data_t p_data)
|
||||
{
|
||||
_send_cmd_t *send_cmd = (_send_cmd_t *)p_data;
|
||||
|
||||
if ((c_event != EVENT_TYPE_CONN_SEND) || (p_data == NULL)) {
|
||||
return;
|
||||
}
|
||||
if ((send_cmd->res = udp_socket_send(&send_cmd->sock, send_cmd->data, send_cmd->data_len)) < 0) {
|
||||
send_cmd->res = -EHOSTUNREACH;
|
||||
}
|
||||
mutex_unlock(&send_cmd->mutex);
|
||||
}
|
||||
|
||||
/** @} */
|
62
pkg/emb6/include/emb6/conn/udp.h
Normal file
62
pkg/emb6/include/emb6/conn/udp.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* For this implementation to receive with an open connection only with one
|
||||
* thread at once. If you use @ref conn_udp_recvfrom() with more than one thread
|
||||
* simultaneously, it will return `-EALREADY`.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @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
|
||||
|
||||
/**
|
||||
* @brief @ref net_conn_udp definition for emb6
|
||||
*/
|
||||
struct conn_udp {
|
||||
struct udp_socket sock; /**< emb6 internal socket */
|
||||
mutex_t mutex; /**< mutex for the connection */
|
||||
kernel_pid_t waiting_thread; /**< thread waiting for an incoming packet
|
||||
* on this connection */
|
||||
struct {
|
||||
uint16_t src_port; /**< source port */
|
||||
const ipv6_addr_t *src; /**< source address */
|
||||
const void *data; /**< data of received packet */
|
||||
size_t datalen; /**< length of received packet data */
|
||||
} recv_info; /**< info on received packet */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EMB6_CONN_UDP_H_ */
|
||||
/** @} */
|
@ -31,6 +31,10 @@
|
||||
#include "lwip/conn.h"
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_EMB6_CONN_UDP
|
||||
#include "emb6/conn/udp.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user