diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..f2c08cd2 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +all: coap-server #coap-client + $(MAKE) $(MAKEFLAGS) ROLE=server coap-server +# $(MAKE) $(MAKEFLAGS) clean +# $(MAKE) $(MAKEFLAGS) ROLE=client coap-client + +CONTIKI=../.. +#CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +WITH_UIP6=1 +UIP_CONF_IPV6=1 + +ifneq ($(TARGET), minimal-net) +CFLAGS += -DUIP_CONF_IPV6_RPL=1 +endif + +ifneq ($(ROLE),client) + UIP_LLADDR="{0x00,0x06,0x98,0x00,0x02,0x32}" + CFLAGS+= -DUIP_CONF_LLADDR=$(UIP_LLADDR) +else + UIP_LLADDR="{0x00,0x06,0x98,0x00,0x02,0x30}" + CFLAGS+= -DUDP_CONNECTION_ADDR="fe80::206:98ff:fe00:232" \ + -DUIP_CONF_LLADDR=$(UIP_LLADDR) +endif + +CFLAGS += -ffunction-sections +LDFLAGS += -Wl,--gc-sections,--undefined=_reset_vector__,--undefined=InterruptVectors,--undefined=_copy_data_init__,--undefined=_clear_bss_init__,--undefined=_end_of_init__ + +CFLAGS += -DUIP_CONF_TCP=0 -DUIP_CONF_BYTE_ORDER=1234 + +APPS += libcoap + +PROJECT_SOURCEFILES = pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c str.c option.c async.c + +include $(CONTIKI)/Makefile.include diff --git a/address.h b/address.h index 838dd541..78bf9a23 100644 --- a/address.h +++ b/address.h @@ -35,12 +35,12 @@ #include "uip.h" typedef struct { - socklen_t size; + unsigned char size; uip_ipaddr_t addr; - unsigned short rport; -} __uip_address_t; + unsigned short port; +} __coap_uip_address_t; -#define coap_address_t __uip_address_t +#define coap_address_t __coap_uip_address_t #endif /* WITH_CONTIKI */ /** multi-purpose address abstraction */ diff --git a/coap-server.c b/coap-server.c new file mode 100644 index 00000000..130efe7d --- /dev/null +++ b/coap-server.c @@ -0,0 +1,86 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#ifndef DEBUG +#define DEBUG DEBUG_PRINT +#include "net/uip-debug.h" +#endif + +#include "debug.h" +#include "coap.h" + +static coap_context_t *coap_context; + + +PROCESS(coap_server_process, "CoAP server process"); +AUTOSTART_PROCESSES(&coap_server_process); +/*---------------------------------------------------------------------------*/ +void +init_coap() { + coap_address_t listen_addr; + + coap_address_init(&listen_addr); + listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT); + + coap_context = coap_new_context(&listen_addr); + + coap_set_log_level(LOG_DEBUG); + + if (!coap_context) + coap_log(LOG_CRIT, "cannot create CoAP context\r\n"); +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_server_process, ev, data) +{ + PROCESS_BEGIN(); + + init_coap(); + if (!coap_context) { + coap_log(LOG_EMERG, "cannot create context\n"); + PROCESS_EXIT(); + } + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + coap_read(coap_context); /* read received data */ + coap_dispatch(coap_context); /* and dispatch PDUs from receivequeue */ + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/coap.h b/coap.h index 5abcce82..8dee38e3 100644 --- a/coap.h +++ b/coap.h @@ -12,7 +12,7 @@ #include "config.h" #include "debug.h" #include "mem.h" -#include "list.h" +#include "coap_list.h" #include "pdu.h" #include "option.h" #include "net.h" diff --git a/coap_list.c b/coap_list.c index a1ef71fc..4a10788f 100644 --- a/coap_list.c +++ b/coap_list.c @@ -1,4 +1,4 @@ -/* list.c -- CoAP list structures +/* coap_list.c -- CoAP list structures * * Copyright (C) 2010,2011 Olaf Bergmann * @@ -10,7 +10,7 @@ #include #include "mem.h" -#include "list.h" +#include "coap_list.h" int coap_insert(coap_list_t **queue, coap_list_t *node, diff --git a/coap_list.h b/coap_list.h index 6cfa33fa..62e5055c 100644 --- a/coap_list.h +++ b/coap_list.h @@ -1,4 +1,4 @@ -/* list.h -- CoAP list structures +/* coap_list.h -- CoAP list structures * * Copyright (C) 2010,2011 Olaf Bergmann * diff --git a/coap_time.h b/coap_time.h index a5b3e162..be8fbbde 100644 --- a/coap_time.h +++ b/coap_time.h @@ -36,7 +36,7 @@ extern clock_time_t clock_offset; static inline void contiki_clock_init_impl(void) { clock_init(); - offset = clock_time(); + clock_offset = clock_time(); } #define coap_clock_init contiki_clock_init_impl diff --git a/config.h b/config.h index 6cbfa775..66f5e4f0 100644 --- a/config.h +++ b/config.h @@ -7,6 +7,9 @@ #define WITH_CONTIKI 1 +#define DEBUG 0 +#define HAVE_STRNLEN 1 + #ifndef BYTE_ORDER # ifdef UIP_CONF_BYTE_ORDER # define BYTE_ORDER UIP_CONF_BYTE_ORDER diff --git a/debug.c b/debug.c index 52a340ba..2c091343 100644 --- a/debug.c +++ b/debug.c @@ -24,6 +24,13 @@ #include "debug.h" #include "net.h" +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/uip-debug.h" +#endif + static coap_log_t maxlog = LOG_WARN; /* default maximum log level */ coap_log_t @@ -64,6 +71,7 @@ print_timestamp(char *s, size_t len, coap_tick_t t) { #ifndef NDEBUG +#ifndef HAVE_STRNLEN /** * A length-safe strlen() fake. * @@ -79,6 +87,7 @@ strnlen(unsigned char *s, size_t maxlen) { ++n; return n; } +#endif /* HAVE_STRNLEN */ unsigned int print_readable( const unsigned char *data, unsigned int len, @@ -157,8 +166,7 @@ coap_print_addr(const struct __coap_address_t *addr, unsigned char *buf, size_t return buf + len - p; #else /* TODO: output addresses manually */ -#warn "inet_ntop() not available, network addresses will " - "not be included in debug output" +#warning "inet_ntop() not available, network addresses will not be included in debug output" return 0; #endif } @@ -167,9 +175,15 @@ void coap_show_pdu(const coap_pdu_t *pdu) { unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ +#ifndef WITH_CONTIKI fprintf(COAP_DEBUG_FD, "v:%d t:%d oc:%d c:%d id:%u", pdu->hdr->version, pdu->hdr->type, pdu->hdr->optcnt, pdu->hdr->code, ntohs(pdu->hdr->id)); +#else /* WITH_CONTIKI */ + fprintf(COAP_DEBUG_FD, "v:%d t:%d oc:%d c:%d id:%u", + pdu->hdr->version, pdu->hdr->type, + pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id)); +#endif /* WITH_CONTIKI */ /* show options, if any */ if (pdu->hdr->optcnt) { @@ -193,11 +207,14 @@ coap_show_pdu(const coap_pdu_t *pdu) { fprintf(COAP_DEBUG_FD, " d:%s", buf); } fprintf(COAP_DEBUG_FD, "\n"); +#ifndef WITH_CONTIKI fflush(COAP_DEBUG_FD); +#endif } #endif /* NDEBUG */ +#ifndef WITH_CONTIKI void coap_log_impl(coap_log_t level, const char *format, ...) { char timebuf[32]; @@ -222,3 +239,25 @@ coap_log_impl(coap_log_t level, const char *format, ...) { va_end(ap); fflush(log_fd); } +#else /* WITH_CONTIKI */ +void +coap_log_impl(coap_log_t level, const char *format, ...) { + char timebuf[32]; + coap_tick_t now; + va_list ap; + + if (maxlog < level) + return; + + coap_ticks(&now); + if (print_timestamp(timebuf,sizeof(timebuf), now)) + PRINTF("%s ", timebuf); + + if (level <= LOG_DEBUG) + PRINTF("%s ", loglevels[level]); + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} +#endif /* WITH_CONTIKI */ diff --git a/encode.h b/encode.h index 53d69243..8f32e64a 100644 --- a/encode.h +++ b/encode.h @@ -9,7 +9,7 @@ #ifndef _COAP_ENCODE_H_ #define _COAP_ENCODE_H_ -#if (BSD >= 199103) +#if (BSD >= 199103) || defined(WITH_CONTIKI) # include #else # include diff --git a/net.c b/net.c index 266a53c0..d1f8dd1a 100644 --- a/net.c +++ b/net.c @@ -12,9 +12,15 @@ #include #include #include +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_ARPA_INET_H #include +#endif #include "debug.h" #include "mem.h" @@ -25,7 +31,21 @@ #include "encode.h" #include "net.h" +#ifndef WITH_CONTIKI + time_t clock_offset; +#else /* WITH_CONTIKI */ +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/uip-debug.h" + +clock_time_t clock_offset; + +#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]) + +#endif /* WITH_CONTIKI */ int coap_insert_node(coap_queue_t **queue, coap_queue_t *node, @@ -135,7 +155,7 @@ is_wkc(coap_key_t k) { #endif coap_context_t * -coap_new_context(const struct sockaddr *listen_addr, size_t addr_size) { +coap_new_context(const coap_address_t *listen_addr) { coap_context_t *c = coap_malloc( sizeof( coap_context_t ) ); int reuse = 1; @@ -165,6 +185,7 @@ coap_new_context(const struct sockaddr *listen_addr, size_t addr_size) { coap_register_option(c, COAP_OPTION_TOKEN); coap_register_option(c, COAP_OPTION_URI_QUERY); +#ifndef WITH_CONTIKI c->sockfd = socket(listen_addr->sa_family, SOCK_DGRAM, 0); if ( c->sockfd < 0 ) { #ifndef NDEBUG @@ -193,6 +214,13 @@ coap_new_context(const struct sockaddr *listen_addr, size_t addr_size) { close ( c->sockfd ); coap_free( c ); return NULL; + +#else /* WITH_CONTIKI */ + c->conn = udp_new(NULL, 0, NULL); + udp_bind(c->conn, listen_addr->port); + + return c; +#endif /* WITH_CONTIKI */ } void @@ -209,7 +237,9 @@ coap_free_context( coap_context_t *context ) { } /* coap_delete_list(context->subscriptions); */ +#ifndef WITH_CONTIKI close( context->sockfd ); +#endif /* WITH_CONTIKI */ coap_free( context ); } @@ -259,6 +289,7 @@ coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, /* Compare the complete address structure in case of IPv4. For IPv6, * we need to look at the transport address only. */ +#ifndef WITH_CONTIKI switch (peer->addr.sa.sa_family) { case AF_INET: coap_hash((const unsigned char *)&peer->addr.sa, peer->size, h); @@ -272,6 +303,10 @@ coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, default: return; } +#else /* WITH_CONTIKI */ + coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h); + coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h); +#endif /* WITH_CONTIKI */ if (coap_check_option((coap_pdu_t *)pdu, COAP_OPTION_TOKEN, &opt_iter)) coap_hash(COAP_OPT_VALUE(opt_iter.option), @@ -281,6 +316,7 @@ coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]); } +#ifndef WITH_CONTIKI /* releases space allocated by PDU if free_pdu is set */ coap_tid_t coap_send_impl(coap_context_t *context, @@ -306,6 +342,29 @@ coap_send_impl(coap_context_t *context, return id; } +#else /* WITH_CONTIKI */ +/* releases space allocated by PDU if free_pdu is set */ +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu, int free_pdu) { + coap_tid_t id = COAP_INVALID_TID; + + if ( !context || !dst || !pdu ) + return id; + + /* FIXME: is there a way to check if send was successful? */ + uip_udp_packet_sendto(context->conn, pdu->hdr, pdu->length, + &dst->addr, dst->port); + + coap_transaction_id(dst, pdu, &id); + + if (free_pdu) + coap_delete_pdu(pdu); + + return id; +} +#endif /* WITH_CONTIKI */ coap_tid_t coap_send(coap_context_t *context, @@ -354,7 +413,7 @@ coap_send_confirmed(coap_context_t *context, return COAP_INVALID_TID; } - r = rand(); + prng((unsigned char *)&r,sizeof(r)); coap_ticks(&node->t); /* add randomized RESPONSE_TIMEOUT to determine retransmission timeout */ @@ -384,8 +443,13 @@ coap_retransmit( coap_context_t *context, coap_queue_t *node ) { node->t += ( node->timeout << node->retransmit_cnt ); coap_insert_node( &context->sendqueue, node, _order_timestamp ); +#ifndef WITH_CONTIKI debug("** retransmission #%d of transaction %d\n", node->retransmit_cnt, ntohs(node->pdu->hdr->id)); +#else /* WITH_CONTIKI */ + debug("** retransmission #%d of transaction %d\n", + node->retransmit_cnt, uip_ntohs(node->pdu->hdr->id)); +#endif /* WITH_CONTIKI */ node->id = coap_send_impl(context, &node->remote, node->pdu, 0); return node->id; @@ -409,15 +473,39 @@ _order_transaction_id( coap_queue_t *lhs, coap_queue_t *rhs ) { int coap_read( coap_context_t *ctx ) { +#ifndef WITH_CONTIKI static char buf[COAP_MAX_PDU_SIZE]; static coap_hdr_t *pdu = (coap_hdr_t *)buf; +#else /* WITH_CONTIKI */ + static char *buf; + static coap_hdr_t *pdu; +#endif /* WITH_CONTIKI */ ssize_t bytes_read; static coap_address_t src; coap_queue_t *node; +#ifdef WITH_CONTIKI + buf = uip_appdata; + pdu = (coap_hdr_t *)buf; +#endif /* WITH_CONTIKI */ + coap_address_init(&src); + +#ifndef WITH_CONTIKI bytes_read = recvfrom(ctx->sockfd, buf, sizeof(buf), 0, &src.addr.sa, &src.size); +#else /* WITH_CONTIKI */ + if(uip_newdata()) { + uip_ipaddr_copy(&src.addr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + + bytes_read = uip_datalen(); + ((char *)uip_appdata)[uip_datalen()] = 0; + PRINTF("Server received message from "); + PRINT6ADDR(&src.addr); + PRINTF(":%d\n", uip_ntohs(src.port)); + } +#endif /* WITH_CONTIKI */ if ( bytes_read < 0 ) { warn("coap_read: recvfrom"); @@ -470,6 +558,9 @@ coap_read( coap_context_t *ctx ) { #ifndef NDEBUG if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif unsigned char addr[INET6_ADDRSTRLEN+8]; if (coap_print_addr(&src, addr, sizeof(addr))) @@ -804,7 +895,11 @@ coap_dispatch( coap_context_t *context ) { * not only the transaction but also the subscriptions we might * have. */ +#ifndef WITH_CONTIKI coap_log(LOG_ALERT, "got RST for message %u\n", ntohs(rcvd->pdu->hdr->id)); +#else /* WITH_CONTIKI */ + coap_log(LOG_ALERT, "got RST for message %u\n", uip_ntohs(rcvd->pdu->hdr->id)); +#endif /* WITH_CONTIKI */ /* find transaction in sendqueue to stop retransmission */ coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); diff --git a/net.h b/net.h index 1a865420..cf46bbeb 100644 --- a/net.h +++ b/net.h @@ -15,7 +15,7 @@ #include #else #ifndef assert -#warn "assertions are disabled" +#warning "assertions are disabled" # define assert(x) #endif #endif @@ -88,8 +88,11 @@ typedef struct coap_context_t { struct coap_async_state_t *async_state; #endif coap_queue_t *sendqueue, *recvqueue; - int sockfd; /* send/receive socket */ - +#ifndef WITH_CONTIKI + int sockfd; /**< send/receive socket */ +#else /* WITH_CONTIKI */ + struct uip_udp_conn *conn; /**< uIP connection object */ +#endif /* WITH_CONTIKI */ coap_response_handler_t response_handler; } coap_context_t; @@ -126,7 +129,7 @@ coap_queue_t *coap_peek_next( coap_context_t *context ); coap_queue_t *coap_pop_next( coap_context_t *context ); /* Creates a new coap_context_t object that will hold the CoAP stack status. */ -coap_context_t *coap_new_context(const struct sockaddr *listen_addr, size_t addr_size); +coap_context_t *coap_new_context(const coap_address_t *listen_addr); /* CoAP stack context must be released with coap_free_context() */ void coap_free_context( coap_context_t *context ); diff --git a/pdu.c b/pdu.c index 8448a0d3..f9408b43 100644 --- a/pdu.c +++ b/pdu.c @@ -9,7 +9,9 @@ #include #include #include +#ifdef HAVE_ARPA_INET_H #include +#endif #include "debug.h" #include "mem.h" diff --git a/pdu.h b/pdu.h index 7349da46..6556ead5 100644 --- a/pdu.h +++ b/pdu.h @@ -10,7 +10,7 @@ #define _PDU_H_ #include "config.h" -#include "list.h" +#include "coap_list.h" #include "uri.h" /* pre-defined constants that reflect defaults for CoAP */