From 3d3eb02ad84881969f2cb8dfe5d3283cd491cc12 Mon Sep 17 00:00:00 2001 From: Olaf Bergmann Date: Thu, 25 Feb 2016 11:10:42 +0100 Subject: [PATCH] net.[hc]: allow multiple endpoints in single context Endpoints will be attached to the context object using a new function coap_attach_endpoint(). The sockfd component has been removed from coap_context_t as it is accessible by the endpoint. coap_endpoint_t has a new field 'context' that refers to the context object the respective endpoint has been associated with, or NULL if it is not attached to any context. An endpoint can be attached to at least one context at a time. --- Makefile.am | 7 +- include/coap/coap_io.h | 5 +- include/coap/net.h | 4 - src/net.c | 27 ++++--- src/platform/posix/coap_io.c | 153 +++-------------------------------- 5 files changed, 34 insertions(+), 162 deletions(-) diff --git a/Makefile.am b/Makefile.am index da4574f0..ab553fb4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,9 @@ libcoap_@LIBCOAP_API_VERSION@_la_CFLAGS = \ -fPIE \ $(AM_CFLAGS) +## Platform-specific sources are located in platform_src +platform_src = src/platform/@PLATFORM@ + ## Define the source file list for the "libcoap.la" target. ## Note that it is not necessary to list header files which are already listed ## elsewhere in a _HEADERS variable assignment. @@ -51,7 +54,6 @@ libcoap_@LIBCOAP_API_VERSION@_la_SOURCES = \ src/address.c \ src/async.c \ src/block.c \ - src/platform/@PLATFORM@/coap_io.c \ src/coap_time.c \ src/debug.c \ src/encode.c \ @@ -64,7 +66,8 @@ libcoap_@LIBCOAP_API_VERSION@_la_SOURCES = \ src/str.c \ src/subscribe.c \ src/uri.c \ - src/platform/@PLATFORM@/prng.c + $(platform_src)/coap_io.c \ + $(platform_src)/prng.c ## Define the list of public header files and their install location. ## The list defined here will be used within the include/Makefile.am diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index 0263ef9b..69c302cb 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -37,6 +37,7 @@ struct coap_context_t; * tuple (handle, addr) must uniquely identify this endpoint. */ typedef struct coap_endpoint_t { + struct coap_endpoint_t *next; #if defined(WITH_POSIX) || defined(WITH_CONTIKI) union { int fd; /**< on POSIX systems */ @@ -46,10 +47,8 @@ typedef struct coap_endpoint_t { #ifdef WITH_LWIP struct udp_pcb *pcb; - /**< @FIXME --chrysn - * this was added in a hurry, not sure it confirms to the overall model */ - struct coap_context_t *context; #endif /* WITH_LWIP */ + struct coap_context_t *context; coap_address_t addr; /**< local interface address */ int ifindex; diff --git a/include/coap/net.h b/include/coap/net.h index 014b4903..4c8e595f 100644 --- a/include/coap/net.h +++ b/include/coap/net.h @@ -90,10 +90,6 @@ typedef struct coap_context_t { coap_queue_t *sendqueue; coap_endpoint_t *endpoint; /**< the endpoint used for listening */ -#ifdef WITH_POSIX - int sockfd; /**< send/receive socket */ -#endif /* WITH_POSIX */ - #ifdef WITH_CONTIKI struct uip_udp_conn *conn; /**< uIP connection object */ struct etimer retransmit_timer; /**< fires when the next packet must be sent */ diff --git a/src/net.c b/src/net.c index 98173113..b4ae16c1 100644 --- a/src/net.c +++ b/src/net.c @@ -1,6 +1,6 @@ /* net.c -- CoAP network interface * - * Copyright (C) 2010--2015 Olaf Bergmann + * Copyright (C) 2010--2016 Olaf Bergmann * * This file is part of the CoAP library libcoap. Please see * README for terms of use. @@ -36,6 +36,7 @@ #include #endif +#include "utlist.h" #include "debug.h" #include "mem.h" #include "str.h" @@ -329,6 +330,21 @@ is_wkc(coap_key_t k) { } #endif +void +coap_detach_endpoint(coap_endpoint_t *endpoint) { + if (endpoint->context != NULL) { + LL_DELETE(endpoint->context->endpoint, endpoint); + endpoint->context = NULL; + } +} + +void +coap_attach_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint) { + coap_detach_endpoint(endpoint); + endpoint->context = ctx; + LL_PREPEND(ctx->endpoint, endpoint); +} + coap_context_t * coap_new_context( const coap_address_t *listen_addr) { @@ -376,18 +392,11 @@ coap_new_context( /* initialize message id */ coap_prng((unsigned char *)&c->message_id, sizeof(unsigned short)); - c->endpoint = coap_new_endpoint(listen_addr, COAP_ENDPOINT_NOSEC); -#ifdef WITH_LWIP - c->endpoint->context = c; -#endif + coap_attach_endpoint(c, coap_new_endpoint(listen_addr, COAP_ENDPOINT_NOSEC)); if (c->endpoint == NULL) { goto onerror; } -#ifdef WITH_POSIX - c->sockfd = c->endpoint->handle.fd; -#endif /* WITH_POSIX */ - #if defined(WITH_POSIX) || defined(WITH_CONTIKI) c->network_send = coap_network_send; c->network_read = coap_network_read; diff --git a/src/platform/posix/coap_io.c b/src/platform/posix/coap_io.c index cbf2263d..ea4349ca 100644 --- a/src/platform/posix/coap_io.c +++ b/src/platform/posix/coap_io.c @@ -1,6 +1,6 @@ -/* coap_io.h -- Default network I/O functions for libcoap +/* coap_io.c -- Default network I/O functions for libcoap * - * Copyright (C) 2012,2014 Olaf Bergmann + * Copyright (C) 2012,2014,2016 Olaf Bergmann * * This file is part of the CoAP library libcoap. Please see * README for terms of use. @@ -29,15 +29,10 @@ #endif #include -#ifdef WITH_CONTIKI -# include "uip.h" -#endif - #include "debug.h" #include "mem.h" #include "coap_io.h" -#ifdef WITH_POSIX struct coap_packet_t { coap_if_handle_t hnd; /**< the interface handle */ coap_address_t src; /**< the packet's source address */ @@ -50,62 +45,9 @@ struct coap_packet_t { size_t length; /**< length of payload */ unsigned char payload[]; /**< payload */ }; -#endif #ifndef CUSTOM_COAP_NETWORK_ENDPOINT -#ifdef WITH_CONTIKI -static int ep_initialized = 0; - -static inline struct coap_endpoint_t * -coap_malloc_contiki_endpoint() { - static struct coap_endpoint_t ep; - - if (ep_initialized) { - return NULL; - } else { - ep_initialized = 1; - return &ep; - } -} - -static inline void -coap_free_contiki_endpoint(struct coap_endpoint_t *ep) { - ep_initialized = 0; -} - -coap_endpoint_t * -coap_new_endpoint(const coap_address_t *addr, int flags) { - struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint(); - - if (ep) { - memset(ep, 0, sizeof(struct coap_endpoint_t)); - ep->handle.conn = udp_new(NULL, 0, NULL); - - if (!ep->handle.conn) { - coap_free_endpoint(ep); - return NULL; - } - - coap_address_init(&ep->addr); - uip_ipaddr_copy(&ep->addr.addr, &addr->addr); - ep->addr.port = addr->port; - udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port); - } - return ep; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if (ep) { - if (ep->handle.conn) { - uip_udp_remove((struct uip_udp_conn *)ep->handle.conn); - } - coap_free_contiki_endpoint(ep); - } -} - -#else /* WITH_CONTIKI */ static inline struct coap_endpoint_t * coap_malloc_posix_endpoint(void) { return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t)); @@ -200,12 +142,11 @@ coap_free_endpoint(coap_endpoint_t *ep) { } } -#endif /* WITH_CONTIKI */ #endif /* CUSTOM_COAP_NETWORK_ENDPOINT */ #ifndef CUSTOM_COAP_NETWORK_SEND -#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H) +#ifndef HAVE_NETINET_IN_H /* define struct in6_pktinfo and struct in_pktinfo if not available FIXME: check with configure */ @@ -219,7 +160,7 @@ struct in_pktinfo { struct in_addr ipi_spec_dst; struct in_addr ipi_addr; }; -#endif +#endif /* HAVE_NETINET_IN_H */ #if defined(WITH_POSIX) && !defined(SOL_IP) /* Solaris expects level IPPROTO_IP for ancillary data. */ @@ -242,7 +183,6 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct coap_endpoint_t *ep = (struct coap_endpoint_t *)local_interface; -#ifndef WITH_CONTIKI /* a buffer large enough to hold all protocol address types */ char buf[CMSG_LEN(sizeof(struct sockaddr_storage))]; struct msghdr mhdr; @@ -325,13 +265,6 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, } return sendmsg(ep->handle.fd, &mhdr, 0); -#else /* WITH_CONTIKI */ - /* FIXME: untested */ - /* FIXME: is there a way to check if send was successful? */ - uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen, - &dst->addr, dst->port); - return datalen; -#endif /* WITH_CONTIKI */ } #endif /* CUSTOM_COAP_NETWORK_SEND */ @@ -340,7 +273,6 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #define SIN6(A) ((struct sockaddr_in6 *)(A)) -#ifdef WITH_POSIX static coap_packet_t * coap_malloc_packet(void) { coap_packet_t *packet; @@ -357,18 +289,6 @@ void coap_free_packet(coap_packet_t *packet) { coap_free(packet); } -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI -static inline coap_packet_t * -coap_malloc_packet(void) { - return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0); -} - -void -coap_free_packet(coap_packet_t *packet) { - coap_free_type(COAP_PACKET, packet); -} -#endif /* WITH_CONTIKI */ static inline size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { @@ -376,23 +296,20 @@ coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { } void -coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) -{ +coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) { target->handle = packet->interface->handle; memcpy(&target->addr, &packet->dst, sizeof(target->addr)); target->ifindex = packet->ifindex; target->flags = 0; /* FIXME */ } void -coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) -{ +coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) { memcpy(target, &packet->src, sizeof(coap_address_t)); } void -coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) -{ - *address = packet->payload; - *length = packet->length; +coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) { + *address = packet->payload; + *length = packet->length; } /** @@ -410,11 +327,9 @@ ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { ssize_t len = -1; -#ifdef WITH_POSIX char msg_control[CMSG_LEN(sizeof(struct sockaddr_storage))]; struct msghdr mhdr; struct iovec iov[1]; -#endif /* WITH_POSIX */ assert(ep); assert(packet); @@ -429,7 +344,6 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { coap_address_init(&(*packet)->dst); /* the local interface address */ coap_address_init(&(*packet)->src); /* the remote peer */ -#ifdef WITH_POSIX iov[0].iov_base = (*packet)->payload; iov[0].iov_len = coap_get_max_packetlength(*packet); @@ -515,55 +429,6 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { goto error; } } -#endif /* WITH_POSIX */ -#ifdef WITH_CONTIKI - /* FIXME: untested, make this work */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) - - if(uip_newdata()) { - uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr); - (*packet)->src.port = UIP_UDP_BUF->srcport; - uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr); - (*packet)->dst.port = UIP_UDP_BUF->destport; - - if (!is_local_if(&ep->addr, &(*packet)->dst)) { - coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n"); - goto error; - } - - len = uip_datalen(); - - if (len > coap_get_max_packetlength(*packet)) { - /* FIXME: we might want to send back a response */ - warn("discarded oversized packet\n"); - return -1; - } - - ((char *)uip_appdata)[len] = 0; -#ifndef NDEBUG - if (LOG_DEBUG <= coap_get_log_level()) { -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 40 -#endif - unsigned char addr_str[INET6_ADDRSTRLEN+8]; - - if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) { - debug("received %zd bytes from %s\n", len, addr_str); - } - } -#endif /* NDEBUG */ - - (*packet)->length = len; - memcpy(&(*packet)->payload, uip_appdata, len); - } - -#undef UIP_IP_BUF -#undef UIP_UDP_BUF -#endif /* WITH_CONTIKI */ -#ifdef WITH_LWIP -#error "coap_network_read() not implemented on this platform" -#endif (*packet)->interface = ep;