From 1b3818d1cd95ff96c8c6dff3e6399b79a1cb0426 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 26 Jul 2016 17:17:27 -0700 Subject: [PATCH 01/27] Patches from IoTivity Change-Id: Idddee819530e8eb497a8abf72aa1f94a7b30d40b Signed-off-by: Dave Thaler --- coap_config.h.contiki | 1 + examples/client.c | 6 +- examples/coap-rd.c | 4 +- examples/etsi_iot_01.c | 6 +- include/coap/address.h | 20 +-- include/coap/async.h | 2 +- include/coap/bits.h | 6 +- include/coap/block.h | 4 +- include/coap/coap.h.in | 1 + include/coap/coap_io.h | 6 +- include/coap/coap_list.h | 48 +++++++ include/coap/coap_time.h | 20 +-- include/coap/encode.h | 6 +- include/coap/libcoap.h | 11 +- include/coap/mem.h | 10 +- include/coap/net.h | 12 +- include/coap/option.h | 29 ++++- include/coap/pdu.h | 274 ++++++++++++++++++++++++++++++++++----- include/coap/prng.h | 6 +- include/coap/resource.h | 4 +- src/address.c | 18 ++- src/block.c | 8 +- src/coap_io.c | 121 ++++++++++++----- src/coap_list.c | 91 +++++++++++++ src/coap_time.c | 5 +- src/debug.c | 17 ++- src/encode.c | 3 +- src/net.c | 33 +++-- src/option.c | 4 +- src/pdu.c | 2 +- src/resource.c | 8 +- src/uri.c | 6 +- 32 files changed, 629 insertions(+), 163 deletions(-) create mode 100644 include/coap/coap_list.h create mode 100644 src/coap_list.c diff --git a/coap_config.h.contiki b/coap_config.h.contiki index 43bef3a4ed..66bf57e0c5 100644 --- a/coap_config.h.contiki +++ b/coap_config.h.contiki @@ -56,6 +56,7 @@ #define HAVE_STRNLEN 1 #define HAVE_SNPRINTF 1 +#define HAVE_STRINGS_H 1 /* there is no file-oriented output */ #define COAP_DEBUG_FD NULL diff --git a/examples/client.c b/examples/client.c index 4d35dbc2ca..31fd806bfd 100644 --- a/examples/client.c +++ b/examples/client.c @@ -69,7 +69,7 @@ coap_tick_t obs_wait = 0; /* timeout for current subscription */ #define UNUSED_PARAM #endif /* GCC */ -static inline void +COAP_STATIC_INLINE void set_timeout(coap_tick_t *timer, const unsigned int seconds) { coap_ticks(timer); *timer += seconds * COAP_TICKS_PER_SECOND; @@ -305,7 +305,7 @@ resolve_address(const str *server, struct sockaddr *dst) { ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \ (Pdu)->hdr->code == COAP_RESPONSE_CODE(204))) -static inline int +COAP_STATIC_INLINE int check_token(coap_pdu_t *received) { return received->hdr->token_length == the_token.length && memcmp(received->hdr->token, the_token.s, the_token.length) == 0; @@ -808,7 +808,7 @@ cmdline_proxy(char *arg) { return 1; } -static inline void +COAP_STATIC_INLINE void cmdline_token(char *arg) { strncpy((char *)the_token.s, arg, min(sizeof(_token_data), strlen(arg))); the_token.length = strlen(arg); diff --git a/examples/coap-rd.c b/examples/coap-rd.c index 64f156f2d6..3a7efcb281 100644 --- a/examples/coap-rd.c +++ b/examples/coap-rd.c @@ -65,7 +65,7 @@ rd_t *resources = NULL; #define UNUSED_PARAM #endif /* GCC */ -static inline rd_t * +COAP_STATIC_INLINE rd_t * rd_new(void) { rd_t *rd; rd = (rd_t *)coap_malloc(sizeof(rd_t)); @@ -75,7 +75,7 @@ rd_new(void) { return rd; } -static inline void +COAP_STATIC_INLINE void rd_delete(rd_t *rd) { if (rd) { coap_free(rd->data.s); diff --git a/examples/etsi_iot_01.c b/examples/etsi_iot_01.c index 0edc8a9368..8fe0767fd6 100644 --- a/examples/etsi_iot_01.c +++ b/examples/etsi_iot_01.c @@ -88,14 +88,14 @@ coap_new_payload(size_t size) { return p; } -static inline coap_payload_t * +COAP_STATIC_INLINE coap_payload_t * coap_find_payload(const coap_key_t key) { coap_payload_t *p; HASH_FIND(hh, test_resources, key, sizeof(coap_key_t), p); return p; } -static inline void +COAP_STATIC_INLINE void coap_add_payload(const coap_key_t key, coap_payload_t *payload, coap_dynamic_uri_t *uri) { assert(payload); @@ -109,7 +109,7 @@ coap_add_payload(const coap_key_t key, coap_payload_t *payload, } } -static inline void +COAP_STATIC_INLINE void coap_delete_payload(coap_payload_t *payload) { if (payload) { coap_dynamic_uri_t *uri; diff --git a/include/coap/address.h b/include/coap/address.h index fe2e89d4c2..1ebf578ecd 100644 --- a/include/coap/address.h +++ b/include/coap/address.h @@ -52,7 +52,7 @@ typedef struct coap_address_t { #define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) #endif /* WITH_CONTIKI */ -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) /** multi-purpose address abstraction */ typedef struct coap_address_t { socklen_t size; /**< size of addr */ @@ -71,7 +71,7 @@ typedef struct coap_address_t { */ int coap_address_equals(const coap_address_t *a, const coap_address_t *b); -static inline int +COAP_STATIC_INLINE int _coap_address_isany_impl(const coap_address_t *a) { /* need to compare only relevant parts of sockaddr_in6 */ switch (a->addr.sa.sa_family) { @@ -88,7 +88,7 @@ _coap_address_isany_impl(const coap_address_t *a) { return 0; } -static inline int +COAP_STATIC_INLINE int _coap_is_mcast_impl(const coap_address_t *a) { if (!a) return 0; @@ -103,7 +103,7 @@ _coap_is_mcast_impl(const coap_address_t *a) { } return 0; } -#endif /* WITH_POSIX */ +#endif /* !WITH_LWIP && !WITH_CONTIKI */ /** * Resets the given coap_address_t object @p addr to its default values. In @@ -112,23 +112,23 @@ _coap_is_mcast_impl(const coap_address_t *a) { * * @param addr The coap_address_t object to initialize. */ -static inline void +COAP_STATIC_INLINE void coap_address_init(coap_address_t *addr) { assert(addr); memset(addr, 0, sizeof(coap_address_t)); -#ifdef WITH_POSIX +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) /* lwip and Contiki have constant address sizes and doesn't need the .size part */ addr->size = sizeof(addr->addr); #endif } -#ifndef WITH_POSIX +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) /** * Compares given address objects @p a and @p b. This function returns @c 1 if * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be * @c NULL; */ -static inline int +COAP_STATIC_INLINE int coap_address_equals(const coap_address_t *a, const coap_address_t *b) { assert(a); assert(b); return _coap_address_equals_impl(a, b); @@ -140,7 +140,7 @@ coap_address_equals(const coap_address_t *a, const coap_address_t *b) { * function returns @c 1 if this is the case, @c 0 otherwise. The parameters @p * a must not be @c NULL; */ -static inline int +COAP_STATIC_INLINE int coap_address_isany(const coap_address_t *a) { assert(a); return _coap_address_isany_impl(a); @@ -150,7 +150,7 @@ coap_address_isany(const coap_address_t *a) { * Checks if given address @p a denotes a multicast address. This function * returns @c 1 if @p a is multicast, @c 0 otherwise. */ -static inline int +COAP_STATIC_INLINE int coap_is_mcast(const coap_address_t *a) { return a && _coap_is_mcast_impl(a); } diff --git a/include/coap/async.h b/include/coap/async.h index 0c36defacd..3fbcc09f52 100644 --- a/include/coap/async.h +++ b/include/coap/async.h @@ -136,7 +136,7 @@ coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id); * * @param s The state object to update. */ -static inline void +COAP_STATIC_INLINE void coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); } /** @} */ diff --git a/include/coap/bits.h b/include/coap/bits.h index 0b269166d5..d7f0bf53ab 100644 --- a/include/coap/bits.h +++ b/include/coap/bits.h @@ -28,7 +28,7 @@ * * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_setb(uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; @@ -48,7 +48,7 @@ bits_setb(uint8_t *vec, size_t size, uint8_t bit) { * * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; @@ -67,7 +67,7 @@ bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { * * @return @c 1 if the bit is set, @c 0 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_getb(const uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; diff --git a/include/coap/block.h b/include/coap/block.h index 9ce00311cc..9535e29bb2 100644 --- a/include/coap/block.h +++ b/include/coap/block.h @@ -61,13 +61,13 @@ unsigned int coap_opt_block_num(const coap_opt_t *block_opt); * Checks if more than @p num blocks are required to deliver @p data_len * bytes of data for a block size of 1 << (@p szx + 4). */ -static inline int +COAP_STATIC_INLINE int coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) { return ((num+1) << (szx + 4)) < data_len; } /** Sets the More-bit in @p block_opt */ -static inline void +COAP_STATIC_INLINE void coap_opt_block_set_m(coap_opt_t *block_opt, int m) { if (m) *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08; diff --git a/include/coap/coap.h.in b/include/coap/coap.h.in index 76ebc5eb0d..6e18c6f64f 100644 --- a/include/coap/coap.h.in +++ b/include/coap/coap.h.in @@ -37,6 +37,7 @@ extern "C" { #include "bits.h" #include "block.h" #include "coap_io.h" +#include "coap_list.h" #include "coap_time.h" #include "debug.h" #include "encode.h" diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index 7a48b319a1..9c8b584bb7 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -33,14 +33,12 @@ struct coap_context_t; * tuple (handle, addr) must uniquely identify this endpoint. */ typedef struct coap_endpoint_t { -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) +#ifndef WITH_LWIP union { int fd; /**< on POSIX systems */ void *conn; /**< opaque connection (e.g. uip_conn in Contiki) */ } handle; /**< opaque handle to identify this endpoint */ -#endif /* WITH_POSIX or WITH_CONTIKI */ - -#ifdef WITH_LWIP +#else struct udp_pcb *pcb; /**< @FIXME --chrysn * this was added in a hurry, not sure it confirms to the overall model */ diff --git a/include/coap/coap_list.h b/include/coap/coap_list.h new file mode 100644 index 0000000000..9cbd858ae8 --- /dev/null +++ b/include/coap/coap_list.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.h -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +#ifndef _COAP_LIST_H_ +#define _COAP_LIST_H_ + +#include "utlist.h" + +struct coap_linkedlistnode { + struct coap_linkedlistnode *next; + void *data; + + /** + * Callback function that is called from coap_delete to release + * additional memory allocated by data Set to NULL if you do not + * need this. Note that data is free'd automatically. */ + void (*delete_func)(void *); +}; + +typedef struct coap_linkedlistnode coap_list_t; + +/** + * Adds node to given queue, ordered by specified order function. Returns 1 + * when insert was successful, 0 otherwise. + */ +int coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *)); + +/* destroys specified node */ +int coap_delete(coap_list_t *node); + +/* removes all items from given queue and frees the allocated storage */ +void coap_delete_list(coap_list_t *queue); + +/** + * Creates a new list node and adds the given data object. The memory allocated + * by data will be released by coap_delete() with the new node. Returns the + * new list node. + */ +coap_list_t *coap_new_listnode(void *data, void (*delete_func)(void *)); + +#endif /* _COAP_LIST_H_ */ diff --git a/include/coap/coap_time.h b/include/coap/coap_time.h index 9357e5ff7d..bd877c675b 100644 --- a/include/coap/coap_time.h +++ b/include/coap/coap_time.h @@ -33,17 +33,17 @@ typedef uint32_t coap_tick_t; typedef uint32_t coap_time_t; typedef int32_t coap_tick_diff_t; -static inline void coap_ticks_impl(coap_tick_t *t) { +COAP_STATIC_INLINE void coap_ticks_impl(coap_tick_t *t) { *t = sys_now(); } -static inline void coap_clock_init_impl(void) { +COAP_STATIC_INLINE void coap_clock_init_impl(void) { } #define coap_clock_init coap_clock_init_impl #define coap_ticks coap_ticks_impl -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { return t / COAP_TICKS_PER_SECOND; } #endif @@ -63,20 +63,20 @@ typedef int coap_tick_diff_t; #define COAP_TICKS_PER_SECOND CLOCK_SECOND -static inline void coap_clock_init(void) { +COAP_STATIC_INLINE void coap_clock_init(void) { clock_init(); } -static inline void coap_ticks(coap_tick_t *t) { +COAP_STATIC_INLINE void coap_ticks(coap_tick_t *t) { *t = clock_time(); } -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { return t / COAP_TICKS_PER_SECOND; } #endif /* WITH_CONTIKI */ -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) /** * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND * resolution. @@ -119,13 +119,13 @@ void coap_ticks(coap_tick_t *t); * point (seconds since epoch on POSIX). */ coap_time_t coap_ticks_to_rt(coap_tick_t t); -#endif /* WITH_POSIX */ +#endif /* !WITH_LWIP && !WITH_CONTIKI */ /** * Returns @c 1 if and only if @p a is less than @p b where less is defined on a * signed data type. */ -static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { +COAP_STATIC_INLINE int coap_time_lt(coap_tick_t a, coap_tick_t b) { return ((coap_tick_diff_t)(a - b)) < 0; } @@ -133,7 +133,7 @@ static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { * Returns @c 1 if and only if @p a is less than or equal @p b where less is * defined on a signed data type. */ -static inline int coap_time_le(coap_tick_t a, coap_tick_t b) { +COAP_STATIC_INLINE int coap_time_le(coap_tick_t a, coap_tick_t b) { return a == b || coap_time_lt(a,b); } diff --git a/include/coap/encode.h b/include/coap/encode.h index 283343d022..fb268b269e 100644 --- a/include/coap/encode.h +++ b/include/coap/encode.h @@ -10,10 +10,10 @@ #ifndef _COAP_ENCODE_H_ #define _COAP_ENCODE_H_ -#if (BSD >= 199103) || defined(WITH_CONTIKI) -# include -#else +#ifdef HAVE_STRINGS_H # include +#else +# include #endif #define Nn 8 /* duplicate definition of N if built on sky motes */ diff --git a/include/coap/libcoap.h b/include/coap/libcoap.h index 214b9e235e..5e0c9c0383 100644 --- a/include/coap/libcoap.h +++ b/include/coap/libcoap.h @@ -10,6 +10,8 @@ #ifndef _LIBCOAP_H_ #define _LIBCOAP_H_ +#include "coap_config.h" + /* The non posix embedded platforms like Contiki, TinyOS, RIOT, ... doesn't have * a POSIX compatible header structure so we have to slightly do some platform * related things. Currently there is only Contiki available so we check for a @@ -18,9 +20,14 @@ * * The CONTIKI variable is within the Contiki build environment! */ -#if !defined (CONTIKI) +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H #include -#endif /* CONTIKI */ +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #endif /* _LIBCOAP_H_ */ diff --git a/include/coap/mem.h b/include/coap/mem.h index fd3c69aafd..f4bfce5d8a 100644 --- a/include/coap/mem.h +++ b/include/coap/mem.h @@ -67,14 +67,14 @@ void coap_free_type(coap_memory_tag_t type, void *p); /** * Wrapper function to coap_malloc_type() for backwards compatibility. */ -static inline void *coap_malloc(size_t size) { +COAP_STATIC_INLINE void *coap_malloc(size_t size) { return coap_malloc_type(COAP_STRING, size); } /** * Wrapper function to coap_free_type() for backwards compatibility. */ -static inline void coap_free(void *object) { +COAP_STATIC_INLINE void coap_free(void *object) { coap_free_type(COAP_STRING, object); } @@ -86,7 +86,7 @@ static inline void coap_free(void *object) { /* no initialization needed with lwip (or, more precisely: lwip must be * completely initialized anyway by the time coap gets active) */ -static inline void coap_memory_init(void) {} +COAP_STATIC_INLINE void coap_memory_init(void) {} /* It would be nice to check that size equals the size given at the memp * declaration, but i currently don't see a standard way to check that without @@ -98,11 +98,11 @@ static inline void coap_memory_init(void) {} /* Those are just here to make uri.c happy where string allocation has not been * made conditional. */ -static inline void *coap_malloc(size_t size) { +COAP_STATIC_INLINE void *coap_malloc(size_t size) { LWIP_ASSERT("coap_malloc must not be used in lwIP", 0); } -static inline void coap_free(void *pointer) { +COAP_STATIC_INLINE void coap_free(void *pointer) { LWIP_ASSERT("coap_free must not be used in lwIP", 0); } diff --git a/include/coap/net.h b/include/coap/net.h index 014b4903ab..ea0a288d20 100644 --- a/include/coap/net.h +++ b/include/coap/net.h @@ -13,7 +13,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H #include +#endif #include #ifdef WITH_LWIP @@ -137,7 +139,7 @@ typedef struct coap_context_t { * @param context The context to register the handler for. * @param handler The response handler to register. */ -static inline void +COAP_STATIC_INLINE void coap_register_response_handler(coap_context_t *context, coap_response_handler_t handler) { context->response_handler = handler; @@ -149,7 +151,7 @@ coap_register_response_handler(coap_context_t *context, * @param ctx The context to use. * @param type The option type to register. */ -inline static void +COAP_STATIC_INLINE void coap_register_option(coap_context_t *ctx, unsigned char type) { coap_option_setb(ctx->known_options, type); } @@ -185,7 +187,7 @@ coap_context_t *coap_new_context(const coap_address_t *listen_addr); * * @return Incremented message id in network byte order. */ -static inline unsigned short +COAP_STATIC_INLINE unsigned short coap_new_message_id(coap_context_t *context) { context->message_id++; #ifndef WITH_CONTIKI @@ -342,7 +344,7 @@ coap_tid_t coap_send_ack(coap_context_t *context, * @return The transaction id if RST was sent or @c * COAP_INVALID_TID on error. */ -static inline coap_tid_t +COAP_STATIC_INLINE coap_tid_t coap_send_rst(coap_context_t *context, const coap_endpoint_t *local_interface, const coap_address_t *dst, @@ -420,7 +422,7 @@ int coap_remove_from_queue(coap_queue_t **queue, * * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) { coap_queue_t *node; if (!coap_remove_from_queue(queue, id, &node)) diff --git a/include/coap/option.h b/include/coap/option.h index ace2b81c71..f1da48ae94 100644 --- a/include/coap/option.h +++ b/include/coap/option.h @@ -32,6 +32,17 @@ typedef struct { unsigned char *value; } coap_option_t; +/** Representation of the association between a CoAP option key and its + * data type and valid data length ranges. + */ +typedef struct +{ + unsigned short key; /**< The ID of the option the following values apply to. */ + unsigned char type; /**< The type of the option: u=uint, s=string, o=opaque. */ + unsigned int min; /**< The minimum number of bytes allowed for the option data */ + unsigned int max; /**< The maximum number of bytes allowed for the option data */ +} coap_option_def_t; + /** * Parses the option pointed to by @p opt into @p result. This function returns * the number of bytes that have been parsed, or @c 0 on error. An error is @@ -142,7 +153,7 @@ typedef uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE]; * * @param f The filter to clear. */ -static inline void +COAP_STATIC_INLINE void coap_option_filter_clear(coap_opt_filter_t f) { memset(f, 0, sizeof(coap_opt_filter_t)); } @@ -195,7 +206,7 @@ int coap_option_filter_get(const coap_opt_filter_t filter, unsigned short type); * * @return @c 1 if bit was set, @c -1 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_option_setb(coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_set(filter, type) ? 1 : -1; } @@ -212,7 +223,7 @@ coap_option_setb(coap_opt_filter_t filter, unsigned short type) { * * @return @c 1 if bit was set, @c -1 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_unset(filter, type) ? 1 : -1; } @@ -229,7 +240,7 @@ coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { * * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. */ -inline static int +COAP_STATIC_INLINE int coap_option_getb(const coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_get(filter, type); } @@ -402,6 +413,16 @@ unsigned short coap_opt_length(const coap_opt_t *opt); */ unsigned char *coap_opt_value(coap_opt_t *opt); +/** + * Returns a pointer to the coap option range definitions. @key + * must be a valid option ID. This function returns @c NULL if + * @p key is not a valid option ID. + * + * @param key The option ID whose definition should be returned. + * @return A pointer to the option definition. + */ +coap_option_def_t* coap_opt_def(unsigned short key); + /** @deprecated { Use coap_opt_value() instead. } */ #define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt) diff --git a/include/coap/pdu.h b/include/coap/pdu.h index e60dadca8b..fffdbc7a7a 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -21,6 +21,11 @@ #include #endif +#ifdef __cplusplus +extern "C" +{ +#endif + #define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ #define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ #ifndef COAP_MAX_PDU_SIZE @@ -53,11 +58,14 @@ #define COAP_REQUEST_DELETE 4 /* CoAP option types (be sure to update check_critical when adding options */ +/* See http://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers */ #define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */ #define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */ #define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */ #define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */ +#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ +#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE #define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */ #define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */ #define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */ @@ -71,15 +79,11 @@ #define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */ #define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */ -/* option types from draft-ietf-coap-observe-09 */ +/* selected option types from draft-core-block-21 */ -#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ -#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE - -/* selected option types from draft-core-block-04 */ - -#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */ -#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */ +#define COAP_OPTION_BLOCK2 23 /* C, uint, 0-3 B, (none) */ +#define COAP_OPTION_BLOCK1 27 /* C, uint, 0-3 B, (none) */ +#define COAP_OPTION_SIZE2 28 /* E, uint, 0-4 B, (none) */ /* selected option types from draft-tcs-coap-no-response-option-11 */ @@ -171,28 +175,92 @@ typedef int coap_tid_t; */ #define COAP_DROPPED_RESPONSE -2 +#define COAP_TCP_HEADER_NO_FIELD 2 +#define COAP_TCP_HEADER_8_BIT 3 +#define COAP_TCP_HEADER_16_BIT 4 +#define COAP_TCP_HEADER_32_BIT 6 + +#define COAP_TCP_LENGTH_FIELD_8_BIT 13 +#define COAP_TCP_LENGTH_FIELD_16_BIT 269 +#define COAP_TCP_LENGTH_FIELD_32_BIT 65805 + +#define COAP_TCP_LENGTH_LIMIT_8_BIT 13 +#define COAP_TCP_LENGTH_LIMIT_16_BIT 256 +#define COAP_TCP_LENGTH_LIMIT_32_BIT 65536 + +#define COAP_TCP_LENGTH_FIELD_NUM_8_BIT 13 +#define COAP_TCP_LENGTH_FIELD_NUM_16_BIT 14 +#define COAP_TCP_LENGTH_FIELD_NUM_32_BIT 15 + +#define COAP_OPTION_FIELD_8_BIT 12 +#define COAP_OPTION_FIELD_16_BIT 256 +#define COAP_OPTION_FIELD_32_BIT 65536 + +typedef enum { + COAP_UDP = 0, +#ifdef WITH_TCP + COAP_TCP, + COAP_TCP_8BIT, + COAP_TCP_16BIT, + COAP_TCP_32BIT +#endif +} coap_transport_t; + #ifdef WORDS_BIGENDIAN typedef struct { - unsigned int version:2; /* protocol version */ - unsigned int type:2; /* type flag */ - unsigned int token_length:4; /* length of Token */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* message id */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; + unsigned short version:2; /* protocol version */ + unsigned short type:2; /* type flag */ + unsigned short token_length:4; /* length of Token */ + unsigned short code:8; /* request method (value 1--10) or response + code (value 40-255) */ + unsigned short id; /* message id */ + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_udp_t; #else typedef struct { - unsigned int token_length:4; /* length of Token */ - unsigned int type:2; /* type flag */ - unsigned int version:2; /* protocol version */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* transaction id (network byte order!) */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; + unsigned short token_length:4; /* length of Token */ + unsigned short type:2; /* type flag */ + unsigned short version:2; /* protocol version */ + unsigned short code:8; /* request method (value 1--10) or response + code (value 40-255) */ + unsigned short id; /* transaction id (network byte order!) */ + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_udp_t; #endif +#ifdef WITH_TCP +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_NO_FIELD]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_t; + +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_8_BIT]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_8bit_t; + +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_16_BIT]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_16bit_t; + +typedef struct { + unsigned char header_data[6]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_32bit_t; + +typedef union { + coap_hdr_udp_t udp; + coap_hdr_tcp_t tcp; + coap_hdr_tcp_8bit_t tcp_8bit; + coap_hdr_tcp_16bit_t tcp_16bit; + coap_hdr_tcp_32bit_t tcp_32bit; +} coap_hdr_transport_t; +#endif /* WITH_TCP */ + +// Typedef for backwards compatibility. +typedef coap_hdr_udp_t coap_hdr_t; + #define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0) #define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \ && ((MSG)->code < 32)) @@ -226,10 +294,18 @@ typedef struct { typedef struct { size_t max_size; /**< allocated storage for options and data */ - coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. - * This may or may not equal (coap_hdr_t*)(pdu+1) - * depending on the memory management - * implementation. */ + union { + coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. + * This may or may not equal (coap_hdr_t*)(pdu+1) + * depending on the memory management + * implementation. */ +#ifdef WITH_TCP + coap_hdr_transport_t *transport_hdr; /**< Address of the first byte of the CoAP message. + * This may or may not equal (coap_hdr_t*)(pdu+1) + * depending on the memory management + * implementation. */ + }; +#endif unsigned short max_delta; /**< highest option number */ unsigned short length; /**< PDU length (including header, options, data) */ unsigned char *data; /**< payload */ @@ -308,6 +384,15 @@ void coap_pdu_clear(coap_pdu_t *pdu, size_t size); */ coap_pdu_t *coap_new_pdu(void); +/** + * Creates a new CoAP PDU. The object is created on the heap and must be released + * using coap_delete_pdu(); + * + * @deprecated This function allocates the maximum storage for each + * PDU. Use coap_pdu_init2() instead. + */ +coap_pdu_t *coap_new_pdu2(coap_transport_t transport, unsigned int size); + void coap_delete_pdu(coap_pdu_t *); /** @@ -326,6 +411,106 @@ int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result); +/** + * Parses @p data into the CoAP PDU structure given in @p result. This + * function returns @c 0 on error or a number greater than zero on + * success. + * + * @param data The raw data to parse as CoAP PDU + * @param length The actual size of @p data + * @param result The PDU structure to fill. Note that the structure must + * provide space for at least @p length bytes to hold the + * entire CoAP PDU. + * @param transport The transport type. + * @return A value greater than zero on success or @c 0 on error. + */ +int coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, + coap_transport_t transport); + +#ifdef WITH_TCP +/** + * Get total pdu size including header + option + payload (with marker) from pdu data. + * + * @param data The raw data to parse as CoAP PDU. + * @param size payload size of pdu. + * @return Total message length. + */ +size_t coap_get_total_message_length(const unsigned char *data, size_t size); + +/** + * Get transport type of coap header for coap over tcp + * through payload size(including payload marker) + option size. + * + * @param size payload size of pdu. + * @return The transport type. + */ +coap_transport_t coap_get_tcp_header_type_from_size(unsigned int size); + +/** + * Get transport type of coap header for coap over tcp + * through first nibble(0~E) of init-byte . + * + * @param legnth length value of init byte. +* @return The transport type. + */ +coap_transport_t coap_get_tcp_header_type_from_initbyte(unsigned int length); + +/** + * Add length of option/payload into 'Len+ byte...' field of coap header + * for coap over tcp. + * + * @param pdu The pdu pointer. + * @param transport The transport type. + * @param length length value of init byte. + */ +void coap_add_length(const coap_pdu_t *pdu, coap_transport_t transport, + unsigned int length); + +/** + * Get the length of option/payload field of coap header for coap over tcp. + * + * @param pdu The pdu pointer. + * @param transport The transport type. + * @return length value of init byte. + */ +unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_t transport); + +/** + * Get the length of option/payload field of coap header for coap over tcp. + * + * @param header The header to parse. + * @return transport The transport type. + */ +unsigned int coap_get_length_from_header(const unsigned char *header, + coap_transport_t transport); + +/** + * Get length of header including len, TKL, Len+bytes, Code, token bytes for coap over tcp. + * + * @param data The raw data to parse as CoAP PDU + * @return header length + token length + */ +unsigned int coap_get_tcp_header_length(unsigned char *data); + +/** + * Get length of header including len, TKL, Len+bytes, Code + * without token bytes for coap over tcp. + * + * @param transport The transport type. + * @return header length. + */ +unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport); + +/** + * Get option length. + * + * @param key delta of option + * @param length length of option + * @return total option length + */ +size_t coap_get_opt_header_length(unsigned short key, size_t length); +#endif /* WITH_TCP */ + /** * Adds token of length @p len to @p pdu. * Adding the token destroys any following contents of the pdu. Hence options @@ -344,8 +529,23 @@ int coap_add_token(coap_pdu_t *pdu, const unsigned char *data); /** - * Adds option of given type to pdu that is passed as first - * parameter. + * Adds token of length @p len to @p pdu. Adding the token destroys + * any following contents of the pdu. Hence options and data must be + * added after coap_add_token2() has been called. In @p pdu, length is + * set to @p len + @c 4, and max_delta is set to @c 0. This funtion + * returns @c 0 on error or a value greater than zero on success. + * + * @param pdu The pdu pointer. + * @param len The length of the new token. + * @param data The token to add. + * @param transport The transport type. + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, + coap_transport_t transport); + +/** + * Adds option of given type to pdu that is passed as first parameter. * coap_add_option() destroys the PDU's data, so coap_add_data() must be called * after all options have been added. As coap_add_token() destroys the options * following the token, the token must be added before coap_add_option() is @@ -356,6 +556,17 @@ size_t coap_add_option(coap_pdu_t *pdu, unsigned int len, const unsigned char *data); +/** + * Adds option of given type to pdu that is passed as first + * parameter. coap_add_option2() destroys the PDU's data, so + * coap_add_data() must be called after all options have been added. + * As coap_add_token2() destroys the options following the token, + * the token must be added before coap_add_option2() is called. + * This function returns the number of bytes written or @c 0 on error. + */ +size_t coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, + const unsigned char *data, coap_transport_t transport); + /** * Adds option of given type to pdu that is passed as first parameter, but does * not write a value. It works like coap_add_option with respect to calling @@ -385,4 +596,7 @@ int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data); +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* _COAP_PDU_H_ */ diff --git a/include/coap/prng.h b/include/coap/prng.h index da6d953440..881d62b4be 100644 --- a/include/coap/prng.h +++ b/include/coap/prng.h @@ -28,7 +28,7 @@ * prng(). You might want to change prng() to use a better PRNG on your specific * platform. */ -static inline int +COAP_STATIC_INLINE int coap_prng_impl(unsigned char *buf, size_t len) { while (len--) *buf++ = rand() & 0xFF; @@ -44,7 +44,7 @@ coap_prng_impl(unsigned char *buf, size_t len) { * prng(). You might want to change prng() to use a better PRNG on your specific * platform. */ -static inline int +COAP_STATIC_INLINE int contiki_prng_impl(unsigned char *buf, size_t len) { unsigned short v = random_rand(); while (len > sizeof(v)) { @@ -63,7 +63,7 @@ contiki_prng_impl(unsigned char *buf, size_t len) { #endif /* WITH_CONTIKI */ #if defined(WITH_LWIP) && defined(LWIP_RAND) -static inline int +COAP_STATIC_INLINE int lwip_prng_impl(unsigned char *buf, size_t len) { u32_t v = LWIP_RAND(); while (len > sizeof(v)) { diff --git a/include/coap/resource.h b/include/coap/resource.h index 9c7b45ced6..a2ac0156eb 100644 --- a/include/coap/resource.h +++ b/include/coap/resource.h @@ -115,7 +115,7 @@ coap_resource_t *coap_resource_init(const unsigned char *uri, * @p mode which must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON * or @c COAP_RESOURCE_FLAGS_NOTIFY_CON. */ -static inline void +COAP_STATIC_INLINE void coap_resource_set_mode(coap_resource_t *r, int mode) { r->flags = (r->flags & !COAP_RESOURCE_FLAGS_NOTIFY_CON) | mode; } @@ -244,7 +244,7 @@ coap_print_status_t coap_print_link(const coap_resource_t *resource, * @param method The CoAP request method to handle. * @param handler The handler to register with @p resource. */ -static inline void +COAP_STATIC_INLINE void coap_register_handler(coap_resource_t *resource, unsigned char method, coap_method_handler_t handler) { diff --git a/src/address.c b/src/address.c index e237881a7a..3cb8c5bed4 100644 --- a/src/address.c +++ b/src/address.c @@ -6,10 +6,19 @@ * README for terms of use. */ -#ifdef WITH_POSIX +#include "coap_config.h" + +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) #include +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #include "address.h" @@ -37,12 +46,11 @@ coap_address_equals(const coap_address_t *a, const coap_address_t *b) { return 0; } -#else /* WITH_POSIX */ +#else /* WITH_LWIP || WITH_CONTIKI */ /* make compilers happy that do not like empty modules */ -static inline void dummy() +COAP_STATIC_INLINE void dummy() { } -#endif /* not WITH_POSIX */ - +#endif diff --git a/src/block.c b/src/block.c index a82037a97d..f13ba1a134 100644 --- a/src/block.c +++ b/src/block.c @@ -49,7 +49,7 @@ coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { assert(block); memset(block, 0, sizeof(coap_block_t)); - if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) { + if (pdu && (option = coap_check_option(pdu, type, &opt_iter) != NULL)) { block->szx = COAP_OPT_BLOCK_SZX(option); if (COAP_OPT_BLOCK_MORE(option)) block->m = 1; @@ -68,6 +68,12 @@ coap_write_block_opt(coap_block_t *block, unsigned short type, assert(pdu); + /* Block2 */ + if (type != COAP_OPTION_BLOCK2) { + warn("coap_write_block_opt: skipped unknown option\n"); + return -1; + } + start = block->num << (block->szx + 4); if (data_length <= start) { debug("illegal block requested\n"); diff --git a/src/coap_io.c b/src/coap_io.c index cbf2263d79..5a87515b11 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -17,10 +17,28 @@ #endif #ifdef HAVE_SYS_SOCKET_H # include +# define OPTVAL_T(t) (t) +# define CLOSE_SOCKET(fd) close(fd) +# define COAP_SOCKET_ERROR (-1) +# define COAP_INVALID_SOCKET (-1) +typedef int coap_socket_t; #endif #ifdef HAVE_NETINET_IN_H # include #endif +#ifdef HAVE_WS2TCPIP_H +# include +# define OPTVAL_T(t) (const char*)(t) +# define CLOSE_SOCKET(fd) closesocket(fd) +# define COAP_SOCKET_ERROR SOCKET_ERROR +# define COAP_INVALID_SOCKET INVALID_SOCKET +# undef CMSG_DATA +# define CMSG_DATA WSA_CMSG_DATA +# define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR +# define CMSG_LEN WSA_CMSG_LEN +# define CMSG_SPACE WSA_CMSG_SPACE +typedef SOCKET coap_socket_t; +#endif #ifdef HAVE_SYS_UIO_H # include #endif @@ -37,12 +55,12 @@ #include "mem.h" #include "coap_io.h" -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) struct coap_packet_t { coap_if_handle_t hnd; /**< the interface handle */ coap_address_t src; /**< the packet's source address */ coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; + const coap_endpoint_t *endpoint; int ifindex; void *session; /**< opaque session data */ @@ -57,7 +75,7 @@ struct coap_packet_t { #ifdef WITH_CONTIKI static int ep_initialized = 0; -static inline struct coap_endpoint_t * +COAP_STATIC_INLINE struct coap_endpoint_t * coap_malloc_contiki_endpoint() { static struct coap_endpoint_t ep; @@ -69,7 +87,7 @@ coap_malloc_contiki_endpoint() { } } -static inline void +COAP_STATIC_INLINE void coap_free_contiki_endpoint(struct coap_endpoint_t *ep) { ep_initialized = 0; } @@ -106,42 +124,42 @@ coap_free_endpoint(coap_endpoint_t *ep) { } #else /* WITH_CONTIKI */ -static inline struct coap_endpoint_t * +COAP_STATIC_INLINE struct coap_endpoint_t * coap_malloc_posix_endpoint(void) { return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t)); } -static inline void +COAP_STATIC_INLINE void coap_free_posix_endpoint(struct coap_endpoint_t *ep) { coap_free(ep); } coap_endpoint_t * coap_new_endpoint(const coap_address_t *addr, int flags) { - int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); + coap_socket_t sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); int on = 1; struct coap_endpoint_t *ep; - if (sockfd < 0) { + if (sockfd == COAP_INVALID_SOCKET) { coap_log(LOG_WARNING, "coap_new_endpoint: socket"); return NULL; } - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR"); on = 1; switch(addr->addr.sa.sa_family) { case AF_INET: - if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IP_PKTINFO\n"); break; case AF_INET6: #ifdef IPV6_RECVPKTINFO - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_RECVPKTINFO\n"); #else /* IPV6_RECVPKTINFO */ - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_PKTINFO\n"); #endif /* IPV6_RECVPKTINFO */ break; @@ -149,16 +167,16 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { coap_log(LOG_ALERT, "coap_new_endpoint: unsupported sa_family\n"); } - if (bind(sockfd, &addr->addr.sa, addr->size) < 0) { + if (bind(sockfd, &addr->addr.sa, addr->size) == COAP_SOCKET_ERROR) { coap_log(LOG_WARNING, "coap_new_endpoint: bind"); - close (sockfd); + CLOSE_SOCKET(sockfd); return NULL; } ep = coap_malloc_posix_endpoint(); if (!ep) { coap_log(LOG_WARNING, "coap_new_endpoint: malloc"); - close(sockfd); + CLOSE_SOCKET(sockfd); return NULL; } @@ -167,9 +185,9 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { ep->flags = flags; ep->addr.size = addr->size; - if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) { + if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) == COAP_SOCKET_ERROR) { coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address"); - close (sockfd); + CLOSE_SOCKET(sockfd); return NULL; } @@ -193,9 +211,9 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { void coap_free_endpoint(coap_endpoint_t *ep) { - if(ep) { + if (ep) { if (ep->handle.fd >= 0) - close(ep->handle.fd); + CLOSE_SOCKET(ep->handle.fd); coap_free_posix_endpoint((struct coap_endpoint_t *)ep); } } @@ -221,8 +239,8 @@ struct in_pktinfo { }; #endif -#if defined(WITH_POSIX) && !defined(SOL_IP) -/* Solaris expects level IPPROTO_IP for ancillary data. */ +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(SOL_IP) +/* Solaris and Windows expect level IPPROTO_IP for ancillary data. */ #define SOL_IP IPPROTO_IP #endif @@ -245,28 +263,43 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef WITH_CONTIKI /* a buffer large enough to hold all protocol address types */ char buf[CMSG_LEN(sizeof(struct sockaddr_storage))]; + assert(local_interface); + +#ifdef WSA_CMSG_SPACE + WSAMSG mhdr; + WSABUF dataBuf; + + memset(&mhdr, 0, sizeof(mhdr)); + + mhdr.name = (PSOCKADDR)&dst->addr.sa; + mhdr.lpBuffers = &dataBuf; + mhdr.dwBufferCount = 1; +#else struct msghdr mhdr; struct iovec iov[1]; - assert(local_interface); - iov[0].iov_base = data; iov[0].iov_len = datalen; - memset(&mhdr, 0, sizeof(struct msghdr)); + memset(&mhdr, 0, sizeof(mhdr)); mhdr.msg_name = (void *)&dst->addr; mhdr.msg_namelen = dst->size; mhdr.msg_iov = iov; mhdr.msg_iovlen = 1; + mhdr.msg_control = buf; +#endif switch (dst->addr.sa.sa_family) { case AF_INET6: { struct cmsghdr *cmsg; struct in6_pktinfo *pktinfo; - mhdr.msg_control = buf; +#ifdef WSA_CMSG_SPACE + mhdr.Control.len = CMSG_SPACE(sizeof(struct in6_pktinfo)); +#else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); +#endif cmsg = CMSG_FIRSTHDR(&mhdr); cmsg->cmsg_level = IPPROTO_IPV6; @@ -294,8 +327,11 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct cmsghdr *cmsg; struct in_pktinfo *pktinfo; - mhdr.msg_control = buf; +#ifdef WSA_CMSG_SPACE + mhdr.Control.len = CMSG_SPACE(sizeof(struct in_pktinfo)); +#else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); +#endif cmsg = CMSG_FIRSTHDR(&mhdr); cmsg->cmsg_level = SOL_IP; @@ -309,12 +345,30 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, /* We cannot send with multicast address as source address * and hence let the kernel pick the outgoing interface. */ pktinfo->ipi_ifindex = 0; + +#ifdef WSA_CMSG_SPACE + /* OS's without ipi_spec_dst put the source address in ipi_addr. */ + memset(&pktinfo->ipi_addr, 0, sizeof(pktinfo->ipi_addr)); +#else + /* OS's with ipi_spec_dst seem to put the source address in ipi_spec_dst + * which is apparently a misnomer. */ memset(&pktinfo->ipi_spec_dst, 0, sizeof(pktinfo->ipi_spec_dst)); +#endif } else { pktinfo->ipi_ifindex = ep->ifindex; + +#ifdef WSA_CMSG_SPACE + /* OS's without ipi_spec_dst put the source address in ipi_addr. */ + memcpy(&pktinfo->ipi_addr, + &local_interface->addr.addr.sin.sin_addr, + local_interface->addr.size); +#else + /* OS's with ipi_spec_dst seem to put the source address in ipi_spec_dst + * which is apparently a misnomer. */ memcpy(&pktinfo->ipi_spec_dst, &local_interface->addr.addr.sin.sin_addr, local_interface->addr.size); +#endif } break; } @@ -339,8 +393,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef CUSTOM_COAP_NETWORK_READ #define SIN6(A) ((struct sockaddr_in6 *)(A)) - -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) static coap_packet_t * coap_malloc_packet(void) { coap_packet_t *packet; @@ -359,7 +412,7 @@ coap_free_packet(coap_packet_t *packet) { } #endif /* WITH_POSIX */ #ifdef WITH_CONTIKI -static inline coap_packet_t * +COAP_STATIC_INLINE coap_packet_t * coap_malloc_packet(void) { return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0); } @@ -370,7 +423,7 @@ coap_free_packet(coap_packet_t *packet) { } #endif /* WITH_CONTIKI */ -static inline size_t +COAP_STATIC_INLINE size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { return COAP_MAX_PDU_SIZE; } @@ -378,7 +431,7 @@ coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { void coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) { - target->handle = packet->interface->handle; + target->handle = packet->endpoint->handle; memcpy(&target->addr, &packet->dst, sizeof(target->addr)); target->ifindex = packet->ifindex; target->flags = 0; /* FIXME */ @@ -400,7 +453,7 @@ coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t * local interface with address @p local. This function returns @c 1 * if @p dst is a valid match, and @c 0 otherwise. */ -static inline int +COAP_STATIC_INLINE int is_local_if(const coap_address_t *local, const coap_address_t *dst) { return coap_address_isany(local) || coap_address_equals(dst, local) || coap_is_mcast(dst); @@ -457,7 +510,7 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { /* use getsockname() to get the local port */ (*packet)->dst.size = sizeof((*packet)->dst.addr); - if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) { + if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) == COAP_SOCKET_ERROR) { coap_log(LOG_DEBUG, "cannot determine local port\n"); goto error; } @@ -565,7 +618,7 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { #error "coap_network_read() not implemented on this platform" #endif - (*packet)->interface = ep; + (*packet)->endpoint = ep; return len; error: diff --git a/src/coap_list.c b/src/coap_list.c new file mode 100644 index 0000000000..1932d4e6c9 --- /dev/null +++ b/src/coap_list.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.c -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +#include "coap_config.h" + +#include +#include + +#include "debug.h" +#include "mem.h" +#include "coap_list.h" + +int +coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *node)) { + coap_list_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) { + *queue = node; + return 1; + } + + /* replace queue head if new node has to be added before the existing queue head */ + q = *queue; + if (order(node->data, q->data) < 0) { + node->next = q; + *queue = node; + return 1; + } + + /* search for right place to insert */ + do { + p = q; + q = q->next; + } while (q && order(node->data, q->data) >= 0); + + /* insert new item */ + node->next = q; + p->next = node; + return 1; +} + +int +coap_delete(coap_list_t *node) { + if (!node) + return 0; + + if (node->delete_func) + node->delete_func(node->data); + coap_free( node->data); + coap_free( node); + + return 1; +} + +void +coap_delete_list(coap_list_t *queue) { + coap_list_t *elt, *tmp; + + if (!queue) + return; + + LL_FOREACH_SAFE(queue, elt, tmp) { + coap_delete(elt); + } +} + +coap_list_t * +coap_new_listnode(void *data, void (*delete_func)(void *)) { + coap_list_t *node = (coap_list_t *)coap_malloc(sizeof(coap_list_t)); + if (!node) { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_listnode: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof(coap_list_t)); + node->data = data; + node->delete_func = delete_func; + return node; +} diff --git a/src/coap_time.c b/src/coap_time.c index 1f991755ea..356f5ea4f9 100644 --- a/src/coap_time.c +++ b/src/coap_time.c @@ -6,12 +6,13 @@ * README for terms of use. */ +#include "coap_config.h" + #ifdef WITH_POSIX #include #include #include /* _POSIX_TIMERS */ -#include "coap_config.h" #include "coap_time.h" static coap_time_t coap_clock_offset = 0; @@ -90,7 +91,7 @@ coap_ticks_to_rt(coap_tick_t t) { #else /* WITH_POSIX */ /* make compilers happy that do not like empty modules */ -static inline void dummy() +COAP_STATIC_INLINE void dummy() { } diff --git a/src/debug.c b/src/debug.c index e62a4edf30..d36e1e70bc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -7,6 +7,7 @@ */ #include "coap_config.h" +#include "coap.h" #if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 @@ -23,6 +24,12 @@ #ifdef HAVE_ARPA_INET_H #include +#if defined(__ANDROID__) +typedef __uint16_t in_port_t; +#endif +#endif +#ifdef HAVE_WS2TCPIP_H +#include #endif #ifdef HAVE_TIME_H @@ -73,7 +80,7 @@ static char *loglevels[] = { #ifdef HAVE_TIME_H -static inline size_t +COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t) { struct tm *tmp; time_t now = coap_ticks_to_rt(t); @@ -83,7 +90,7 @@ print_timestamp(char *s, size_t len, coap_tick_t t) { #else /* alternative implementation: just print the timestamp */ -static inline size_t +COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t) { #ifdef HAVE_SNPRINTF return snprintf(s, len, "%u.%03u", @@ -108,7 +115,7 @@ print_timestamp(char *s, size_t len, coap_tick_t t) { * * @return The length of @p s. */ -static inline size_t +COAP_STATIC_INLINE size_t strnlen(const char *s, size_t maxlen) { size_t n = 0; while(*s++ && n < maxlen) @@ -160,7 +167,7 @@ print_readable( const unsigned char *data, unsigned int len, size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#ifdef HAVE_ARPA_INET_H +#if defined(HAVE_ARPA_INET_H) || defined(_WIN32) const void *addrptr = NULL; in_port_t port; unsigned char *p = buf; @@ -362,7 +369,7 @@ print_content_format(unsigned int format_type, * to carry binary data. The return value @c 0 hence indicates * printable data which is also assumed if @p content_format is @c 01. */ -static inline int +COAP_STATIC_INLINE int is_binary(int content_format) { return !(content_format == -1 || content_format == COAP_MEDIATYPE_TEXT_PLAIN || diff --git a/src/encode.c b/src/encode.c index 10c0c6c939..8c1ef5c9ae 100644 --- a/src/encode.c +++ b/src/encode.c @@ -14,7 +14,8 @@ #include "encode.h" /* Carsten suggested this when fls() is not available: */ -int coap_fls(unsigned int i) { +int +coap_fls(unsigned int i) { int n; for (n = 0; i; n++) i >>= 1; diff --git a/src/net.c b/src/net.c index bbdbd720ee..300bd2a7e3 100644 --- a/src/net.c +++ b/src/net.c @@ -19,7 +19,9 @@ #elif HAVE_SYS_UNISTD_H #include #endif -#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -29,6 +31,9 @@ #ifdef HAVE_ARPA_INET_H #include #endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #ifdef WITH_LWIP #include @@ -113,16 +118,16 @@ /** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_TIMEOUT */ #define ACK_TIMEOUT Q(FRAC_BITS, COAP_DEFAULT_ACK_TIMEOUT) -#if defined(WITH_POSIX) +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) time_t clock_offset; -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node(void) { return (coap_queue_t *)coap_malloc_type(COAP_NODE, sizeof(coap_queue_t)); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { coap_free_type(COAP_NODE, node); } @@ -134,12 +139,12 @@ coap_free_node(coap_queue_t *node) { static void coap_retransmittimer_execute(void *arg); static void coap_retransmittimer_restart(coap_context_t *ctx); -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node() { return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { memp_free(MEMP_COAP_NODE, node); } @@ -165,12 +170,12 @@ coap_context_t the_coap_context; PROCESS(coap_retransmit_process, "message retransmit process"); -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node() { return (coap_queue_t *)coap_malloc_type(COAP_NODE, 0); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { coap_free_type(COAP_NODE, node); } @@ -668,7 +673,7 @@ coap_send_message_type(coap_context_t *context, * value * @return COAP_TICKS_PER_SECOND * ACK_TIMEOUT * (1 + (ACK_RANDOM_FACTOR - 1) * r) */ -static inline unsigned int +COAP_STATIC_INLINE unsigned int calc_timeout(unsigned char r) { unsigned int result; @@ -969,7 +974,7 @@ coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node) } -static inline int +COAP_STATIC_INLINE int token_match(const unsigned char *a, size_t alen, const unsigned char *b, size_t blen) { return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); @@ -1120,7 +1125,7 @@ coap_new_error_response(coap_pdu_t *request, unsigned char code, * Quick hack to determine the size of the resource description for * .well-known/core. */ -static inline size_t +COAP_STATIC_INLINE size_t get_wkc_len(coap_context_t *context, coap_opt_t *query_filter) { unsigned char buf[1]; size_t len = 0; @@ -1324,7 +1329,7 @@ coap_cancel(coap_context_t *context, const coap_queue_t *sent) { * @return @c 1 if the response code matches the No-Response option, * or @c 0, otherwise. */ -static inline int +COAP_STATIC_INLINE int no_response(coap_pdu_t *request, coap_pdu_t *response) { coap_opt_t *nores; coap_opt_iterator_t opt_iter; @@ -1497,7 +1502,7 @@ handle_request(coap_context_t *context, coap_queue_t *node) { } } -static inline void +COAP_STATIC_INLINE void handle_response(coap_context_t *context, coap_queue_t *sent, coap_queue_t *rcvd) { @@ -1519,7 +1524,7 @@ handle_response(coap_context_t *context, } } -static inline int +COAP_STATIC_INLINE int #ifdef __GNUC__ handle_locally(coap_context_t *context __attribute__ ((unused)), coap_queue_t *node __attribute__ ((unused))) { diff --git a/src/option.c b/src/option.c index 60c0788d76..251c852ef1 100644 --- a/src/option.c +++ b/src/option.c @@ -143,7 +143,7 @@ coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, return oi; } -static inline int +COAP_STATIC_INLINE int opt_finished(coap_opt_iterator_t *oi) { assert(oi); @@ -420,7 +420,7 @@ typedef struct { } opt_filter; /** Returns true iff @p type denotes an option type larger than 255. */ -static inline int +COAP_STATIC_INLINE int is_long_option(unsigned short type) { return type > 255; } /** Operation specifiers for coap_filter_op(). */ diff --git a/src/pdu.c b/src/pdu.c index cf84af7cb2..64701d54b6 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -85,7 +85,7 @@ coap_pdu_init(unsigned char type, unsigned char code, return NULL; /* size must be large enough for hdr */ -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) +#if !defined(WITH_LWIP) pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); if (!pdu) return NULL; pdu->hdr = coap_malloc_type(COAP_PDU_BUF, size); diff --git a/src/resource.c b/src/resource.c index 61ab87ca89..aa4f383285 100644 --- a/src/resource.c +++ b/src/resource.c @@ -29,7 +29,7 @@ #endif -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) #define COAP_MALLOC_TYPE(Type) \ ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) @@ -50,19 +50,21 @@ coap_resources_init() { memb_init(&subscription_storage); } -static inline coap_subscription_t * +COAP_STATIC_INLINE coap_subscription_t * coap_malloc_subscription() { return memb_alloc(&subscription_storage); } -static inline void +COAP_STATIC_INLINE void coap_free_subscription(coap_subscription_t *subscription) { memb_free(&subscription_storage, subscription); } #endif /* WITH_CONTIKI */ +#ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) +#endif /* Helper functions for conditional output of character sequences into * a given buffer. The first Offset characters are skipped. diff --git a/src/uri.c b/src/uri.c index 73732b8b41..3d5af8da28 100644 --- a/src/uri.c +++ b/src/uri.c @@ -33,7 +33,7 @@ * @return A pointer to the first occurence of @p c, or @c NULL * if not found. */ -static inline unsigned char * +COAP_STATIC_INLINE unsigned char * strnchr(unsigned char *s, size_t len, unsigned char c) { while (len && *s++ != c) --len; @@ -308,7 +308,7 @@ typedef void (*segment_handler_t)(unsigned char *, size_t, void *); /** * Checks if path segment @p s consists of one or two dots. */ -static inline int +COAP_STATIC_INLINE int dots(unsigned char *s, size_t len) { return *s == '.' && (len == 1 || (*(s+1) == '.' && len == 2)); } @@ -474,7 +474,7 @@ coap_clone_uri(const coap_uri_t *uri) { /* The function signature of coap_hash() is different from * segment_handler_t hence we use this wrapper as safe typecast. */ -static inline void +COAP_STATIC_INLINE void hash_segment(unsigned char *s, size_t len, void *data) { coap_hash(s, len, data); } From c1bda6e0a4136bc3a3f981ffb4d38a984f2a4f3c Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 26 Jul 2016 17:17:27 -0700 Subject: [PATCH 02/27] Patches from IoTivity Change-Id: Idddee819530e8eb497a8abf72aa1f94a7b30d40b Signed-off-by: Dave Thaler --- coap_config.h.contiki | 1 + coap_config.h.windows | 37 ++++++ examples/client.c | 6 +- examples/coap-rd.c | 4 +- examples/etsi_iot_01.c | 6 +- include/coap/address.h | 20 +-- include/coap/async.h | 2 +- include/coap/bits.h | 6 +- include/coap/block.h | 4 +- include/coap/coap.h.in | 1 + include/coap/coap_io.h | 6 +- include/coap/coap_list.h | 48 +++++++ include/coap/coap_time.h | 20 +-- include/coap/encode.h | 6 +- include/coap/libcoap.h | 11 +- include/coap/mem.h | 10 +- include/coap/net.h | 12 +- include/coap/option.h | 29 ++++- include/coap/pdu.h | 274 ++++++++++++++++++++++++++++++++++----- include/coap/prng.h | 6 +- include/coap/resource.h | 4 +- src/address.c | 18 ++- src/block.c | 10 +- src/coap_io.c | 133 ++++++++++++++----- src/coap_list.c | 91 +++++++++++++ src/coap_time.c | 5 +- src/debug.c | 17 ++- src/encode.c | 3 +- src/net.c | 33 +++-- src/option.c | 4 +- src/pdu.c | 2 +- src/resource.c | 8 +- src/uri.c | 6 +- 33 files changed, 679 insertions(+), 164 deletions(-) create mode 100644 coap_config.h.windows create mode 100644 include/coap/coap_list.h create mode 100644 src/coap_list.c diff --git a/coap_config.h.contiki b/coap_config.h.contiki index 43bef3a4ed..66bf57e0c5 100644 --- a/coap_config.h.contiki +++ b/coap_config.h.contiki @@ -56,6 +56,7 @@ #define HAVE_STRNLEN 1 #define HAVE_SNPRINTF 1 +#define HAVE_STRINGS_H 1 /* there is no file-oriented output */ #define COAP_DEBUG_FD NULL diff --git a/coap_config.h.windows b/coap_config.h.windows new file mode 100644 index 0000000000..f44c1c71e1 --- /dev/null +++ b/coap_config.h.windows @@ -0,0 +1,37 @@ +#ifndef _COAP_CONFIG_H_ +#define _COAP_CONFIG_H_ + +/* Define to 1 if you have header file. */ +#if defined(_WIN32) +#define HAVE_WS2TCPIP_H 1 +#endif + +/* Define to 1 if you have header file. */ +#if defined(_WIN32) +#define HAVE_WINSOCK2_H 1 +#endif + +#ifdef _WIN32 +#define ssize_t SSIZE_T +#define in_port_t uint16_t +#endif + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libcoap" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libcoap 4.1.1" + +#ifndef COAP_STATIC_INLINE +# if defined(__cplusplus) +# define COAP_STATIC_INLINE inline +# else +# ifdef _MSC_VER +# define COAP_STATIC_INLINE static __inline +# else +# define COAP_STATIC_INLINE static inline +# endif +# endif +#endif + +#endif /* _COAP_CONFIG_H_ */ diff --git a/examples/client.c b/examples/client.c index 4d35dbc2ca..31fd806bfd 100644 --- a/examples/client.c +++ b/examples/client.c @@ -69,7 +69,7 @@ coap_tick_t obs_wait = 0; /* timeout for current subscription */ #define UNUSED_PARAM #endif /* GCC */ -static inline void +COAP_STATIC_INLINE void set_timeout(coap_tick_t *timer, const unsigned int seconds) { coap_ticks(timer); *timer += seconds * COAP_TICKS_PER_SECOND; @@ -305,7 +305,7 @@ resolve_address(const str *server, struct sockaddr *dst) { ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \ (Pdu)->hdr->code == COAP_RESPONSE_CODE(204))) -static inline int +COAP_STATIC_INLINE int check_token(coap_pdu_t *received) { return received->hdr->token_length == the_token.length && memcmp(received->hdr->token, the_token.s, the_token.length) == 0; @@ -808,7 +808,7 @@ cmdline_proxy(char *arg) { return 1; } -static inline void +COAP_STATIC_INLINE void cmdline_token(char *arg) { strncpy((char *)the_token.s, arg, min(sizeof(_token_data), strlen(arg))); the_token.length = strlen(arg); diff --git a/examples/coap-rd.c b/examples/coap-rd.c index 64f156f2d6..3a7efcb281 100644 --- a/examples/coap-rd.c +++ b/examples/coap-rd.c @@ -65,7 +65,7 @@ rd_t *resources = NULL; #define UNUSED_PARAM #endif /* GCC */ -static inline rd_t * +COAP_STATIC_INLINE rd_t * rd_new(void) { rd_t *rd; rd = (rd_t *)coap_malloc(sizeof(rd_t)); @@ -75,7 +75,7 @@ rd_new(void) { return rd; } -static inline void +COAP_STATIC_INLINE void rd_delete(rd_t *rd) { if (rd) { coap_free(rd->data.s); diff --git a/examples/etsi_iot_01.c b/examples/etsi_iot_01.c index 0edc8a9368..8fe0767fd6 100644 --- a/examples/etsi_iot_01.c +++ b/examples/etsi_iot_01.c @@ -88,14 +88,14 @@ coap_new_payload(size_t size) { return p; } -static inline coap_payload_t * +COAP_STATIC_INLINE coap_payload_t * coap_find_payload(const coap_key_t key) { coap_payload_t *p; HASH_FIND(hh, test_resources, key, sizeof(coap_key_t), p); return p; } -static inline void +COAP_STATIC_INLINE void coap_add_payload(const coap_key_t key, coap_payload_t *payload, coap_dynamic_uri_t *uri) { assert(payload); @@ -109,7 +109,7 @@ coap_add_payload(const coap_key_t key, coap_payload_t *payload, } } -static inline void +COAP_STATIC_INLINE void coap_delete_payload(coap_payload_t *payload) { if (payload) { coap_dynamic_uri_t *uri; diff --git a/include/coap/address.h b/include/coap/address.h index fe2e89d4c2..1ebf578ecd 100644 --- a/include/coap/address.h +++ b/include/coap/address.h @@ -52,7 +52,7 @@ typedef struct coap_address_t { #define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) #endif /* WITH_CONTIKI */ -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) /** multi-purpose address abstraction */ typedef struct coap_address_t { socklen_t size; /**< size of addr */ @@ -71,7 +71,7 @@ typedef struct coap_address_t { */ int coap_address_equals(const coap_address_t *a, const coap_address_t *b); -static inline int +COAP_STATIC_INLINE int _coap_address_isany_impl(const coap_address_t *a) { /* need to compare only relevant parts of sockaddr_in6 */ switch (a->addr.sa.sa_family) { @@ -88,7 +88,7 @@ _coap_address_isany_impl(const coap_address_t *a) { return 0; } -static inline int +COAP_STATIC_INLINE int _coap_is_mcast_impl(const coap_address_t *a) { if (!a) return 0; @@ -103,7 +103,7 @@ _coap_is_mcast_impl(const coap_address_t *a) { } return 0; } -#endif /* WITH_POSIX */ +#endif /* !WITH_LWIP && !WITH_CONTIKI */ /** * Resets the given coap_address_t object @p addr to its default values. In @@ -112,23 +112,23 @@ _coap_is_mcast_impl(const coap_address_t *a) { * * @param addr The coap_address_t object to initialize. */ -static inline void +COAP_STATIC_INLINE void coap_address_init(coap_address_t *addr) { assert(addr); memset(addr, 0, sizeof(coap_address_t)); -#ifdef WITH_POSIX +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) /* lwip and Contiki have constant address sizes and doesn't need the .size part */ addr->size = sizeof(addr->addr); #endif } -#ifndef WITH_POSIX +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) /** * Compares given address objects @p a and @p b. This function returns @c 1 if * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be * @c NULL; */ -static inline int +COAP_STATIC_INLINE int coap_address_equals(const coap_address_t *a, const coap_address_t *b) { assert(a); assert(b); return _coap_address_equals_impl(a, b); @@ -140,7 +140,7 @@ coap_address_equals(const coap_address_t *a, const coap_address_t *b) { * function returns @c 1 if this is the case, @c 0 otherwise. The parameters @p * a must not be @c NULL; */ -static inline int +COAP_STATIC_INLINE int coap_address_isany(const coap_address_t *a) { assert(a); return _coap_address_isany_impl(a); @@ -150,7 +150,7 @@ coap_address_isany(const coap_address_t *a) { * Checks if given address @p a denotes a multicast address. This function * returns @c 1 if @p a is multicast, @c 0 otherwise. */ -static inline int +COAP_STATIC_INLINE int coap_is_mcast(const coap_address_t *a) { return a && _coap_is_mcast_impl(a); } diff --git a/include/coap/async.h b/include/coap/async.h index 0c36defacd..3fbcc09f52 100644 --- a/include/coap/async.h +++ b/include/coap/async.h @@ -136,7 +136,7 @@ coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id); * * @param s The state object to update. */ -static inline void +COAP_STATIC_INLINE void coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); } /** @} */ diff --git a/include/coap/bits.h b/include/coap/bits.h index 0b269166d5..d7f0bf53ab 100644 --- a/include/coap/bits.h +++ b/include/coap/bits.h @@ -28,7 +28,7 @@ * * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_setb(uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; @@ -48,7 +48,7 @@ bits_setb(uint8_t *vec, size_t size, uint8_t bit) { * * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; @@ -67,7 +67,7 @@ bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { * * @return @c 1 if the bit is set, @c 0 otherwise. */ -inline static int +COAP_STATIC_INLINE int bits_getb(const uint8_t *vec, size_t size, uint8_t bit) { if (size <= (bit >> 3)) return -1; diff --git a/include/coap/block.h b/include/coap/block.h index 9ce00311cc..9535e29bb2 100644 --- a/include/coap/block.h +++ b/include/coap/block.h @@ -61,13 +61,13 @@ unsigned int coap_opt_block_num(const coap_opt_t *block_opt); * Checks if more than @p num blocks are required to deliver @p data_len * bytes of data for a block size of 1 << (@p szx + 4). */ -static inline int +COAP_STATIC_INLINE int coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) { return ((num+1) << (szx + 4)) < data_len; } /** Sets the More-bit in @p block_opt */ -static inline void +COAP_STATIC_INLINE void coap_opt_block_set_m(coap_opt_t *block_opt, int m) { if (m) *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08; diff --git a/include/coap/coap.h.in b/include/coap/coap.h.in index 76ebc5eb0d..6e18c6f64f 100644 --- a/include/coap/coap.h.in +++ b/include/coap/coap.h.in @@ -37,6 +37,7 @@ extern "C" { #include "bits.h" #include "block.h" #include "coap_io.h" +#include "coap_list.h" #include "coap_time.h" #include "debug.h" #include "encode.h" diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index 7a48b319a1..9c8b584bb7 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -33,14 +33,12 @@ struct coap_context_t; * tuple (handle, addr) must uniquely identify this endpoint. */ typedef struct coap_endpoint_t { -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) +#ifndef WITH_LWIP union { int fd; /**< on POSIX systems */ void *conn; /**< opaque connection (e.g. uip_conn in Contiki) */ } handle; /**< opaque handle to identify this endpoint */ -#endif /* WITH_POSIX or WITH_CONTIKI */ - -#ifdef WITH_LWIP +#else struct udp_pcb *pcb; /**< @FIXME --chrysn * this was added in a hurry, not sure it confirms to the overall model */ diff --git a/include/coap/coap_list.h b/include/coap/coap_list.h new file mode 100644 index 0000000000..9cbd858ae8 --- /dev/null +++ b/include/coap/coap_list.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.h -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +#ifndef _COAP_LIST_H_ +#define _COAP_LIST_H_ + +#include "utlist.h" + +struct coap_linkedlistnode { + struct coap_linkedlistnode *next; + void *data; + + /** + * Callback function that is called from coap_delete to release + * additional memory allocated by data Set to NULL if you do not + * need this. Note that data is free'd automatically. */ + void (*delete_func)(void *); +}; + +typedef struct coap_linkedlistnode coap_list_t; + +/** + * Adds node to given queue, ordered by specified order function. Returns 1 + * when insert was successful, 0 otherwise. + */ +int coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *)); + +/* destroys specified node */ +int coap_delete(coap_list_t *node); + +/* removes all items from given queue and frees the allocated storage */ +void coap_delete_list(coap_list_t *queue); + +/** + * Creates a new list node and adds the given data object. The memory allocated + * by data will be released by coap_delete() with the new node. Returns the + * new list node. + */ +coap_list_t *coap_new_listnode(void *data, void (*delete_func)(void *)); + +#endif /* _COAP_LIST_H_ */ diff --git a/include/coap/coap_time.h b/include/coap/coap_time.h index 9357e5ff7d..bd877c675b 100644 --- a/include/coap/coap_time.h +++ b/include/coap/coap_time.h @@ -33,17 +33,17 @@ typedef uint32_t coap_tick_t; typedef uint32_t coap_time_t; typedef int32_t coap_tick_diff_t; -static inline void coap_ticks_impl(coap_tick_t *t) { +COAP_STATIC_INLINE void coap_ticks_impl(coap_tick_t *t) { *t = sys_now(); } -static inline void coap_clock_init_impl(void) { +COAP_STATIC_INLINE void coap_clock_init_impl(void) { } #define coap_clock_init coap_clock_init_impl #define coap_ticks coap_ticks_impl -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { return t / COAP_TICKS_PER_SECOND; } #endif @@ -63,20 +63,20 @@ typedef int coap_tick_diff_t; #define COAP_TICKS_PER_SECOND CLOCK_SECOND -static inline void coap_clock_init(void) { +COAP_STATIC_INLINE void coap_clock_init(void) { clock_init(); } -static inline void coap_ticks(coap_tick_t *t) { +COAP_STATIC_INLINE void coap_ticks(coap_tick_t *t) { *t = clock_time(); } -static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { return t / COAP_TICKS_PER_SECOND; } #endif /* WITH_CONTIKI */ -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) /** * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND * resolution. @@ -119,13 +119,13 @@ void coap_ticks(coap_tick_t *t); * point (seconds since epoch on POSIX). */ coap_time_t coap_ticks_to_rt(coap_tick_t t); -#endif /* WITH_POSIX */ +#endif /* !WITH_LWIP && !WITH_CONTIKI */ /** * Returns @c 1 if and only if @p a is less than @p b where less is defined on a * signed data type. */ -static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { +COAP_STATIC_INLINE int coap_time_lt(coap_tick_t a, coap_tick_t b) { return ((coap_tick_diff_t)(a - b)) < 0; } @@ -133,7 +133,7 @@ static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { * Returns @c 1 if and only if @p a is less than or equal @p b where less is * defined on a signed data type. */ -static inline int coap_time_le(coap_tick_t a, coap_tick_t b) { +COAP_STATIC_INLINE int coap_time_le(coap_tick_t a, coap_tick_t b) { return a == b || coap_time_lt(a,b); } diff --git a/include/coap/encode.h b/include/coap/encode.h index 283343d022..fb268b269e 100644 --- a/include/coap/encode.h +++ b/include/coap/encode.h @@ -10,10 +10,10 @@ #ifndef _COAP_ENCODE_H_ #define _COAP_ENCODE_H_ -#if (BSD >= 199103) || defined(WITH_CONTIKI) -# include -#else +#ifdef HAVE_STRINGS_H # include +#else +# include #endif #define Nn 8 /* duplicate definition of N if built on sky motes */ diff --git a/include/coap/libcoap.h b/include/coap/libcoap.h index 214b9e235e..5e0c9c0383 100644 --- a/include/coap/libcoap.h +++ b/include/coap/libcoap.h @@ -10,6 +10,8 @@ #ifndef _LIBCOAP_H_ #define _LIBCOAP_H_ +#include "coap_config.h" + /* The non posix embedded platforms like Contiki, TinyOS, RIOT, ... doesn't have * a POSIX compatible header structure so we have to slightly do some platform * related things. Currently there is only Contiki available so we check for a @@ -18,9 +20,14 @@ * * The CONTIKI variable is within the Contiki build environment! */ -#if !defined (CONTIKI) +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H #include -#endif /* CONTIKI */ +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #endif /* _LIBCOAP_H_ */ diff --git a/include/coap/mem.h b/include/coap/mem.h index fd3c69aafd..f4bfce5d8a 100644 --- a/include/coap/mem.h +++ b/include/coap/mem.h @@ -67,14 +67,14 @@ void coap_free_type(coap_memory_tag_t type, void *p); /** * Wrapper function to coap_malloc_type() for backwards compatibility. */ -static inline void *coap_malloc(size_t size) { +COAP_STATIC_INLINE void *coap_malloc(size_t size) { return coap_malloc_type(COAP_STRING, size); } /** * Wrapper function to coap_free_type() for backwards compatibility. */ -static inline void coap_free(void *object) { +COAP_STATIC_INLINE void coap_free(void *object) { coap_free_type(COAP_STRING, object); } @@ -86,7 +86,7 @@ static inline void coap_free(void *object) { /* no initialization needed with lwip (or, more precisely: lwip must be * completely initialized anyway by the time coap gets active) */ -static inline void coap_memory_init(void) {} +COAP_STATIC_INLINE void coap_memory_init(void) {} /* It would be nice to check that size equals the size given at the memp * declaration, but i currently don't see a standard way to check that without @@ -98,11 +98,11 @@ static inline void coap_memory_init(void) {} /* Those are just here to make uri.c happy where string allocation has not been * made conditional. */ -static inline void *coap_malloc(size_t size) { +COAP_STATIC_INLINE void *coap_malloc(size_t size) { LWIP_ASSERT("coap_malloc must not be used in lwIP", 0); } -static inline void coap_free(void *pointer) { +COAP_STATIC_INLINE void coap_free(void *pointer) { LWIP_ASSERT("coap_free must not be used in lwIP", 0); } diff --git a/include/coap/net.h b/include/coap/net.h index 014b4903ab..ea0a288d20 100644 --- a/include/coap/net.h +++ b/include/coap/net.h @@ -13,7 +13,9 @@ #include #include #include +#ifdef HAVE_SYS_TIME_H #include +#endif #include #ifdef WITH_LWIP @@ -137,7 +139,7 @@ typedef struct coap_context_t { * @param context The context to register the handler for. * @param handler The response handler to register. */ -static inline void +COAP_STATIC_INLINE void coap_register_response_handler(coap_context_t *context, coap_response_handler_t handler) { context->response_handler = handler; @@ -149,7 +151,7 @@ coap_register_response_handler(coap_context_t *context, * @param ctx The context to use. * @param type The option type to register. */ -inline static void +COAP_STATIC_INLINE void coap_register_option(coap_context_t *ctx, unsigned char type) { coap_option_setb(ctx->known_options, type); } @@ -185,7 +187,7 @@ coap_context_t *coap_new_context(const coap_address_t *listen_addr); * * @return Incremented message id in network byte order. */ -static inline unsigned short +COAP_STATIC_INLINE unsigned short coap_new_message_id(coap_context_t *context) { context->message_id++; #ifndef WITH_CONTIKI @@ -342,7 +344,7 @@ coap_tid_t coap_send_ack(coap_context_t *context, * @return The transaction id if RST was sent or @c * COAP_INVALID_TID on error. */ -static inline coap_tid_t +COAP_STATIC_INLINE coap_tid_t coap_send_rst(coap_context_t *context, const coap_endpoint_t *local_interface, const coap_address_t *dst, @@ -420,7 +422,7 @@ int coap_remove_from_queue(coap_queue_t **queue, * * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) { coap_queue_t *node; if (!coap_remove_from_queue(queue, id, &node)) diff --git a/include/coap/option.h b/include/coap/option.h index ace2b81c71..f1da48ae94 100644 --- a/include/coap/option.h +++ b/include/coap/option.h @@ -32,6 +32,17 @@ typedef struct { unsigned char *value; } coap_option_t; +/** Representation of the association between a CoAP option key and its + * data type and valid data length ranges. + */ +typedef struct +{ + unsigned short key; /**< The ID of the option the following values apply to. */ + unsigned char type; /**< The type of the option: u=uint, s=string, o=opaque. */ + unsigned int min; /**< The minimum number of bytes allowed for the option data */ + unsigned int max; /**< The maximum number of bytes allowed for the option data */ +} coap_option_def_t; + /** * Parses the option pointed to by @p opt into @p result. This function returns * the number of bytes that have been parsed, or @c 0 on error. An error is @@ -142,7 +153,7 @@ typedef uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE]; * * @param f The filter to clear. */ -static inline void +COAP_STATIC_INLINE void coap_option_filter_clear(coap_opt_filter_t f) { memset(f, 0, sizeof(coap_opt_filter_t)); } @@ -195,7 +206,7 @@ int coap_option_filter_get(const coap_opt_filter_t filter, unsigned short type); * * @return @c 1 if bit was set, @c -1 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_option_setb(coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_set(filter, type) ? 1 : -1; } @@ -212,7 +223,7 @@ coap_option_setb(coap_opt_filter_t filter, unsigned short type) { * * @return @c 1 if bit was set, @c -1 otherwise. */ -inline static int +COAP_STATIC_INLINE int coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_unset(filter, type) ? 1 : -1; } @@ -229,7 +240,7 @@ coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { * * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. */ -inline static int +COAP_STATIC_INLINE int coap_option_getb(const coap_opt_filter_t filter, unsigned short type) { return coap_option_filter_get(filter, type); } @@ -402,6 +413,16 @@ unsigned short coap_opt_length(const coap_opt_t *opt); */ unsigned char *coap_opt_value(coap_opt_t *opt); +/** + * Returns a pointer to the coap option range definitions. @key + * must be a valid option ID. This function returns @c NULL if + * @p key is not a valid option ID. + * + * @param key The option ID whose definition should be returned. + * @return A pointer to the option definition. + */ +coap_option_def_t* coap_opt_def(unsigned short key); + /** @deprecated { Use coap_opt_value() instead. } */ #define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt) diff --git a/include/coap/pdu.h b/include/coap/pdu.h index e60dadca8b..edad5f625a 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -21,6 +21,11 @@ #include #endif +#ifdef __cplusplus +extern "C" +{ +#endif + #define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ #define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ #ifndef COAP_MAX_PDU_SIZE @@ -53,11 +58,14 @@ #define COAP_REQUEST_DELETE 4 /* CoAP option types (be sure to update check_critical when adding options */ +/* See http://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers */ #define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */ #define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */ #define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */ #define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */ +#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ +#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE #define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */ #define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */ #define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */ @@ -71,15 +79,11 @@ #define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */ #define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */ -/* option types from draft-ietf-coap-observe-09 */ +/* selected option types from draft-core-block-21 */ -#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ -#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE - -/* selected option types from draft-core-block-04 */ - -#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */ -#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */ +#define COAP_OPTION_BLOCK2 23 /* C, uint, 0-3 B, (none) */ +#define COAP_OPTION_BLOCK1 27 /* C, uint, 0-3 B, (none) */ +#define COAP_OPTION_SIZE2 28 /* E, uint, 0-4 B, (none) */ /* selected option types from draft-tcs-coap-no-response-option-11 */ @@ -171,28 +175,92 @@ typedef int coap_tid_t; */ #define COAP_DROPPED_RESPONSE -2 +#define COAP_TCP_HEADER_NO_FIELD 2 +#define COAP_TCP_HEADER_8_BIT 3 +#define COAP_TCP_HEADER_16_BIT 4 +#define COAP_TCP_HEADER_32_BIT 6 + +#define COAP_TCP_LENGTH_FIELD_8_BIT 13 +#define COAP_TCP_LENGTH_FIELD_16_BIT 269 +#define COAP_TCP_LENGTH_FIELD_32_BIT 65805 + +#define COAP_TCP_LENGTH_LIMIT_8_BIT 13 +#define COAP_TCP_LENGTH_LIMIT_16_BIT 256 +#define COAP_TCP_LENGTH_LIMIT_32_BIT 65536 + +#define COAP_TCP_LENGTH_FIELD_NUM_8_BIT 13 +#define COAP_TCP_LENGTH_FIELD_NUM_16_BIT 14 +#define COAP_TCP_LENGTH_FIELD_NUM_32_BIT 15 + +#define COAP_OPTION_FIELD_8_BIT 12 +#define COAP_OPTION_FIELD_16_BIT 256 +#define COAP_OPTION_FIELD_32_BIT 65536 + +typedef enum { + COAP_UDP = 0, +#ifdef WITH_TCP + COAP_TCP, + COAP_TCP_8BIT, + COAP_TCP_16BIT, + COAP_TCP_32BIT +#endif +} coap_transport_t; + #ifdef WORDS_BIGENDIAN typedef struct { - unsigned int version:2; /* protocol version */ - unsigned int type:2; /* type flag */ - unsigned int token_length:4; /* length of Token */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* message id */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; + unsigned short version:2; /* protocol version */ + unsigned short type:2; /* type flag */ + unsigned short token_length:4; /* length of Token */ + unsigned short code:8; /* request method (value 1--10) or response + code (value 40-255) */ + unsigned short id; /* message id */ + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_udp_t; #else typedef struct { - unsigned int token_length:4; /* length of Token */ - unsigned int type:2; /* type flag */ - unsigned int version:2; /* protocol version */ - unsigned int code:8; /* request method (value 1--10) or response - code (value 40-255) */ - unsigned short id; /* transaction id (network byte order!) */ - unsigned char token[]; /* the actual token, if any */ -} coap_hdr_t; + unsigned short token_length:4; /* length of Token */ + unsigned short type:2; /* type flag */ + unsigned short version:2; /* protocol version */ + unsigned short code:8; /* request method (value 1--10) or response + code (value 40-255) */ + unsigned short id; /* transaction id (network byte order!) */ + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_udp_t; #endif +#ifdef WITH_TCP +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_NO_FIELD]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_t; + +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_8_BIT]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_8bit_t; + +typedef struct { + unsigned char header_data[COAP_TCP_HEADER_16_BIT]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_16bit_t; + +typedef struct { + unsigned char header_data[6]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_tcp_32bit_t; + +typedef union { + coap_hdr_udp_t udp; + coap_hdr_tcp_t tcp; + coap_hdr_tcp_8bit_t tcp_8bit; + coap_hdr_tcp_16bit_t tcp_16bit; + coap_hdr_tcp_32bit_t tcp_32bit; +} coap_hdr_transport_t; +#endif /* WITH_TCP */ + +// Typedef for backwards compatibility. +typedef coap_hdr_udp_t coap_hdr_t; + #define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0) #define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \ && ((MSG)->code < 32)) @@ -226,10 +294,18 @@ typedef struct { typedef struct { size_t max_size; /**< allocated storage for options and data */ - coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. - * This may or may not equal (coap_hdr_t*)(pdu+1) - * depending on the memory management - * implementation. */ + union { + coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. + * This may or may not equal (coap_hdr_t*)(pdu+1) + * depending on the memory management + * implementation. */ +#ifdef WITH_TCP + coap_hdr_transport_t *transport_hdr; /**< Address of the first byte of the CoAP message. + * This may or may not equal (coap_hdr_t*)(pdu+1) + * depending on the memory management + * implementation. */ +#endif + }; unsigned short max_delta; /**< highest option number */ unsigned short length; /**< PDU length (including header, options, data) */ unsigned char *data; /**< payload */ @@ -308,6 +384,15 @@ void coap_pdu_clear(coap_pdu_t *pdu, size_t size); */ coap_pdu_t *coap_new_pdu(void); +/** + * Creates a new CoAP PDU. The object is created on the heap and must be released + * using coap_delete_pdu(); + * + * @deprecated This function allocates the maximum storage for each + * PDU. Use coap_pdu_init2() instead. + */ +coap_pdu_t *coap_new_pdu2(coap_transport_t transport, unsigned int size); + void coap_delete_pdu(coap_pdu_t *); /** @@ -326,6 +411,106 @@ int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result); +/** + * Parses @p data into the CoAP PDU structure given in @p result. This + * function returns @c 0 on error or a number greater than zero on + * success. + * + * @param data The raw data to parse as CoAP PDU + * @param length The actual size of @p data + * @param result The PDU structure to fill. Note that the structure must + * provide space for at least @p length bytes to hold the + * entire CoAP PDU. + * @param transport The transport type. + * @return A value greater than zero on success or @c 0 on error. + */ +int coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, + coap_transport_t transport); + +#ifdef WITH_TCP +/** + * Get total pdu size including header + option + payload (with marker) from pdu data. + * + * @param data The raw data to parse as CoAP PDU. + * @param size payload size of pdu. + * @return Total message length. + */ +size_t coap_get_total_message_length(const unsigned char *data, size_t size); + +/** + * Get transport type of coap header for coap over tcp + * through payload size(including payload marker) + option size. + * + * @param size payload size of pdu. + * @return The transport type. + */ +coap_transport_t coap_get_tcp_header_type_from_size(unsigned int size); + +/** + * Get transport type of coap header for coap over tcp + * through first nibble(0~E) of init-byte . + * + * @param legnth length value of init byte. +* @return The transport type. + */ +coap_transport_t coap_get_tcp_header_type_from_initbyte(unsigned int length); + +/** + * Add length of option/payload into 'Len+ byte...' field of coap header + * for coap over tcp. + * + * @param pdu The pdu pointer. + * @param transport The transport type. + * @param length length value of init byte. + */ +void coap_add_length(const coap_pdu_t *pdu, coap_transport_t transport, + unsigned int length); + +/** + * Get the length of option/payload field of coap header for coap over tcp. + * + * @param pdu The pdu pointer. + * @param transport The transport type. + * @return length value of init byte. + */ +unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_t transport); + +/** + * Get the length of option/payload field of coap header for coap over tcp. + * + * @param header The header to parse. + * @return transport The transport type. + */ +unsigned int coap_get_length_from_header(const unsigned char *header, + coap_transport_t transport); + +/** + * Get length of header including len, TKL, Len+bytes, Code, token bytes for coap over tcp. + * + * @param data The raw data to parse as CoAP PDU + * @return header length + token length + */ +unsigned int coap_get_tcp_header_length(unsigned char *data); + +/** + * Get length of header including len, TKL, Len+bytes, Code + * without token bytes for coap over tcp. + * + * @param transport The transport type. + * @return header length. + */ +unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport); + +/** + * Get option length. + * + * @param key delta of option + * @param length length of option + * @return total option length + */ +size_t coap_get_opt_header_length(unsigned short key, size_t length); +#endif /* WITH_TCP */ + /** * Adds token of length @p len to @p pdu. * Adding the token destroys any following contents of the pdu. Hence options @@ -344,8 +529,23 @@ int coap_add_token(coap_pdu_t *pdu, const unsigned char *data); /** - * Adds option of given type to pdu that is passed as first - * parameter. + * Adds token of length @p len to @p pdu. Adding the token destroys + * any following contents of the pdu. Hence options and data must be + * added after coap_add_token2() has been called. In @p pdu, length is + * set to @p len + @c 4, and max_delta is set to @c 0. This funtion + * returns @c 0 on error or a value greater than zero on success. + * + * @param pdu The pdu pointer. + * @param len The length of the new token. + * @param data The token to add. + * @param transport The transport type. + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, + coap_transport_t transport); + +/** + * Adds option of given type to pdu that is passed as first parameter. * coap_add_option() destroys the PDU's data, so coap_add_data() must be called * after all options have been added. As coap_add_token() destroys the options * following the token, the token must be added before coap_add_option() is @@ -356,6 +556,17 @@ size_t coap_add_option(coap_pdu_t *pdu, unsigned int len, const unsigned char *data); +/** + * Adds option of given type to pdu that is passed as first + * parameter. coap_add_option2() destroys the PDU's data, so + * coap_add_data() must be called after all options have been added. + * As coap_add_token2() destroys the options following the token, + * the token must be added before coap_add_option2() is called. + * This function returns the number of bytes written or @c 0 on error. + */ +size_t coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, + const unsigned char *data, coap_transport_t transport); + /** * Adds option of given type to pdu that is passed as first parameter, but does * not write a value. It works like coap_add_option with respect to calling @@ -385,4 +596,7 @@ int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data); +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* _COAP_PDU_H_ */ diff --git a/include/coap/prng.h b/include/coap/prng.h index da6d953440..881d62b4be 100644 --- a/include/coap/prng.h +++ b/include/coap/prng.h @@ -28,7 +28,7 @@ * prng(). You might want to change prng() to use a better PRNG on your specific * platform. */ -static inline int +COAP_STATIC_INLINE int coap_prng_impl(unsigned char *buf, size_t len) { while (len--) *buf++ = rand() & 0xFF; @@ -44,7 +44,7 @@ coap_prng_impl(unsigned char *buf, size_t len) { * prng(). You might want to change prng() to use a better PRNG on your specific * platform. */ -static inline int +COAP_STATIC_INLINE int contiki_prng_impl(unsigned char *buf, size_t len) { unsigned short v = random_rand(); while (len > sizeof(v)) { @@ -63,7 +63,7 @@ contiki_prng_impl(unsigned char *buf, size_t len) { #endif /* WITH_CONTIKI */ #if defined(WITH_LWIP) && defined(LWIP_RAND) -static inline int +COAP_STATIC_INLINE int lwip_prng_impl(unsigned char *buf, size_t len) { u32_t v = LWIP_RAND(); while (len > sizeof(v)) { diff --git a/include/coap/resource.h b/include/coap/resource.h index 9c7b45ced6..a2ac0156eb 100644 --- a/include/coap/resource.h +++ b/include/coap/resource.h @@ -115,7 +115,7 @@ coap_resource_t *coap_resource_init(const unsigned char *uri, * @p mode which must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON * or @c COAP_RESOURCE_FLAGS_NOTIFY_CON. */ -static inline void +COAP_STATIC_INLINE void coap_resource_set_mode(coap_resource_t *r, int mode) { r->flags = (r->flags & !COAP_RESOURCE_FLAGS_NOTIFY_CON) | mode; } @@ -244,7 +244,7 @@ coap_print_status_t coap_print_link(const coap_resource_t *resource, * @param method The CoAP request method to handle. * @param handler The handler to register with @p resource. */ -static inline void +COAP_STATIC_INLINE void coap_register_handler(coap_resource_t *resource, unsigned char method, coap_method_handler_t handler) { diff --git a/src/address.c b/src/address.c index e237881a7a..3cb8c5bed4 100644 --- a/src/address.c +++ b/src/address.c @@ -6,10 +6,19 @@ * README for terms of use. */ -#ifdef WITH_POSIX +#include "coap_config.h" + +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) #include +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #include "address.h" @@ -37,12 +46,11 @@ coap_address_equals(const coap_address_t *a, const coap_address_t *b) { return 0; } -#else /* WITH_POSIX */ +#else /* WITH_LWIP || WITH_CONTIKI */ /* make compilers happy that do not like empty modules */ -static inline void dummy() +COAP_STATIC_INLINE void dummy() { } -#endif /* not WITH_POSIX */ - +#endif diff --git a/src/block.c b/src/block.c index a82037a97d..e0020bcab4 100644 --- a/src/block.c +++ b/src/block.c @@ -19,7 +19,9 @@ #error "COAP_MAX_BLOCK_SZX too large" #endif +#ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) +#endif #ifndef WITHOUT_BLOCK unsigned int @@ -49,7 +51,7 @@ coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { assert(block); memset(block, 0, sizeof(coap_block_t)); - if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) { + if (pdu && (option = coap_check_option(pdu, type, &opt_iter)) != NULL) { block->szx = COAP_OPT_BLOCK_SZX(option); if (COAP_OPT_BLOCK_MORE(option)) block->m = 1; @@ -68,6 +70,12 @@ coap_write_block_opt(coap_block_t *block, unsigned short type, assert(pdu); + /* Block2 */ + if (type != COAP_OPTION_BLOCK2) { + warn("coap_write_block_opt: skipped unknown option\n"); + return -1; + } + start = block->num << (block->szx + 4); if (data_length <= start) { debug("illegal block requested\n"); diff --git a/src/coap_io.c b/src/coap_io.c index cbf2263d79..0fe0cb20cc 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -17,10 +17,28 @@ #endif #ifdef HAVE_SYS_SOCKET_H # include +# define OPTVAL_T(t) (t) +# define CLOSE_SOCKET(fd) close(fd) +# define COAP_SOCKET_ERROR (-1) +# define COAP_INVALID_SOCKET (-1) +typedef int coap_socket_t; #endif #ifdef HAVE_NETINET_IN_H # include #endif +#ifdef HAVE_WS2TCPIP_H +# include +# define OPTVAL_T(t) (const char*)(t) +# define CLOSE_SOCKET(fd) { closesocket(fd); WSACleanup(); } +# define COAP_SOCKET_ERROR SOCKET_ERROR +# define COAP_INVALID_SOCKET INVALID_SOCKET +# undef CMSG_DATA +# define CMSG_DATA WSA_CMSG_DATA +# define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR +# define CMSG_LEN WSA_CMSG_LEN +# define CMSG_SPACE WSA_CMSG_SPACE +typedef SOCKET coap_socket_t; +#endif #ifdef HAVE_SYS_UIO_H # include #endif @@ -37,12 +55,12 @@ #include "mem.h" #include "coap_io.h" -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) struct coap_packet_t { coap_if_handle_t hnd; /**< the interface handle */ coap_address_t src; /**< the packet's source address */ coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; + const coap_endpoint_t *endpoint; int ifindex; void *session; /**< opaque session data */ @@ -57,7 +75,7 @@ struct coap_packet_t { #ifdef WITH_CONTIKI static int ep_initialized = 0; -static inline struct coap_endpoint_t * +COAP_STATIC_INLINE struct coap_endpoint_t * coap_malloc_contiki_endpoint() { static struct coap_endpoint_t ep; @@ -69,7 +87,7 @@ coap_malloc_contiki_endpoint() { } } -static inline void +COAP_STATIC_INLINE void coap_free_contiki_endpoint(struct coap_endpoint_t *ep) { ep_initialized = 0; } @@ -106,42 +124,52 @@ coap_free_endpoint(coap_endpoint_t *ep) { } #else /* WITH_CONTIKI */ -static inline struct coap_endpoint_t * +COAP_STATIC_INLINE struct coap_endpoint_t * coap_malloc_posix_endpoint(void) { return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t)); } -static inline void +COAP_STATIC_INLINE void coap_free_posix_endpoint(struct coap_endpoint_t *ep) { coap_free(ep); } coap_endpoint_t * coap_new_endpoint(const coap_address_t *addr, int flags) { - int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); +#ifdef HAVE_WS2TCPIP_H + WSADATA Data; + if (WSAStartup(MAKEWORD(2, 2), &Data) != NO_ERROR) { + coap_log(LOG_WARNING, "coap_new_endpoint: WSAStartup failed"); + return NULL; + } +#endif + coap_socket_t sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0); int on = 1; struct coap_endpoint_t *ep; - if (sockfd < 0) { + if (sockfd == COAP_INVALID_SOCKET) { +#ifdef HAVE_WS2TCPIP_H + WSACleanup(); +#endif coap_log(LOG_WARNING, "coap_new_endpoint: socket"); return NULL; } - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR"); on = 1; switch(addr->addr.sa.sa_family) { case AF_INET: - if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IP_PKTINFO\n"); break; case AF_INET6: #ifdef IPV6_RECVPKTINFO - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_RECVPKTINFO\n"); #else /* IPV6_RECVPKTINFO */ - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_PKTINFO\n"); #endif /* IPV6_RECVPKTINFO */ break; @@ -149,16 +177,16 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { coap_log(LOG_ALERT, "coap_new_endpoint: unsupported sa_family\n"); } - if (bind(sockfd, &addr->addr.sa, addr->size) < 0) { + if (bind(sockfd, &addr->addr.sa, addr->size) == COAP_SOCKET_ERROR) { coap_log(LOG_WARNING, "coap_new_endpoint: bind"); - close (sockfd); + CLOSE_SOCKET(sockfd); return NULL; } ep = coap_malloc_posix_endpoint(); if (!ep) { coap_log(LOG_WARNING, "coap_new_endpoint: malloc"); - close(sockfd); + CLOSE_SOCKET(sockfd); return NULL; } @@ -167,9 +195,9 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { ep->flags = flags; ep->addr.size = addr->size; - if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) { + if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) == COAP_SOCKET_ERROR) { coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address"); - close (sockfd); + CLOSE_SOCKET(sockfd); return NULL; } @@ -193,9 +221,9 @@ coap_new_endpoint(const coap_address_t *addr, int flags) { void coap_free_endpoint(coap_endpoint_t *ep) { - if(ep) { - if (ep->handle.fd >= 0) - close(ep->handle.fd); + if (ep) { + if (ep->handle.fd != COAP_INVALID_SOCKET) + CLOSE_SOCKET(ep->handle.fd); coap_free_posix_endpoint((struct coap_endpoint_t *)ep); } } @@ -221,8 +249,8 @@ struct in_pktinfo { }; #endif -#if defined(WITH_POSIX) && !defined(SOL_IP) -/* Solaris expects level IPPROTO_IP for ancillary data. */ +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(SOL_IP) +/* Solaris and Windows expect level IPPROTO_IP for ancillary data. */ #define SOL_IP IPPROTO_IP #endif @@ -245,28 +273,43 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef WITH_CONTIKI /* a buffer large enough to hold all protocol address types */ char buf[CMSG_LEN(sizeof(struct sockaddr_storage))]; + assert(local_interface); + +#ifdef WSA_CMSG_SPACE + WSAMSG mhdr; + WSABUF dataBuf; + + memset(&mhdr, 0, sizeof(mhdr)); + + mhdr.name = (PSOCKADDR)&dst->addr.sa; + mhdr.lpBuffers = &dataBuf; + mhdr.dwBufferCount = 1; +#else struct msghdr mhdr; struct iovec iov[1]; - assert(local_interface); - iov[0].iov_base = data; iov[0].iov_len = datalen; - memset(&mhdr, 0, sizeof(struct msghdr)); + memset(&mhdr, 0, sizeof(mhdr)); mhdr.msg_name = (void *)&dst->addr; mhdr.msg_namelen = dst->size; mhdr.msg_iov = iov; mhdr.msg_iovlen = 1; + mhdr.msg_control = buf; +#endif switch (dst->addr.sa.sa_family) { case AF_INET6: { struct cmsghdr *cmsg; struct in6_pktinfo *pktinfo; - mhdr.msg_control = buf; +#ifdef WSA_CMSG_SPACE + mhdr.Control.len = CMSG_SPACE(sizeof(struct in6_pktinfo)); +#else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); +#endif cmsg = CMSG_FIRSTHDR(&mhdr); cmsg->cmsg_level = IPPROTO_IPV6; @@ -294,8 +337,11 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct cmsghdr *cmsg; struct in_pktinfo *pktinfo; - mhdr.msg_control = buf; +#ifdef WSA_CMSG_SPACE + mhdr.Control.len = CMSG_SPACE(sizeof(struct in_pktinfo)); +#else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); +#endif cmsg = CMSG_FIRSTHDR(&mhdr); cmsg->cmsg_level = SOL_IP; @@ -309,12 +355,30 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, /* We cannot send with multicast address as source address * and hence let the kernel pick the outgoing interface. */ pktinfo->ipi_ifindex = 0; + +#ifdef WSA_CMSG_SPACE + /* OS's without ipi_spec_dst put the source address in ipi_addr. */ + memset(&pktinfo->ipi_addr, 0, sizeof(pktinfo->ipi_addr)); +#else + /* OS's with ipi_spec_dst seem to put the source address in ipi_spec_dst + * which is apparently a misnomer. */ memset(&pktinfo->ipi_spec_dst, 0, sizeof(pktinfo->ipi_spec_dst)); +#endif } else { pktinfo->ipi_ifindex = ep->ifindex; + +#ifdef WSA_CMSG_SPACE + /* OS's without ipi_spec_dst put the source address in ipi_addr. */ + memcpy(&pktinfo->ipi_addr, + &local_interface->addr.addr.sin.sin_addr, + local_interface->addr.size); +#else + /* OS's with ipi_spec_dst seem to put the source address in ipi_spec_dst + * which is apparently a misnomer. */ memcpy(&pktinfo->ipi_spec_dst, &local_interface->addr.addr.sin.sin_addr, local_interface->addr.size); +#endif } break; } @@ -339,8 +403,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef CUSTOM_COAP_NETWORK_READ #define SIN6(A) ((struct sockaddr_in6 *)(A)) - -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) static coap_packet_t * coap_malloc_packet(void) { coap_packet_t *packet; @@ -359,7 +422,7 @@ coap_free_packet(coap_packet_t *packet) { } #endif /* WITH_POSIX */ #ifdef WITH_CONTIKI -static inline coap_packet_t * +COAP_STATIC_INLINE coap_packet_t * coap_malloc_packet(void) { return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0); } @@ -370,7 +433,7 @@ coap_free_packet(coap_packet_t *packet) { } #endif /* WITH_CONTIKI */ -static inline size_t +COAP_STATIC_INLINE size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { return COAP_MAX_PDU_SIZE; } @@ -378,7 +441,7 @@ coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) { void coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target) { - target->handle = packet->interface->handle; + target->handle = packet->endpoint->handle; memcpy(&target->addr, &packet->dst, sizeof(target->addr)); target->ifindex = packet->ifindex; target->flags = 0; /* FIXME */ @@ -400,7 +463,7 @@ coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t * local interface with address @p local. This function returns @c 1 * if @p dst is a valid match, and @c 0 otherwise. */ -static inline int +COAP_STATIC_INLINE int is_local_if(const coap_address_t *local, const coap_address_t *dst) { return coap_address_isany(local) || coap_address_equals(dst, local) || coap_is_mcast(dst); @@ -457,7 +520,7 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { /* use getsockname() to get the local port */ (*packet)->dst.size = sizeof((*packet)->dst.addr); - if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) { + if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) == COAP_SOCKET_ERROR) { coap_log(LOG_DEBUG, "cannot determine local port\n"); goto error; } @@ -565,7 +628,7 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { #error "coap_network_read() not implemented on this platform" #endif - (*packet)->interface = ep; + (*packet)->endpoint = ep; return len; error: diff --git a/src/coap_list.c b/src/coap_list.c new file mode 100644 index 0000000000..1932d4e6c9 --- /dev/null +++ b/src/coap_list.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.c -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +#include "coap_config.h" + +#include +#include + +#include "debug.h" +#include "mem.h" +#include "coap_list.h" + +int +coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *node)) { + coap_list_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) { + *queue = node; + return 1; + } + + /* replace queue head if new node has to be added before the existing queue head */ + q = *queue; + if (order(node->data, q->data) < 0) { + node->next = q; + *queue = node; + return 1; + } + + /* search for right place to insert */ + do { + p = q; + q = q->next; + } while (q && order(node->data, q->data) >= 0); + + /* insert new item */ + node->next = q; + p->next = node; + return 1; +} + +int +coap_delete(coap_list_t *node) { + if (!node) + return 0; + + if (node->delete_func) + node->delete_func(node->data); + coap_free( node->data); + coap_free( node); + + return 1; +} + +void +coap_delete_list(coap_list_t *queue) { + coap_list_t *elt, *tmp; + + if (!queue) + return; + + LL_FOREACH_SAFE(queue, elt, tmp) { + coap_delete(elt); + } +} + +coap_list_t * +coap_new_listnode(void *data, void (*delete_func)(void *)) { + coap_list_t *node = (coap_list_t *)coap_malloc(sizeof(coap_list_t)); + if (!node) { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_listnode: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof(coap_list_t)); + node->data = data; + node->delete_func = delete_func; + return node; +} diff --git a/src/coap_time.c b/src/coap_time.c index 1f991755ea..356f5ea4f9 100644 --- a/src/coap_time.c +++ b/src/coap_time.c @@ -6,12 +6,13 @@ * README for terms of use. */ +#include "coap_config.h" + #ifdef WITH_POSIX #include #include #include /* _POSIX_TIMERS */ -#include "coap_config.h" #include "coap_time.h" static coap_time_t coap_clock_offset = 0; @@ -90,7 +91,7 @@ coap_ticks_to_rt(coap_tick_t t) { #else /* WITH_POSIX */ /* make compilers happy that do not like empty modules */ -static inline void dummy() +COAP_STATIC_INLINE void dummy() { } diff --git a/src/debug.c b/src/debug.c index e62a4edf30..d36e1e70bc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -7,6 +7,7 @@ */ #include "coap_config.h" +#include "coap.h" #if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 @@ -23,6 +24,12 @@ #ifdef HAVE_ARPA_INET_H #include +#if defined(__ANDROID__) +typedef __uint16_t in_port_t; +#endif +#endif +#ifdef HAVE_WS2TCPIP_H +#include #endif #ifdef HAVE_TIME_H @@ -73,7 +80,7 @@ static char *loglevels[] = { #ifdef HAVE_TIME_H -static inline size_t +COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t) { struct tm *tmp; time_t now = coap_ticks_to_rt(t); @@ -83,7 +90,7 @@ print_timestamp(char *s, size_t len, coap_tick_t t) { #else /* alternative implementation: just print the timestamp */ -static inline size_t +COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t) { #ifdef HAVE_SNPRINTF return snprintf(s, len, "%u.%03u", @@ -108,7 +115,7 @@ print_timestamp(char *s, size_t len, coap_tick_t t) { * * @return The length of @p s. */ -static inline size_t +COAP_STATIC_INLINE size_t strnlen(const char *s, size_t maxlen) { size_t n = 0; while(*s++ && n < maxlen) @@ -160,7 +167,7 @@ print_readable( const unsigned char *data, unsigned int len, size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#ifdef HAVE_ARPA_INET_H +#if defined(HAVE_ARPA_INET_H) || defined(_WIN32) const void *addrptr = NULL; in_port_t port; unsigned char *p = buf; @@ -362,7 +369,7 @@ print_content_format(unsigned int format_type, * to carry binary data. The return value @c 0 hence indicates * printable data which is also assumed if @p content_format is @c 01. */ -static inline int +COAP_STATIC_INLINE int is_binary(int content_format) { return !(content_format == -1 || content_format == COAP_MEDIATYPE_TEXT_PLAIN || diff --git a/src/encode.c b/src/encode.c index 10c0c6c939..8c1ef5c9ae 100644 --- a/src/encode.c +++ b/src/encode.c @@ -14,7 +14,8 @@ #include "encode.h" /* Carsten suggested this when fls() is not available: */ -int coap_fls(unsigned int i) { +int +coap_fls(unsigned int i) { int n; for (n = 0; i; n++) i >>= 1; diff --git a/src/net.c b/src/net.c index bbdbd720ee..300bd2a7e3 100644 --- a/src/net.c +++ b/src/net.c @@ -19,7 +19,9 @@ #elif HAVE_SYS_UNISTD_H #include #endif -#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -29,6 +31,9 @@ #ifdef HAVE_ARPA_INET_H #include #endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif #ifdef WITH_LWIP #include @@ -113,16 +118,16 @@ /** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_TIMEOUT */ #define ACK_TIMEOUT Q(FRAC_BITS, COAP_DEFAULT_ACK_TIMEOUT) -#if defined(WITH_POSIX) +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) time_t clock_offset; -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node(void) { return (coap_queue_t *)coap_malloc_type(COAP_NODE, sizeof(coap_queue_t)); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { coap_free_type(COAP_NODE, node); } @@ -134,12 +139,12 @@ coap_free_node(coap_queue_t *node) { static void coap_retransmittimer_execute(void *arg); static void coap_retransmittimer_restart(coap_context_t *ctx); -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node() { return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { memp_free(MEMP_COAP_NODE, node); } @@ -165,12 +170,12 @@ coap_context_t the_coap_context; PROCESS(coap_retransmit_process, "message retransmit process"); -static inline coap_queue_t * +COAP_STATIC_INLINE coap_queue_t * coap_malloc_node() { return (coap_queue_t *)coap_malloc_type(COAP_NODE, 0); } -static inline void +COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node) { coap_free_type(COAP_NODE, node); } @@ -668,7 +673,7 @@ coap_send_message_type(coap_context_t *context, * value * @return COAP_TICKS_PER_SECOND * ACK_TIMEOUT * (1 + (ACK_RANDOM_FACTOR - 1) * r) */ -static inline unsigned int +COAP_STATIC_INLINE unsigned int calc_timeout(unsigned char r) { unsigned int result; @@ -969,7 +974,7 @@ coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node) } -static inline int +COAP_STATIC_INLINE int token_match(const unsigned char *a, size_t alen, const unsigned char *b, size_t blen) { return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); @@ -1120,7 +1125,7 @@ coap_new_error_response(coap_pdu_t *request, unsigned char code, * Quick hack to determine the size of the resource description for * .well-known/core. */ -static inline size_t +COAP_STATIC_INLINE size_t get_wkc_len(coap_context_t *context, coap_opt_t *query_filter) { unsigned char buf[1]; size_t len = 0; @@ -1324,7 +1329,7 @@ coap_cancel(coap_context_t *context, const coap_queue_t *sent) { * @return @c 1 if the response code matches the No-Response option, * or @c 0, otherwise. */ -static inline int +COAP_STATIC_INLINE int no_response(coap_pdu_t *request, coap_pdu_t *response) { coap_opt_t *nores; coap_opt_iterator_t opt_iter; @@ -1497,7 +1502,7 @@ handle_request(coap_context_t *context, coap_queue_t *node) { } } -static inline void +COAP_STATIC_INLINE void handle_response(coap_context_t *context, coap_queue_t *sent, coap_queue_t *rcvd) { @@ -1519,7 +1524,7 @@ handle_response(coap_context_t *context, } } -static inline int +COAP_STATIC_INLINE int #ifdef __GNUC__ handle_locally(coap_context_t *context __attribute__ ((unused)), coap_queue_t *node __attribute__ ((unused))) { diff --git a/src/option.c b/src/option.c index 60c0788d76..251c852ef1 100644 --- a/src/option.c +++ b/src/option.c @@ -143,7 +143,7 @@ coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, return oi; } -static inline int +COAP_STATIC_INLINE int opt_finished(coap_opt_iterator_t *oi) { assert(oi); @@ -420,7 +420,7 @@ typedef struct { } opt_filter; /** Returns true iff @p type denotes an option type larger than 255. */ -static inline int +COAP_STATIC_INLINE int is_long_option(unsigned short type) { return type > 255; } /** Operation specifiers for coap_filter_op(). */ diff --git a/src/pdu.c b/src/pdu.c index cf84af7cb2..64701d54b6 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -85,7 +85,7 @@ coap_pdu_init(unsigned char type, unsigned char code, return NULL; /* size must be large enough for hdr */ -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) +#if !defined(WITH_LWIP) pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); if (!pdu) return NULL; pdu->hdr = coap_malloc_type(COAP_PDU_BUF, size); diff --git a/src/resource.c b/src/resource.c index 61ab87ca89..aa4f383285 100644 --- a/src/resource.c +++ b/src/resource.c @@ -29,7 +29,7 @@ #endif -#ifdef WITH_POSIX +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) #define COAP_MALLOC_TYPE(Type) \ ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) @@ -50,19 +50,21 @@ coap_resources_init() { memb_init(&subscription_storage); } -static inline coap_subscription_t * +COAP_STATIC_INLINE coap_subscription_t * coap_malloc_subscription() { return memb_alloc(&subscription_storage); } -static inline void +COAP_STATIC_INLINE void coap_free_subscription(coap_subscription_t *subscription) { memb_free(&subscription_storage, subscription); } #endif /* WITH_CONTIKI */ +#ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) +#endif /* Helper functions for conditional output of character sequences into * a given buffer. The first Offset characters are skipped. diff --git a/src/uri.c b/src/uri.c index 73732b8b41..3d5af8da28 100644 --- a/src/uri.c +++ b/src/uri.c @@ -33,7 +33,7 @@ * @return A pointer to the first occurence of @p c, or @c NULL * if not found. */ -static inline unsigned char * +COAP_STATIC_INLINE unsigned char * strnchr(unsigned char *s, size_t len, unsigned char c) { while (len && *s++ != c) --len; @@ -308,7 +308,7 @@ typedef void (*segment_handler_t)(unsigned char *, size_t, void *); /** * Checks if path segment @p s consists of one or two dots. */ -static inline int +COAP_STATIC_INLINE int dots(unsigned char *s, size_t len) { return *s == '.' && (len == 1 || (*(s+1) == '.' && len == 2)); } @@ -474,7 +474,7 @@ coap_clone_uri(const coap_uri_t *uri) { /* The function signature of coap_hash() is different from * segment_handler_t hence we use this wrapper as safe typecast. */ -static inline void +COAP_STATIC_INLINE void hash_segment(unsigned char *s, size_t len, void *data) { coap_hash(s, len, data); } From 62c0186b91bd778d812ca063fda00b931af86edd Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 28 Jul 2016 13:34:05 -0700 Subject: [PATCH 03/27] More work on merging IoTivity patches Change-Id: I41875348e9667a999bbb223bca3d99d4201fc8fb Signed-off-by: Dave Thaler --- src/pdu.c | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/pdu.c b/src/pdu.c index 83634fa441..14b05b0d5f 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -99,7 +99,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, #endif unsigned int length = 0; - switch(transport) { + switch (transport) { case COAP_UDP: length = sizeof(coap_hdr_t); break; @@ -129,21 +129,21 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, #endif /* size must be large enough for hdr */ -#if defined(WITH_POSIX) || defined(WITH_ARDUINO) || defined(_WIN32) - pdu = (coap_pdu_t *)coap_malloc(sizeof(coap_pdu_t) + size); -#endif -#ifdef WITH_CONTIKI - pdu = (coap_pdu_t *)memb_alloc(&pdu_storage); +#if defined(WITH_POSIX) || defined(WITH_CONTIKI) || defined(WITH_ARDUINO) || defined(_WIN32) + pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); + if (!pdu) return NULL; + pdu->hdr = coap_malloc_type(COAP_PDU_BUF, size); + if (pdu->hdr == NULL) { + coap_free_type(COAP_PDU, pdu); + pdu = NULL; + } #endif #ifdef WITH_LWIP + pdu = (coap_pdu_t*)coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); + if (!pdu) return NULL; p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (p != NULL) { - u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t)); - /* we could catch that case and allocate larger memory in advance, but then - * again, we'd run into greater trouble with incoming packages anyway */ - LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0); - pdu = p->payload; - } else { + if (p == NULL) { + coap_free_type(COAP_PDU, pdu); pdu = NULL; } #endif @@ -185,7 +185,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, coap_pdu_t * coap_new_pdu(void) { - return coap_new_pdu2(COAP_UDP, 0); + return coap_new_pdu2(COAP_UDP, COAP_MAX_PDU_SIZE); } coap_pdu_t * @@ -198,11 +198,7 @@ coap_new_pdu2(coap_transport_t transport, unsigned int size) { #else /* WITH_CONTIKI */ uip_ntohs(COAP_INVALID_TID), #endif /* WITH_CONTIKI */ -#ifndef WITH_TCP - COAP_MAX_PDU_SIZE, -#else size, -#endif transport); #ifndef NDEBUG @@ -259,7 +255,7 @@ coap_get_tcp_header_type_from_size(unsigned int size) { coap_transport_t coap_get_tcp_header_type_from_initbyte(unsigned int length) { coap_transport_t type; - switch(length) { + switch (length) { case COAP_TCP_LENGTH_FIELD_NUM_8_BIT: type = COAP_TCP_8BIT; break; @@ -279,7 +275,7 @@ void coap_add_length(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int length) { assert(pdu); - switch(transport) { + switch (transport) { case COAP_TCP: pdu->transport_hdr->tcp.header_data[0] = length << 4; break; @@ -316,7 +312,7 @@ coap_get_length_from_header(const unsigned char *header, coap_transport_t transp unsigned int length = 0; unsigned int length_field_data = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = header[0] >> 4; break; @@ -344,7 +340,7 @@ coap_get_length(const coap_pdu_t *pdu, coap_transport_t transport) { unsigned int length = 0; unsigned int length_field_data = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = pdu->transport_hdr->tcp.header_data[0] >> 4; break; @@ -388,7 +384,7 @@ coap_get_tcp_header_length(unsigned char *data) { unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport) { unsigned int length = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = COAP_TCP_HEADER_NO_FIELD; break; @@ -443,7 +439,7 @@ void coap_add_code(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int code) { assert(pdu); - switch(transport) { + switch (transport) { case COAP_UDP: pdu->transport_hdr->udp.code = COAP_RESPONSE_CODE(code); break; @@ -471,7 +467,7 @@ coap_get_code(const coap_pdu_t *pdu, coap_transport_t transport) { assert(pdu); unsigned int code = 0; - switch(transport) { + switch (transport) { case COAP_UDP: code = pdu->transport_hdr->udp.code; break; @@ -509,7 +505,7 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, return 0; unsigned char* token = NULL; - switch(transport) { + switch (transport) { case COAP_UDP: pdu->transport_hdr->udp.token_length = len; token = pdu->transport_hdr->udp.token; @@ -568,7 +564,7 @@ coap_get_token2(const coap_hdr_transport_t *pdu_hdr, coap_transport_t transport, assert(token); assert(token_length); - switch(transport) { + switch (transport) { case COAP_UDP: *token_length = pdu_hdr->udp.token_length; *token = (unsigned char *)pdu_hdr->udp.token; @@ -616,7 +612,7 @@ coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, return 0; } - switch(transport) { + switch (transport) { #ifdef WITH_TCP case COAP_TCP: opt = (unsigned char *) &(pdu->transport_hdr->tcp) + pdu->length; @@ -825,7 +821,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, coap_opt_t *opt = NULL; unsigned int tokenLength = 0; #ifdef WITH_TCP - switch(transport) { + switch (transport) { case COAP_UDP: break; case COAP_TCP: From fd5c9ec1f584c06fc1608df61e32fe4694c1b0df Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 28 Jul 2016 13:34:05 -0700 Subject: [PATCH 04/27] More work on merging IoTivity patches Change-Id: I41875348e9667a999bbb223bca3d99d4201fc8fb Signed-off-by: Dave Thaler --- src/net.c | 14 ++++++------- src/pdu.c | 54 +++++++++++++++++++++++--------------------------- src/resource.c | 2 +- src/str.c | 4 ++-- src/uri.c | 8 ++++---- 5 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/net.c b/src/net.c index 300bd2a7e3..ef7ea6bc40 100644 --- a/src/net.c +++ b/src/net.c @@ -120,7 +120,7 @@ #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) -time_t clock_offset; +time_t clock_offset = 0; COAP_STATIC_INLINE coap_queue_t * coap_malloc_node(void) { @@ -158,7 +158,7 @@ coap_free_node(coap_queue_t *node) { #include "mem.h" #include "net/ip/uip-debug.h" -clock_time_t clock_offset; +clock_time_t clock_offset = 0; #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]) @@ -337,6 +337,11 @@ is_wkc(coap_key_t k) { coap_context_t * coap_new_context( const coap_address_t *listen_addr) { + if (!listen_addr) { + coap_log(LOG_EMERG, "no listen address specified\n"); + return NULL; + } + #ifndef WITH_CONTIKI coap_context_t *c = coap_malloc_type(COAP_CONTEXT, sizeof( coap_context_t ) ); #endif /* not WITH_CONTIKI */ @@ -347,11 +352,6 @@ coap_new_context( return NULL; #endif /* WITH_CONTIKI */ - if (!listen_addr) { - coap_log(LOG_EMERG, "no listen address specified\n"); - return NULL; - } - coap_clock_init(); #ifdef WITH_LWIP prng_init(LWIP_RAND()); diff --git a/src/pdu.c b/src/pdu.c index 83634fa441..92f2b398fe 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -99,7 +99,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, #endif unsigned int length = 0; - switch(transport) { + switch (transport) { case COAP_UDP: length = sizeof(coap_hdr_t); break; @@ -129,21 +129,21 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, #endif /* size must be large enough for hdr */ -#if defined(WITH_POSIX) || defined(WITH_ARDUINO) || defined(_WIN32) - pdu = (coap_pdu_t *)coap_malloc(sizeof(coap_pdu_t) + size); -#endif -#ifdef WITH_CONTIKI - pdu = (coap_pdu_t *)memb_alloc(&pdu_storage); +#if defined(WITH_POSIX) || defined(WITH_CONTIKI) || defined(WITH_ARDUINO) || defined(_WIN32) + pdu = (coap_pdu_t *)coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); + if (!pdu) return NULL; + pdu->hdr = coap_malloc_type(COAP_PDU_BUF, size); + if (pdu->hdr == NULL) { + coap_free_type(COAP_PDU, pdu); + pdu = NULL; + } #endif #ifdef WITH_LWIP + pdu = (coap_pdu_t*)coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); + if (!pdu) return NULL; p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (p != NULL) { - u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t)); - /* we could catch that case and allocate larger memory in advance, but then - * again, we'd run into greater trouble with incoming packages anyway */ - LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0); - pdu = p->payload; - } else { + if (p == NULL) { + coap_free_type(COAP_PDU, pdu); pdu = NULL; } #endif @@ -185,7 +185,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, coap_pdu_t * coap_new_pdu(void) { - return coap_new_pdu2(COAP_UDP, 0); + return coap_new_pdu2(COAP_UDP, COAP_MAX_PDU_SIZE); } coap_pdu_t * @@ -198,11 +198,7 @@ coap_new_pdu2(coap_transport_t transport, unsigned int size) { #else /* WITH_CONTIKI */ uip_ntohs(COAP_INVALID_TID), #endif /* WITH_CONTIKI */ -#ifndef WITH_TCP - COAP_MAX_PDU_SIZE, -#else size, -#endif transport); #ifndef NDEBUG @@ -259,7 +255,7 @@ coap_get_tcp_header_type_from_size(unsigned int size) { coap_transport_t coap_get_tcp_header_type_from_initbyte(unsigned int length) { coap_transport_t type; - switch(length) { + switch (length) { case COAP_TCP_LENGTH_FIELD_NUM_8_BIT: type = COAP_TCP_8BIT; break; @@ -279,7 +275,7 @@ void coap_add_length(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int length) { assert(pdu); - switch(transport) { + switch (transport) { case COAP_TCP: pdu->transport_hdr->tcp.header_data[0] = length << 4; break; @@ -316,7 +312,7 @@ coap_get_length_from_header(const unsigned char *header, coap_transport_t transp unsigned int length = 0; unsigned int length_field_data = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = header[0] >> 4; break; @@ -344,7 +340,7 @@ coap_get_length(const coap_pdu_t *pdu, coap_transport_t transport) { unsigned int length = 0; unsigned int length_field_data = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = pdu->transport_hdr->tcp.header_data[0] >> 4; break; @@ -388,7 +384,7 @@ coap_get_tcp_header_length(unsigned char *data) { unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport) { unsigned int length = 0; - switch(transport) { + switch (transport) { case COAP_TCP: length = COAP_TCP_HEADER_NO_FIELD; break; @@ -443,7 +439,7 @@ void coap_add_code(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int code) { assert(pdu); - switch(transport) { + switch (transport) { case COAP_UDP: pdu->transport_hdr->udp.code = COAP_RESPONSE_CODE(code); break; @@ -471,7 +467,7 @@ coap_get_code(const coap_pdu_t *pdu, coap_transport_t transport) { assert(pdu); unsigned int code = 0; - switch(transport) { + switch (transport) { case COAP_UDP: code = pdu->transport_hdr->udp.code; break; @@ -509,7 +505,7 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, return 0; unsigned char* token = NULL; - switch(transport) { + switch (transport) { case COAP_UDP: pdu->transport_hdr->udp.token_length = len; token = pdu->transport_hdr->udp.token; @@ -568,7 +564,7 @@ coap_get_token2(const coap_hdr_transport_t *pdu_hdr, coap_transport_t transport, assert(token); assert(token_length); - switch(transport) { + switch (transport) { case COAP_UDP: *token_length = pdu_hdr->udp.token_length; *token = (unsigned char *)pdu_hdr->udp.token; @@ -616,7 +612,7 @@ coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, return 0; } - switch(transport) { + switch (transport) { #ifdef WITH_TCP case COAP_TCP: opt = (unsigned char *) &(pdu->transport_hdr->tcp) + pdu->length; @@ -825,7 +821,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, coap_opt_t *opt = NULL; unsigned int tokenLength = 0; #ifdef WITH_TCP - switch(transport) { + switch (transport) { case COAP_UDP: break; case COAP_TCP: diff --git a/src/resource.c b/src/resource.c index aa4f383285..a021f9b0ff 100644 --- a/src/resource.c +++ b/src/resource.c @@ -116,7 +116,7 @@ match(const str *text, const str *pattern, int match_prefix, int match_substring while (remaining_length) { size_t token_length; unsigned char *token = next_token; - next_token = memchr(token, ' ', remaining_length); + next_token = (unsigned char *)memchr(token, ' ', remaining_length); if (next_token) { token_length = next_token - token; diff --git a/src/str.c b/src/str.c index f5800c257b..6f4872f222 100644 --- a/src/str.c +++ b/src/str.c @@ -15,8 +15,8 @@ #include "str.h" str *coap_new_string(size_t size) { - str *s = coap_malloc(sizeof(str) + size + 1); - if ( !s ) { + str *s = (str *)coap_malloc(sizeof(str) + size + 1); + if (!s) { #ifndef NDEBUG coap_log(LOG_CRIT, "coap_new_string: malloc\n"); #endif diff --git a/src/uri.c b/src/uri.c index 95065a662b..801d3adb40 100644 --- a/src/uri.c +++ b/src/uri.c @@ -414,7 +414,7 @@ coap_uri_t * coap_new_uri(const unsigned char *uri, unsigned int length) { unsigned char *result; - result = coap_malloc(length + 1 + sizeof(coap_uri_t)); + result = (unsigned char *)coap_malloc(length + 1 + sizeof(coap_uri_t)); if (!result) return NULL; @@ -476,7 +476,7 @@ coap_clone_uri(const coap_uri_t *uri) { * segment_handler_t hence we use this wrapper as safe typecast. */ COAP_STATIC_INLINE void hash_segment(unsigned char *s, size_t len, void *data) { - coap_hash(s, len, data); + coap_hash(s, len, (unsigned char *)data); } int @@ -530,14 +530,14 @@ coap_parse_next(coap_parse_iterator_t *pi) { /* skip following separator (the first segment might not have one) */ - if (strchr((const char*)s,*(pi->pos))) { + if (strchr((const char*)s, *(pi->pos))) { ++pi->pos; --pi->n; } p = pi->pos; - while ((pi->segment_length < pi->n) && (!strchr((const char*)s,*p)) + while ((pi->segment_length < pi->n) && (!strchr((const char*)s, *p)) && (!strnchr(pi->delim, pi->dlen, *p))) { ++p; ++pi->segment_length; From 42aedb23adbcd6da633be98e67dc30eb89f1fb94 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 22 Sep 2016 06:41:04 -0700 Subject: [PATCH 05/27] Fix merge bug Signed-off-by: Dave Thaler --- src/pdu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pdu.c b/src/pdu.c index 92f2b398fe..543cbbd53c 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -806,7 +806,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, unsigned int headerSize = 0; if (COAP_UDP == transport) { - headerSize = sizeof(sizeof(coap_hdr_t)); + headerSize = sizeof(coap_hdr_t); } #ifdef WITH_TCP else { From 65e73985b78fbf5a640cd2b2c421c2026d605984 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 22 Sep 2016 12:50:35 -0700 Subject: [PATCH 06/27] Windows-specific fix --- src/coap_io.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coap_io.c b/src/coap_io.c index 0fe0cb20cc..57baa222c2 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -388,7 +388,15 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, return -1; } +#ifdef WSA_CMSG_SPACE + { + int sent = 0; + WSASendMsg(ep->handle.fd, &mhdr, 0, &sent, NULL, NULL); + return sent; + } +#else return sendmsg(ep->handle.fd, &mhdr, 0); +#endif #else /* WITH_CONTIKI */ /* FIXME: untested */ /* FIXME: is there a way to check if send was successful? */ From e43531beacace27981e773470bb3f2c68d96d6c6 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 22 Sep 2016 15:02:22 -0700 Subject: [PATCH 07/27] Port tests to windows Signed-off-by: Dave Thaler --- src/net.c | 2 +- tests/test_options.c | 26 ++++++++++++++++---------- tests/test_uri.c | 8 +++++++- tests/test_wellknown.c | 6 ++++++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/net.c b/src/net.c index ef7ea6bc40..140ab3e0cf 100644 --- a/src/net.c +++ b/src/net.c @@ -554,7 +554,7 @@ coap_send_ack(coap_context_t *context, return result; } -#if defined(WITH_POSIX) || defined(WITH_CONTIKI) +#if !defined(WITH_LWIP) static coap_tid_t coap_send_impl(coap_context_t *context, const coap_endpoint_t *local_interface, diff --git a/tests/test_options.c b/tests/test_options.c index 5bb51f4d0e..62e4811efa 100644 --- a/tests/test_options.c +++ b/tests/test_options.c @@ -423,10 +423,16 @@ t_access_option7(void) { #define TEST_MAX_SIZE 1000 +#ifdef _MSC_VER +# define ALIGNED(x) +#else +# define ALIGNED(x) __attribute__ ((aligned (x))) +#endif + static void t_iterate_option1(void) { /* CoAP PDU without token, options, or data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00 }; @@ -451,7 +457,7 @@ t_iterate_option1(void) { static void t_iterate_option2(void) { /* CoAP PDU with token but without options and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k' }; @@ -476,7 +482,7 @@ t_iterate_option2(void) { static void t_iterate_option3(void) { /* CoAP PDU with token and options */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x' }; @@ -517,7 +523,7 @@ t_iterate_option3(void) { static void t_iterate_option4(void) { /* CoAP PDU with token, options, and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x', 0xff, 'd', 'a', 't', 'a' @@ -559,7 +565,7 @@ t_iterate_option4(void) { static void t_iterate_option5(void) { /* CoAP PDU with malformed option */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x52, 'o', 'p', 0xee, 0x12, 0x03, 0x00 }; @@ -591,7 +597,7 @@ static void t_iterate_option6(void) { /* option filter */ /* CoAP PDU with token, options, and data */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00 }; @@ -635,7 +641,7 @@ t_iterate_option6(void) { static void t_iterate_option7(void) { /* option filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; @@ -681,7 +687,7 @@ t_iterate_option7(void) { static void t_iterate_option8(void) { /* option filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; @@ -711,7 +717,7 @@ t_iterate_option8(void) { static void t_iterate_option9(void) { /* options filter: option number too large for filter */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; @@ -741,7 +747,7 @@ t_iterate_option9(void) { static void t_iterate_option10(void) { /* options filter: option numbers in PDU exceed filter size */ - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xd0, 0x26, 0xe0, 0x10, 0x00 }; diff --git a/tests/test_uri.c b/tests/test_uri.c index 004cbd6ab8..0f87c51b7d 100644 --- a/tests/test_uri.c +++ b/tests/test_uri.c @@ -316,9 +316,15 @@ t_parse_uri12(void) { } } +#ifdef _MSC_VER +# define ALIGNED(x) +#else +# define ALIGNED(x) __attribute__ ((aligned (x))) +#endif + static void t_parse_uri13(void) { - uint8_t teststr[] __attribute__ ((aligned (8))) = { + uint8_t teststr[] ALIGNED(8) = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 'f', 'o', 'o', 0x3b, '.', 'w', 'e', 'l', 'l', '-', 'k', 'n', 'o', 'w', 'n', 0x04, 'c', 'o', diff --git a/tests/test_wellknown.c b/tests/test_wellknown.c index 57a4db7a41..aa445a1886 100644 --- a/tests/test_wellknown.c +++ b/tests/test_wellknown.c @@ -12,7 +12,9 @@ #include #include +#ifdef HAVE_NETINET_IN_H #include +#endif #include #include #include @@ -139,8 +141,12 @@ t_wellknown3(void) { /* , (TEST_URI_LEN + 4 chars) */ for (j = 0; j < num_resources; j++) { +#ifdef HAVE_SNPRINTF int len = snprintf((char *)uribuf, TEST_URI_LEN + 1, "%0*d", TEST_URI_LEN, j); +#else + int len = sprintf((char *)uribuf, "%0*d", TEST_URI_LEN, j); +#endif r = coap_resource_init(uribuf, len, 0); coap_add_resource(ctx, r); uribuf += TEST_URI_LEN; From 749514f4200cc0675dc134562b42a8ca06b831fe Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 11 Oct 2016 11:03:39 -0700 Subject: [PATCH 08/27] Fix for x86 Windows Signed-off-by: Dave Thaler --- src/pdu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pdu.c b/src/pdu.c index 543cbbd53c..44fc5d1e9d 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -18,6 +18,9 @@ #ifdef HAVE_ARPA_INET_H #include #endif +#ifdef HAVE_WINSOCK2_H +#include +#endif #include "debug.h" #include "pdu.h" From 9feaa9ee2f976e4cdcb6999c95edb3a8165fdad8 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 14 Oct 2016 14:07:47 -0700 Subject: [PATCH 09/27] Fix release build error Signed-off-by: Dave Thaler --- src/coap_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coap_io.c b/src/coap_io.c index 57baa222c2..46a41f2bfd 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -54,6 +54,7 @@ typedef SOCKET coap_socket_t; #include "debug.h" #include "mem.h" #include "coap_io.h" +#include "pdu.h" #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) struct coap_packet_t { From 9373a4c774a6d84cbf58ea71d11bdf50a8250d86 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 19 Jan 2017 18:32:03 -0800 Subject: [PATCH 10/27] Linux compilation fix Signed-off-by: Dave Thaler --- configure.ac | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configure.ac b/configure.ac index 9de9f3bd91..ec5e966424 100644 --- a/configure.ac +++ b/configure.ac @@ -274,6 +274,7 @@ AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h \ # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T AC_TYPE_SSIZE_T +AC_C_INLINE # Checks for library functions. AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo \ @@ -351,6 +352,17 @@ tests/Makefile libcoap-$LIBCOAP_API_VERSION.pc:libcoap-$LIBCOAP_API_VERSION.pc.in ]) +AH_BOTTOM([ +/* Make libcoap headers safe to use from C++ */ +#ifndef COAP_STATIC_INLINE +# if defined(__cplusplus) +# define COAP_STATIC_INLINE inline +# else +# define COAP_STATIC_INLINE static inline +# endif +#endif +]) + AC_OUTPUT AC_MSG_RESULT([ From fa987b4d44c8cc3da67396e3666ae69ffa416468 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 20 Jan 2017 11:00:49 -0800 Subject: [PATCH 11/27] Fixes from merging Signed-off-by: Dave Thaler --- include/coap/address.h | 4 ++-- src/address.c | 4 ++-- src/coap_io.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/coap/address.h b/include/coap/address.h index ae9b1ef444..ebbedafb83 100644 --- a/include/coap/address.h +++ b/include/coap/address.h @@ -138,13 +138,13 @@ coap_address_isany(const coap_address_t *a) { return _coap_address_isany_impl(a); } -#ifdef WITH_POSIX +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) /** * Checks if given address @p a denotes a multicast address. This function * returns @c 1 if @p a is multicast, @c 0 otherwise. */ int coap_is_mcast(const coap_address_t *a); -#else /* WITH_POSIX */ +#else /* !(WITH_POSIX || HAVE_WS2TCPIP_H) */ /** * Checks if given address @p a denotes a multicast address. This function * returns @c 1 if @p a is multicast, @c 0 otherwise. diff --git a/src/address.c b/src/address.c index b8afff33ae..b83cc3937e 100644 --- a/src/address.c +++ b/src/address.c @@ -8,7 +8,7 @@ #include "coap_config.h" -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) #include #ifdef HAVE_ARPA_INET_H #include @@ -63,7 +63,7 @@ int coap_is_mcast(const coap_address_t *a) { } return 0; } -#else /* WITH_POSIX */ +#else /* !(WITH_POSIX || HAVE_WS2TCPIP_H) */ /* make compilers happy that do not like empty modules */ COAP_STATIC_INLINE void dummy() diff --git a/src/coap_io.c b/src/coap_io.c index 6b85a8da0d..40800eec72 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -56,7 +56,7 @@ typedef SOCKET coap_socket_t; #include "coap_io.h" #include "pdu.h" -#ifdef WITH_POSIX +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) /* define generic PKTINFO for IPv4 */ #if defined(IP_PKTINFO) # define GEN_IP_PKTINFO IP_PKTINFO @@ -87,7 +87,7 @@ struct coap_packet_t { size_t length; /**< length of payload */ unsigned char payload[]; /**< payload */ }; -#endif +#endif /* WITH_POSIX || HAVE_WS2TCPIP_H */ #ifndef CUSTOM_COAP_NETWORK_ENDPOINT From d03c8a0c5719646983f2922e8d185bb5a6169a5e Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 20 Jan 2017 11:29:59 -0800 Subject: [PATCH 12/27] Addressed feedback from tijuca, don't use negative logic in ifdefs Signed-off-by: Dave Thaler --- include/coap/address.h | 12 ++++++------ include/coap/coap_io.h | 6 ++++-- include/coap/coap_time.h | 4 ++-- include/coap/prng.h | 6 ++++-- src/address.c | 2 +- src/coap_io.c | 6 +++--- src/debug.c | 2 +- src/net.c | 4 ++-- src/resource.c | 2 +- 9 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/coap/address.h b/include/coap/address.h index ebbedafb83..e6ce887a72 100644 --- a/include/coap/address.h +++ b/include/coap/address.h @@ -60,7 +60,7 @@ typedef struct coap_address_t { #define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) #endif /* WITH_CONTIKI */ -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) /** multi-purpose address abstraction */ typedef struct coap_address_t { socklen_t size; /**< size of addr */ @@ -95,7 +95,7 @@ _coap_address_isany_impl(const coap_address_t *a) { return 0; } -#endif /* WITH_POSIX */ +#endif /* WITH_POSIX || HAVE_WS2TCPIP_H */ /** * Resets the given coap_address_t object @p addr to its default values. In @@ -108,8 +108,8 @@ COAP_STATIC_INLINE void coap_address_init(coap_address_t *addr) { assert(addr); memset(addr, 0, sizeof(coap_address_t)); -#if defined(WITH_LWIP) || defined(WITH_CONTIKI) - /* lwip and Contiki have constant address sizes and doesn't need the .size part */ +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) + /* lwip and Contiki have constant address sizes and don't need the .size part */ addr->size = sizeof(addr->addr); #endif } @@ -144,7 +144,7 @@ coap_address_isany(const coap_address_t *a) { * returns @c 1 if @p a is multicast, @c 0 otherwise. */ int coap_is_mcast(const coap_address_t *a); -#else /* !(WITH_POSIX || HAVE_WS2TCPIP_H) */ +#else /* WITH_POSIX || HAVE_WS2TCPIP_H */ /** * Checks if given address @p a denotes a multicast address. This function * returns @c 1 if @p a is multicast, @c 0 otherwise. @@ -153,6 +153,6 @@ COAP_STATIC_INLINE int coap_is_mcast(const coap_address_t *a) { return a && _coap_is_mcast_impl(a); } -#endif /* WITH_POSIX */ +#endif /* WITH_POSIX || HAVE_WS2TCPIP_H */ #endif /* _COAP_ADDRESS_H_ */ diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index 9c8b584bb7..f7dad6e2d3 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -33,12 +33,14 @@ struct coap_context_t; * tuple (handle, addr) must uniquely identify this endpoint. */ typedef struct coap_endpoint_t { -#ifndef WITH_LWIP +#if defined(WITH_POSIX) || defined(WITH_CONTIKI) || defined(HAVE_WS2TCPIP_H) union { int fd; /**< on POSIX systems */ void *conn; /**< opaque connection (e.g. uip_conn in Contiki) */ } handle; /**< opaque handle to identify this endpoint */ -#else +#endif /* WITH_POSIX || WITH_CONTIKI || HAVE_WS2TCPIP_H */ + +#ifdef WITH_LWIP struct udp_pcb *pcb; /**< @FIXME --chrysn * this was added in a hurry, not sure it confirms to the overall model */ diff --git a/include/coap/coap_time.h b/include/coap/coap_time.h index bd877c675b..9caa2f5370 100644 --- a/include/coap/coap_time.h +++ b/include/coap/coap_time.h @@ -76,7 +76,7 @@ COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { } #endif /* WITH_CONTIKI */ -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) /** * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND * resolution. @@ -119,7 +119,7 @@ void coap_ticks(coap_tick_t *t); * point (seconds since epoch on POSIX). */ coap_time_t coap_ticks_to_rt(coap_tick_t t); -#endif /* !WITH_LWIP && !WITH_CONTIKI */ +#endif /* WITH_POSIX || HAVE_WS2TCPIP_H */ /** * Returns @c 1 if and only if @p a is less than @p b where less is defined on a diff --git a/include/coap/prng.h b/include/coap/prng.h index 71266acc17..f19e7eff35 100644 --- a/include/coap/prng.h +++ b/include/coap/prng.h @@ -20,7 +20,7 @@ * @{ */ -#if !defined(WITH_CONTIKI) && !defined(LWIP_RAND) +#if defined(WITH_POSIX) || (defined(WITH_LWIP) && !defined(LWIP_RAND)) || defined(HAVE_WS2TCPIP_H) #include /** @@ -34,7 +34,9 @@ coap_prng_impl(unsigned char *buf, size_t len) { *buf++ = rand() & 0xFF; return 1; } -#else /* WITH_CONTIKI */ +#endif /* WITH_POSIX || (WITH_LWIP && !LWIP_RAND) || HAVE_WS2TCPIP_H */ + +#ifdef WITH_CONTIKI #include /** diff --git a/src/address.c b/src/address.c index b83cc3937e..98e39aa83e 100644 --- a/src/address.c +++ b/src/address.c @@ -63,7 +63,7 @@ int coap_is_mcast(const coap_address_t *a) { } return 0; } -#else /* !(WITH_POSIX || HAVE_WS2TCPIP_H) */ +#else /* WITH_POSIX || HAVE_WS2TCPIP_H */ /* make compilers happy that do not like empty modules */ COAP_STATIC_INLINE void dummy() diff --git a/src/coap_io.c b/src/coap_io.c index 40800eec72..c70a48b02d 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -263,7 +263,7 @@ struct in_pktinfo { }; #endif -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(SOL_IP) +#if (defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H)) && !defined(SOL_IP) /* Solaris and Windows expect level IPPROTO_IP for ancillary data. */ #define SOL_IP IPPROTO_IP #endif @@ -427,7 +427,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef CUSTOM_COAP_NETWORK_READ #define SIN6(A) ((struct sockaddr_in6 *)(A)) -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defiend(HAVE_WS2TCPIP_H) static coap_packet_t * coap_malloc_packet(void) { coap_packet_t *packet; @@ -444,7 +444,7 @@ void coap_free_packet(coap_packet_t *packet) { coap_free(packet); } -#endif /* WITH_POSIX */ +#endif /* WITH_POSIX || HAVE_WS2TCPIP_H */ #ifdef WITH_CONTIKI COAP_STATIC_INLINE coap_packet_t * coap_malloc_packet(void) { diff --git a/src/debug.c b/src/debug.c index 7412705054..da103d2a84 100644 --- a/src/debug.c +++ b/src/debug.c @@ -167,7 +167,7 @@ print_readable( const unsigned char *data, unsigned int len, size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#if defined(HAVE_ARPA_INET_H) || defined(_WIN32) +#if defined(HAVE_ARPA_INET_H) || defined(HAVE_WS2TCPIP_H) const void *addrptr = NULL; in_port_t port; unsigned char *p = buf; diff --git a/src/net.c b/src/net.c index 9f36c73c90..54c9bd9532 100644 --- a/src/net.c +++ b/src/net.c @@ -118,7 +118,7 @@ /** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_TIMEOUT */ #define ACK_TIMEOUT Q(FRAC_BITS, COAP_DEFAULT_ACK_TIMEOUT) -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) time_t clock_offset = 0; @@ -553,7 +553,7 @@ coap_send_ack(coap_context_t *context, return result; } -#if !defined(WITH_LWIP) +#if defined(WITH_POSIX) || defined(WITH_CONTIKI) || defined(HAVE_WS2TCPIP_H) static coap_tid_t coap_send_impl(coap_context_t *context, const coap_endpoint_t *local_interface, diff --git a/src/resource.c b/src/resource.c index a021f9b0ff..806eb022a9 100644 --- a/src/resource.c +++ b/src/resource.c @@ -29,7 +29,7 @@ #endif -#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) #define COAP_MALLOC_TYPE(Type) \ ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) From ccc0f0140a70f33be634406ba9114d7fbe1c3cd5 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 20 Jan 2017 11:32:10 -0800 Subject: [PATCH 13/27] Fix typo Signed-off-by: Dave Thaler --- src/coap_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coap_io.c b/src/coap_io.c index c70a48b02d..f9d4962592 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -427,7 +427,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifndef CUSTOM_COAP_NETWORK_READ #define SIN6(A) ((struct sockaddr_in6 *)(A)) -#if defined(WITH_POSIX) || defiend(HAVE_WS2TCPIP_H) +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) static coap_packet_t * coap_malloc_packet(void) { coap_packet_t *packet; From 092d7e2f20d609185c4aafd19ac5dcb10722fcbf Mon Sep 17 00:00:00 2001 From: Pawel Winogrodzki Date: Thu, 26 Jan 2017 17:01:40 -0800 Subject: [PATCH 14/27] Fixing C4018 warnings for x86 builds. Signed-off-by: Pawel Winogrodzki --- include/coap/bits.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/coap/bits.h b/include/coap/bits.h index d7f0bf53ab..1397dde169 100644 --- a/include/coap/bits.h +++ b/include/coap/bits.h @@ -30,7 +30,7 @@ */ COAP_STATIC_INLINE int bits_setb(uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) + if (size <= ((size_t)bit >> 3)) return -1; *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07)); @@ -50,7 +50,7 @@ bits_setb(uint8_t *vec, size_t size, uint8_t bit) { */ COAP_STATIC_INLINE int bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) + if (size <= ((size_t)bit >> 3)) return -1; *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07))); @@ -69,7 +69,7 @@ bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { */ COAP_STATIC_INLINE int bits_getb(const uint8_t *vec, size_t size, uint8_t bit) { - if (size <= (bit >> 3)) + if (size <= ((size_t)bit >> 3)) return -1; return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0; From bc69a9fab0594124e2b1a852095f292a5f919c5d Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 27 Jan 2017 14:01:12 -0800 Subject: [PATCH 15/27] Fix travis issues Signed-off-by: Dave Thaler --- coap_config.h.contiki | 9 +++++ coap_config.h.lwip | 9 +++++ coap_config.h.windows | 3 ++ configure.ac | 2 +- examples/client.c | 47 +++++++++++++++++-------- examples/{coap_list.c => coap_append.c} | 26 ++------------ examples/{coap_list.h => coap_append.h} | 20 +++-------- include/coap/net.h | 4 +++ include/coap/utlist.h | 1 + 9 files changed, 66 insertions(+), 55 deletions(-) rename examples/{coap_list.c => coap_append.c} (65%) rename examples/{coap_list.h => coap_append.h} (52%) diff --git a/coap_config.h.contiki b/coap_config.h.contiki index 87fdbf077a..ba5f42af70 100644 --- a/coap_config.h.contiki +++ b/coap_config.h.contiki @@ -131,5 +131,14 @@ typedef void FILE; #include #define coap_log(fd, ...) printf(__VA_ARGS__) +/* Make libcoap headers safe to use from C++ */ +#ifndef COAP_STATIC_INLINE +# if defined(__cplusplus) +# define COAP_STATIC_INLINE inline +# else +# define COAP_STATIC_INLINE static inline +# endif +#endif + #endif /* _CONFIG_H_ */ diff --git a/coap_config.h.lwip b/coap_config.h.lwip index 5f397a0ea6..9b0f6dad7b 100644 --- a/coap_config.h.lwip +++ b/coap_config.h.lwip @@ -22,4 +22,13 @@ #define COAP_RESOURCES_NOHASH +/* Make libcoap headers safe to use from C++ */ +#ifndef COAP_STATIC_INLINE +# if defined(__cplusplus) +# define COAP_STATIC_INLINE inline +# else +# define COAP_STATIC_INLINE static inline +# endif +#endif + #endif /* _CONFIG_H_ */ diff --git a/coap_config.h.windows b/coap_config.h.windows index 810ba6bd42..303e58dd04 100644 --- a/coap_config.h.windows +++ b/coap_config.h.windows @@ -43,6 +43,9 @@ /* Define to the full name of this package. */ #define PACKAGE_NAME "libcoap" +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.1.1" + /* Define to the full name and version of this package. */ #define PACKAGE_STRING "libcoap 4.1.1" diff --git a/configure.ac b/configure.ac index 695bc34980..c5f91a2aab 100644 --- a/configure.ac +++ b/configure.ac @@ -292,7 +292,7 @@ fi # Checks for header files. AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h \ - stdlib.h string.h strings.h sys/socket.h sys/time.h \ + stdlib.h string.h strings.h sys/select.h sys/socket.h sys/time.h \ time.h unistd.h sys/unistd.h syslog.h]) # Checks for typedefs, structures, and compiler characteristics. diff --git a/examples/client.c b/examples/client.c index eb73c6583d..bd60f55c88 100644 --- a/examples/client.c +++ b/examples/client.c @@ -12,18 +12,33 @@ #include #include -#include +#ifdef HAVE_UNISTD_H +# include +#else +# include "getopt.h" +#endif #include #include -#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif #include #include -#include -#include -#include -#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif #include "coap.h" +#include "coap_append.h" #include "coap_list.h" int flags = 0; @@ -61,7 +76,9 @@ coap_tick_t max_wait; /* global timeout (changed by set_timeou unsigned int obs_seconds = 30; /* default observe time */ coap_tick_t obs_wait = 0; /* timeout for current subscription */ +#ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) +#endif #ifdef __GNUC__ #define UNUSED_PARAM __attribute__ ((unused)) @@ -694,7 +711,7 @@ cmdline_uri(char *arg, int create_uri_opts) { if (proxy.length) { /* create Proxy-Uri from argument */ size_t len = strlen(arg); while (len > 270) { - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_PROXY_URI, 270, (unsigned char *)arg)); @@ -703,7 +720,7 @@ cmdline_uri(char *arg, int create_uri_opts) { arg += 270; } - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_PROXY_URI, len, (unsigned char *)arg)); @@ -714,7 +731,7 @@ cmdline_uri(char *arg, int create_uri_opts) { } if (uri.port != COAP_DEFAULT_PORT && create_uri_opts) { - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_URI_PORT, coap_encode_var_bytes(portbuf, uri.port), portbuf)); @@ -725,7 +742,7 @@ cmdline_uri(char *arg, int create_uri_opts) { res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); while (res--) { - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf))); @@ -740,7 +757,7 @@ cmdline_uri(char *arg, int create_uri_opts) { res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); while (res--) { - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf))); @@ -792,14 +809,14 @@ set_blocksize(void) { opt_length = coap_encode_var_bytes(buf, (block.num << 4 | block.m << 3 | block.szx)); - coap_insert(&optlist, new_option_node(opt, opt_length, buf)); + coap_append(&optlist, new_option_node(opt, opt_length, buf)); } } static void cmdline_subscribe(char *arg) { obs_seconds = atoi(arg); - coap_insert(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL)); + coap_append(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL)); } static int @@ -852,7 +869,7 @@ cmdline_option(char *arg) { if (*arg == ',') ++arg; - coap_insert(&optlist, + coap_append(&optlist, new_option_node(num, strlen(arg), (unsigned char *)arg)); } @@ -1212,7 +1229,7 @@ main(int argc, char **argv) { && create_uri_opts) { /* add Uri-Host */ - coap_insert(&optlist, + coap_append(&optlist, new_option_node(COAP_OPTION_URI_HOST, uri.host.length, uri.host.s)); diff --git a/examples/coap_list.c b/examples/coap_append.c similarity index 65% rename from examples/coap_list.c rename to examples/coap_append.c index 06e59168d9..2c561eaa8c 100644 --- a/examples/coap_list.c +++ b/examples/coap_append.c @@ -15,11 +15,10 @@ #include "debug.h" #include "mem.h" -#include "coap_list.h" - +#include "coap_append.h" int -coap_insert(coap_list_t **head, coap_list_t *node) { +coap_append(coap_list_t **head, coap_list_t *node) { if (!node) { coap_log(LOG_WARNING, "cannot create option Proxy-Uri\n"); } else { @@ -30,24 +29,3 @@ coap_insert(coap_list_t **head, coap_list_t *node) { return node != NULL; } - -int -coap_delete(coap_list_t *node) { - if (node) { - coap_free(node); - } - return 1; -} - -void -coap_delete_list(coap_list_t *queue) { - coap_list_t *elt, *tmp; - - if (!queue) - return; - - LL_FOREACH_SAFE(queue, elt, tmp) { - coap_delete(elt); - } -} - diff --git a/examples/coap_list.h b/examples/coap_append.h similarity index 52% rename from examples/coap_list.h rename to examples/coap_append.h index 14a68a3005..c1a8f44bf5 100644 --- a/examples/coap_list.h +++ b/examples/coap_append.h @@ -8,26 +8,16 @@ * use. */ -#ifndef _COAP_LIST_H_ -#define _COAP_LIST_H_ +#ifndef _COAP_APPEND_H_ +#define _COAP_APPEND_H_ #include "utlist.h" - -typedef struct coap_list_t { - struct coap_list_t *next; - char data[]; -} coap_list_t; +#include "coap_list.h" /** * Adds node to given queue, ordered by specified order function. Returns 1 * when insert was successful, 0 otherwise. */ -int coap_insert(coap_list_t **queue, coap_list_t *node); - -/* destroys specified node */ -int coap_delete(coap_list_t *node); - -/* removes all items from given queue and frees the allocated storage */ -void coap_delete_list(coap_list_t *queue); +int coap_append(coap_list_t **queue, coap_list_t *node); -#endif /* _COAP_LIST_H_ */ +#endif /* _COAP_APPEND_H_ */ diff --git a/include/coap/net.h b/include/coap/net.h index 75cf851e60..628e94c0cf 100644 --- a/include/coap/net.h +++ b/include/coap/net.h @@ -103,6 +103,10 @@ typedef struct coap_context_t { int sockfd; /**< send/receive socket */ #endif /* WITH_POSIX */ +#ifdef HAVE_WS2TCPIP_H + SOCKET sockfd; /**< send/receive socket */ +#endif /* HAVE_WS2TCPIP_H */ + #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/include/coap/utlist.h b/include/coap/utlist.h index b5f3f04c10..b0380a8d16 100644 --- a/include/coap/utlist.h +++ b/include/coap/utlist.h @@ -111,6 +111,7 @@ do { LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _tmp; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ From 2238ebb8a70898e6589f532b88ac0ff97344fb2c Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 27 Jan 2017 14:46:08 -0800 Subject: [PATCH 16/27] Fix more travis issues Signed-off-by: Dave Thaler --- examples/Makefile.am | 2 +- include/coap/coap_io.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Makefile.am b/examples/Makefile.am index 087aef4b4e..dfc5a1df22 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -14,7 +14,7 @@ AM_CFLAGS = -isystem$(top_builddir)/include/coap -I$(top_srcdir)/include/coap $( # etsi_iot_01 and tiny are missing bin_PROGRAMS = coap-client coap-server coap-rd -coap_client_SOURCES = client.c coap_list.c +coap_client_SOURCES = client.c coap_append.c coap_client_LDADD = $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la coap_server_SOURCES = coap-server.c diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index f7dad6e2d3..54582547ce 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -140,7 +140,7 @@ struct coap_packet_t { coap_if_handle_t hnd; /**< the interface handle */ coap_address_t src; /**< the packet's source address */ coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; + const coap_endpoint_t *endpoint; int ifindex; void *session; /**< opaque session data */ size_t length; /**< length of payload */ From c38dc95a7515156d68d009bed43278e2892b0caa Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 27 Jan 2017 14:46:08 -0800 Subject: [PATCH 17/27] Fix more travis issues Signed-off-by: Dave Thaler --- examples/Makefile.am | 2 +- examples/coap_append.c | 2 +- include/coap/coap_io.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Makefile.am b/examples/Makefile.am index 087aef4b4e..dfc5a1df22 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -14,7 +14,7 @@ AM_CFLAGS = -isystem$(top_builddir)/include/coap -I$(top_srcdir)/include/coap $( # etsi_iot_01 and tiny are missing bin_PROGRAMS = coap-client coap-server coap-rd -coap_client_SOURCES = client.c coap_list.c +coap_client_SOURCES = client.c coap_append.c coap_client_LDADD = $(top_builddir)/.libs/libcoap-$(LIBCOAP_API_VERSION).la coap_server_SOURCES = coap-server.c diff --git a/examples/coap_append.c b/examples/coap_append.c index 2c561eaa8c..d3fba4b7cd 100644 --- a/examples/coap_append.c +++ b/examples/coap_append.c @@ -8,7 +8,7 @@ * use. */ -/* #include "coap_config.h" */ +#include "coap_config.h" #include #include diff --git a/include/coap/coap_io.h b/include/coap/coap_io.h index f7dad6e2d3..54582547ce 100644 --- a/include/coap/coap_io.h +++ b/include/coap/coap_io.h @@ -140,7 +140,7 @@ struct coap_packet_t { coap_if_handle_t hnd; /**< the interface handle */ coap_address_t src; /**< the packet's source address */ coap_address_t dst; /**< the packet's destination address */ - const coap_endpoint_t *interface; + const coap_endpoint_t *endpoint; int ifindex; void *session; /**< opaque session data */ size_t length; /**< length of payload */ From 8c39fe4d534cd3cb65123fdc5e7f87a3f592e490 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 27 Jan 2017 15:14:53 -0800 Subject: [PATCH 18/27] Fix more travis issues Signed-off-by: Dave Thaler --- examples/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/client.c b/examples/client.c index bd60f55c88..5fec4f81ed 100644 --- a/examples/client.c +++ b/examples/client.c @@ -36,6 +36,10 @@ #ifdef HAVE_NETDB_H # include #endif +#ifndef HAVE_STRCASECMP + /* The POSIX strcasecmp() is not supported, so use the ISO C++ conformant _stricmp instead. */ +# define strcasecmp _stricmp +#endif #include "coap.h" #include "coap_append.h" From 62c679216e1332560e3cefc1384c5bb63ab37fe8 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Fri, 27 Jan 2017 15:14:53 -0800 Subject: [PATCH 19/27] Fix more travis issues Signed-off-by: Dave Thaler --- Makefile.am | 1 + examples/client.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Makefile.am b/Makefile.am index 15e4881a1d..49e8499d8a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ libcoap_@LIBCOAP_API_VERSION@_la_SOURCES = \ src/async.c \ src/block.c \ src/coap_io.c \ + src/coap_list.c \ src/coap_time.c \ src/debug.c \ src/encode.c \ diff --git a/examples/client.c b/examples/client.c index bd60f55c88..5fec4f81ed 100644 --- a/examples/client.c +++ b/examples/client.c @@ -36,6 +36,10 @@ #ifdef HAVE_NETDB_H # include #endif +#ifndef HAVE_STRCASECMP + /* The POSIX strcasecmp() is not supported, so use the ISO C++ conformant _stricmp instead. */ +# define strcasecmp _stricmp +#endif #include "coap.h" #include "coap_append.h" From 40a26419bcafc570a9e6669921f790edb048edd5 Mon Sep 17 00:00:00 2001 From: Dan Mihai Date: Wed, 8 Mar 2017 12:04:08 -0800 Subject: [PATCH 20/27] Fix pdu length truncation Apparently caused by an incorrect merge. Signed-off-by: Dan Mihai --- src/pdu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pdu.c b/src/pdu.c index e4aa2699f1..2ed2c39b5c 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -928,7 +928,6 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, if (length > sizeof(coap_hdr_t)) { memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t)); } - pdu->length = length; /* Finally calculate beginning of data block and thereby check integrity * of the PDU structure. */ From d54f00179f70a64dbb7d3349e57d914045e35a45 Mon Sep 17 00:00:00 2001 From: Pawel Winogrodzki Date: Mon, 6 Mar 2017 19:52:40 -0800 Subject: [PATCH 21/27] Fixing libcoap W4 warnings. This commit makes sure libcoap doesn't generate any W4 warnings when building with a Visual Studion 2013 and 2015 compiler. --- include/coap/net.h | 2 -- include/coap/pdu.h | 2 +- src/coap_io.c | 19 +++++++++++++--- src/coap_time.c | 3 ++- src/encode.c | 3 ++- src/net.c | 8 +++---- src/pdu.c | 57 +++++++++++++++++++++++++++------------------- 7 files changed, 58 insertions(+), 36 deletions(-) diff --git a/include/coap/net.h b/include/coap/net.h index 3d37972034..628e94c0cf 100644 --- a/include/coap/net.h +++ b/include/coap/net.h @@ -400,11 +400,9 @@ int coap_handle_message(coap_context_t *ctx, * @param pdu The message that initiated the transaction. * @param id Set to the new id. */ -#if defined(WITH_POSIX) || defined(WITH_LWIP) || defined(WITH_CONTIKI) void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, coap_tid_t *id); -#endif /** * This function removes the element with given @p id from the list given list. diff --git a/include/coap/pdu.h b/include/coap/pdu.h index 02df50bfce..506febb7a4 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -300,7 +300,7 @@ typedef struct { */ typedef struct { - size_t max_size; /**< allocated storage for options and data */ + size_t max_size; /**< allocated storage for options and data */ union { coap_hdr_t *hdr; /**< Address of the first byte of the CoAP message. * This may or may not equal (coap_hdr_t*)(pdu+1) diff --git a/src/coap_io.c b/src/coap_io.c index 2bac45c81c..b8500a16b0 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -21,7 +21,6 @@ # define CLOSE_SOCKET(fd) close(fd) # define COAP_SOCKET_ERROR (-1) # define COAP_INVALID_SOCKET (-1) -typedef int coap_socket_t; #endif #ifdef HAVE_NETINET_IN_H # include @@ -37,7 +36,6 @@ typedef int coap_socket_t; # define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR # define CMSG_LEN WSA_CMSG_LEN # define CMSG_SPACE WSA_CMSG_SPACE -typedef SOCKET coap_socket_t; #endif #ifdef HAVE_SYS_UIO_H # include @@ -290,6 +288,10 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, (void)context; #ifdef WSA_CMSG_SPACE + (void)datalen; + (void)data; + (void)context; + WSAMSG mhdr; WSABUF dataBuf; @@ -298,6 +300,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, mhdr.name = (PSOCKADDR)&dst->addr.sa; mhdr.lpBuffers = &dataBuf; mhdr.dwBufferCount = 1; + mhdr.Control.buf = buf; #else struct msghdr mhdr; struct iovec iov[1]; @@ -320,7 +323,12 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct in6_pktinfo *pktinfo; #ifdef WSA_CMSG_SPACE +#pragma warning( push ) +#pragma warning( disable : 4116 ) + /* Warning C4116 "unnamed type definition in parantheses" is harmless in + * this case and the unnamed type is part of a system header macro. */ mhdr.Control.len = CMSG_SPACE(sizeof(struct in6_pktinfo)); +#pragma warning( pop ) #else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); #endif @@ -353,7 +361,12 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct in_pktinfo *pktinfo; #ifdef WSA_CMSG_SPACE +#pragma warning( push ) +#pragma warning( disable : 4116 ) + /* Warning C4116 "unnamed type definition in parantheses" is harmless in + * this case and the unnamed type is part of a system header macro. */ mhdr.Control.len = CMSG_SPACE(sizeof(struct in_pktinfo)); +#pragma warning( pop ) #else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); #endif @@ -406,7 +419,7 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, #ifdef WSA_CMSG_SPACE { - int sent = 0; + DWORD sent = 0; WSASendMsg(ep->handle.fd, &mhdr, 0, &sent, NULL, NULL); return sent; } diff --git a/src/coap_time.c b/src/coap_time.c index db924ebb2d..e8d04061f4 100644 --- a/src/coap_time.c +++ b/src/coap_time.c @@ -35,6 +35,7 @@ static coap_tick_t coap_clock_offset = 0; #ifdef HAVE_WINSOCK2_H static int gettimeofday(struct timeval *tp, TIME_ZONE_INFORMATION *tzp) { + (void)tzp; static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); SYSTEMTIME system_time; @@ -76,7 +77,7 @@ coap_clock_init(void) { void coap_ticks(coap_tick_t *t) { - unsigned long tmp; + coap_tick_t tmp; #ifdef COAP_CLOCK struct timespec tv; diff --git a/src/encode.c b/src/encode.c index f4cf75ef0e..bfea17c36f 100644 --- a/src/encode.c +++ b/src/encode.c @@ -18,7 +18,8 @@ #endif /* Carsten suggested this when fls() is not available: */ -coap_fls(unsigned int i) { +#ifndef HAVE_FLS +int coap_fls(unsigned int i) { return coap_flsll(i); } #endif diff --git a/src/net.c b/src/net.c index fe232e9c8a..809cc32dc9 100644 --- a/src/net.c +++ b/src/net.c @@ -496,19 +496,16 @@ coap_option_check_critical(coap_context_t *ctx, return ok; } -#if defined(WITH_POSIX) || defined(WITH_LWIP) || defined(WITH_CONTIKI) void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, coap_tid_t *id) { - (void)peer; - coap_key_t h; memset(h, 0, sizeof(coap_key_t)); /* Compare the transport address. */ -#ifdef WITH_POSIX +#if defined(WITH_POSIX) || defined(HAVE_WS2TCPIP_H) switch (peer->addr.sa.sa_family) { case AF_INET: coap_hash((const unsigned char *)&peer->addr.sin.sin_port, @@ -536,7 +533,6 @@ coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, *id = (((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3])) & INT_MAX; } -#endif coap_tid_t coap_send_ack(coap_context_t *context, @@ -1574,6 +1570,8 @@ handle_locally(coap_context_t *context __attribute__ ((unused)), handle_locally(coap_context_t *context, coap_queue_t *node) { #endif /* GCC */ /* this function can be used to check if node->pdu is really for us */ + (void)context; + (void)node; return 1; } diff --git a/src/pdu.c b/src/pdu.c index 29c71b6466..bfdc82f617 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -39,6 +39,7 @@ coap_pdu_clear(coap_pdu_t *pdu, size_t size) { void coap_pdu_clear2(coap_pdu_t *pdu, size_t size, coap_transport_t transport, unsigned int length) { + assert(length <= USHRT_MAX); assert(pdu); #ifdef WITH_LWIP @@ -61,7 +62,7 @@ coap_pdu_clear2(coap_pdu_t *pdu, size_t size, coap_transport_t transport, unsign #ifdef WITH_TCP else { /* data is NULL unless explicitly set by coap_add_data() */ - pdu->length = length; + pdu->length = (unsigned short)length; } #endif } @@ -105,7 +106,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, struct pbuf *p; #endif - unsigned int length = 0; + size_t length = 0; switch (transport) { case COAP_UDP: length = sizeof(coap_hdr_t); @@ -128,6 +129,8 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, debug("it has wrong type\n"); } + assert(length <= UINT_MAX); + #ifndef WITH_TCP assert(size <= COAP_MAX_PDU_SIZE); /* Size must be large enough to fit the header. */ @@ -158,7 +161,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, #ifdef WITH_LWIP pdu->pbuf = p; #endif - coap_pdu_clear2(pdu, size, transport, length); + coap_pdu_clear2(pdu, size, transport, (unsigned int)length); switch (transport) { case COAP_UDP: pdu->transport_hdr->udp.id = id; @@ -284,17 +287,21 @@ coap_add_length(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int switch (transport) { case COAP_TCP: - pdu->transport_hdr->tcp.header_data[0] = length << 4; + assert(length < COAP_TCP_LENGTH_FIELD_8_BIT); + pdu->transport_hdr->tcp.header_data[0] = (length << 4) & 0x0000ff; break; case COAP_TCP_8BIT: if (length > COAP_TCP_LENGTH_FIELD_8_BIT) { + unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_8_BIT; + assert(total_length <= UCHAR_MAX); pdu->transport_hdr->tcp_8bit.header_data[1] = - length - COAP_TCP_LENGTH_FIELD_8_BIT; + total_length & 0x0000ff; } break; case COAP_TCP_16BIT: if (length > COAP_TCP_LENGTH_FIELD_16_BIT) { unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_16_BIT; + assert(total_length <= USHRT_MAX); pdu->transport_hdr->tcp_16bit.header_data[1] = (total_length >> 8) & 0x0000ff; pdu->transport_hdr->tcp_16bit.header_data[2] = total_length & 0x000000ff; } @@ -444,24 +451,27 @@ coap_get_opt_header_length(unsigned short key, size_t length) { void coap_add_code(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int code) { + unsigned int long_code = COAP_RESPONSE_CODE(code); + assert(long_code <= UINT8_MAX); assert(pdu); + unsigned char coap_code = (unsigned char)long_code; switch (transport) { case COAP_UDP: - pdu->transport_hdr->udp.code = COAP_RESPONSE_CODE(code); + pdu->transport_hdr->udp.code = coap_code; break; #ifdef WITH_TCP case COAP_TCP: - pdu->transport_hdr->tcp.header_data[1] = COAP_RESPONSE_CODE(code); + pdu->transport_hdr->tcp.header_data[1] = coap_code; break; case COAP_TCP_8BIT: - pdu->transport_hdr->tcp_8bit.header_data[2] = COAP_RESPONSE_CODE(code); + pdu->transport_hdr->tcp_8bit.header_data[2] = coap_code; break; case COAP_TCP_16BIT: - pdu->transport_hdr->tcp_16bit.header_data[3] = COAP_RESPONSE_CODE(code); + pdu->transport_hdr->tcp_16bit.header_data[3] = coap_code; break; case COAP_TCP_32BIT: - pdu->transport_hdr->tcp_32bit.header_data[5] = COAP_RESPONSE_CODE(code); + pdu->transport_hdr->tcp_32bit.header_data[5] = coap_code; break; #endif default: @@ -511,45 +521,46 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH) return 0; + unsigned char token_len = (unsigned char)len; unsigned char* token = NULL; switch (transport) { case COAP_UDP: - pdu->transport_hdr->udp.token_length = (unsigned char)len; + pdu->transport_hdr->udp.token_length = token_len; token = pdu->transport_hdr->udp.token; - pdu->length = HEADERLENGTH; + pdu->length = (unsigned short)HEADERLENGTH; break; #ifdef WITH_TCP case COAP_TCP: pdu->transport_hdr->tcp.header_data[0] = - pdu->transport_hdr->tcp.header_data[0] | len; + pdu->transport_hdr->tcp.header_data[0] | token_len; token = pdu->transport_hdr->tcp.token; - pdu->length = len + COAP_TCP_HEADER_NO_FIELD; + pdu->length = token_len + COAP_TCP_HEADER_NO_FIELD; break; case COAP_TCP_8BIT: pdu->transport_hdr->tcp_8bit.header_data[0] = - pdu->transport_hdr->tcp_8bit.header_data[0] | len; + pdu->transport_hdr->tcp_8bit.header_data[0] | token_len; token = pdu->transport_hdr->tcp_8bit.token; - pdu->length = len + COAP_TCP_HEADER_8_BIT; + pdu->length = token_len + COAP_TCP_HEADER_8_BIT; break; case COAP_TCP_16BIT: pdu->transport_hdr->tcp_16bit.header_data[0] = - pdu->transport_hdr->tcp_16bit.header_data[0] | len; + pdu->transport_hdr->tcp_16bit.header_data[0] | token_len; token = pdu->transport_hdr->tcp_16bit.token; - pdu->length = len + COAP_TCP_HEADER_16_BIT; + pdu->length = token_len + COAP_TCP_HEADER_16_BIT; break; case COAP_TCP_32BIT: pdu->transport_hdr->tcp_32bit.header_data[0] = - pdu->transport_hdr->tcp_32bit.header_data[0] | len; + pdu->transport_hdr->tcp_32bit.header_data[0] | token_len; token = pdu->transport_hdr->tcp_32bit.token; - pdu->length = len + COAP_TCP_HEADER_32_BIT; + pdu->length = token_len + COAP_TCP_HEADER_32_BIT; break; #endif default: debug("it has wrong type\n"); } - if (len) { - memcpy(token, data, len); + if (token_len) { + memcpy(token, data, token_len); } pdu->max_delta = 0; @@ -875,7 +886,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, printf("it has wrong type\n"); } #endif - pdu->length = length; + pdu->length = (unsigned short)length; if (COAP_UDP == transport) { pdu->transport_hdr->udp.version = data[0] >> 6; From 9f1d95669fe36a135f73220ad23e964b04bfdecc Mon Sep 17 00:00:00 2001 From: Pawel Winogrodzki Date: Tue, 4 Apr 2017 14:43:16 -0700 Subject: [PATCH 22/27] Bracket fixes. Making sure that "if" statements have opening brackets on the same line to fit the with the rest of the code. --- src/coap_io.c | 8 ++------ src/net.c | 3 +-- src/resource.c | 9 +++------ 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/coap_io.c b/src/coap_io.c index b8500a16b0..9c7257d881 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -323,12 +323,10 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct in6_pktinfo *pktinfo; #ifdef WSA_CMSG_SPACE -#pragma warning( push ) -#pragma warning( disable : 4116 ) /* Warning C4116 "unnamed type definition in parantheses" is harmless in * this case and the unnamed type is part of a system header macro. */ +#pragma warning( suppress : 4116 ) mhdr.Control.len = CMSG_SPACE(sizeof(struct in6_pktinfo)); -#pragma warning( pop ) #else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); #endif @@ -361,12 +359,10 @@ coap_network_send(struct coap_context_t *context UNUSED_PARAM, struct in_pktinfo *pktinfo; #ifdef WSA_CMSG_SPACE -#pragma warning( push ) -#pragma warning( disable : 4116 ) /* Warning C4116 "unnamed type definition in parantheses" is harmless in * this case and the unnamed type is part of a system header macro. */ +#pragma warning( suppress : 4116 ) mhdr.Control.len = CMSG_SPACE(sizeof(struct in_pktinfo)); -#pragma warning( pop ) #else mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); #endif diff --git a/src/net.c b/src/net.c index 809cc32dc9..a61ee0ef8d 100644 --- a/src/net.c +++ b/src/net.c @@ -1260,8 +1260,7 @@ coap_wellknown_response(coap_context_t *context, coap_pdu_t *request) { } unsigned int new_resp_length = resp->length + COAP_PRINT_OUTPUT_LENGTH(result); - if (new_resp_length > USHRT_MAX) - { + if (new_resp_length > USHRT_MAX) { debug("coap_print_wellknown failed - print result too large\n"); goto error; } diff --git a/src/resource.c b/src/resource.c index 16e65508fe..005124dbbb 100644 --- a/src/resource.c +++ b/src/resource.c @@ -284,8 +284,7 @@ coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen *buflen = written; output_length = p - buf; - if (output_length > COAP_PRINT_STATUS_MAX) - { + if (output_length > COAP_PRINT_STATUS_MAX) { return COAP_PRINT_STATUS_ERROR; } @@ -527,8 +526,7 @@ coap_print_link(const coap_resource_t *resource, output_length = p - buf; - if (output_length > COAP_PRINT_STATUS_MAX) - { + if (output_length > COAP_PRINT_STATUS_MAX) { return COAP_PRINT_STATUS_ERROR; } @@ -692,8 +690,7 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r) { if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON) coap_delete_pdu(response); - if (COAP_INVALID_TID == tid) - { + if (COAP_INVALID_TID == tid) { debug("coap_check_notify: sending failed, resource stays partially dirty\n"); obs->dirty = 1; r->partiallydirty = 1; From 2f6ff0c39ad6dcab579826692fdc8f4b84407024 Mon Sep 17 00:00:00 2001 From: G S Senthil Kumar Date: Fri, 28 Apr 2017 20:32:33 +0530 Subject: [PATCH 23/27] Added CoAP over WebSocket support. This change contains only packet format changes in the library to support coap+ws and coaps+ws. Signed-off-by: G S Senthil Kumar --- include/coap/pdu.h | 22 +++++++++++++-- src/option.c | 14 ++++++++++ src/pdu.c | 68 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 94 insertions(+), 10 deletions(-) diff --git a/include/coap/pdu.h b/include/coap/pdu.h index 506febb7a4..92fe4e3af6 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -180,6 +180,8 @@ typedef int coap_tid_t; */ #define COAP_DROPPED_RESPONSE -2 +#define COAP_WS_HEADER 2 + #define COAP_TCP_HEADER_NO_FIELD 2 #define COAP_TCP_HEADER_8_BIT 3 #define COAP_TCP_HEADER_16_BIT 4 @@ -207,7 +209,10 @@ typedef enum { COAP_TCP, COAP_TCP_8BIT, COAP_TCP_16BIT, - COAP_TCP_32BIT + COAP_TCP_32BIT, +#endif +#ifdef WITH_WS + COAP_WS #endif } coap_transport_t; @@ -255,14 +260,24 @@ typedef struct { } coap_hdr_tcp_32bit_t; #endif /* WITH_TCP */ +#ifdef WITH_WS +typedef struct { + unsigned char header_data[COAP_WS_HEADER]; + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_ws_t; +#endif /* WITH_WS */ + typedef union { coap_hdr_udp_t udp; #ifdef WITH_TCP - coap_hdr_tcp_t tcp; + coap_hdr_tcp_t tcp; coap_hdr_tcp_8bit_t tcp_8bit; coap_hdr_tcp_16bit_t tcp_16bit; coap_hdr_tcp_32bit_t tcp_32bit; #endif /* WITH_TCP */ +#ifdef WITH_WS + coap_hdr_ws_t ws; +#endif /* WITH_WS */ } coap_hdr_transport_t; // Typedef for backwards compatibility. @@ -534,6 +549,8 @@ unsigned int coap_get_tcp_header_length(unsigned char *data); */ unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport); +#endif /* WITH_TCP */ + /** * Get option length. * @@ -542,7 +559,6 @@ unsigned int coap_get_tcp_header_length_for_transport(coap_transport_t transport * @return total option length */ size_t coap_get_opt_header_length(unsigned short key, size_t length); -#endif /* WITH_TCP */ /** * Add code in coap header. diff --git a/src/option.c b/src/option.c index 4b4f126a25..712e809f4f 100644 --- a/src/option.c +++ b/src/option.c @@ -152,6 +152,12 @@ coap_option_iterator_init2(coap_pdu_t *pdu, coap_opt_iterator_t *oi, token_length = pdu->transport_hdr->tcp_32bit.header_data[0] & 0x0f; headerSize = COAP_TCP_HEADER_32_BIT; break; +#endif +#ifdef WITH_WS + case COAP_WS: + token_length = pdu->transport_hdr->ws.header_data[0] & 0x0f; + headerSize = COAP_WS_HEADER; + break; #endif default: token_length = pdu->transport_hdr->udp.token_length; @@ -166,6 +172,14 @@ coap_option_iterator_init2(coap_pdu_t *pdu, coap_opt_iterator_t *oi, return NULL; } } +#ifdef WITH_WS + else if (COAP_WS == transport) { + if ((unsigned char *) &(pdu->transport_hdr->ws) + pdu->length <= oi->next_option) { + oi->bad = 1; + return NULL; + } + } +#endif #ifdef WITH_TCP else { if ((unsigned char *) &(pdu->transport_hdr->tcp) + pdu->length <= oi->next_option) { diff --git a/src/pdu.c b/src/pdu.c index bfdc82f617..ddbc9c6b9f 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -59,7 +59,7 @@ coap_pdu_clear2(coap_pdu_t *pdu, size_t size, coap_transport_t transport, unsign /* data is NULL unless explicitly set by coap_add_data() */ pdu->length = sizeof(coap_hdr_t); } -#ifdef WITH_TCP +#if defined(WITH_TCP) || defined(WITH_WS) else { /* data is NULL unless explicitly set by coap_add_data() */ pdu->length = (unsigned short)length; @@ -124,6 +124,11 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, case COAP_TCP_32BIT: length = COAP_TCP_HEADER_32_BIT; break; +#endif +#ifdef WITH_WS + case COAP_WS: + length = COAP_WS_HEADER; + break; #endif default: debug("it has wrong type\n"); @@ -131,7 +136,7 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, assert(length <= UINT_MAX); -#ifndef WITH_TCP +#if !defined(WITH_TCP) && !defined(WITH_WS) assert(size <= COAP_MAX_PDU_SIZE); /* Size must be large enough to fit the header. */ if (size < length || size > COAP_MAX_PDU_SIZE) @@ -185,6 +190,12 @@ coap_pdu_init2(unsigned char type, unsigned char code, unsigned short id, pdu->transport_hdr->tcp_32bit.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_32_BIT << 4; pdu->transport_hdr->tcp_32bit.header_data[5] = code; break; +#endif +#ifdef WITH_WS + case COAP_WS: + pdu->transport_hdr->ws.header_data[0] = 0; + pdu->transport_hdr->ws.header_data[1] = code; + break; #endif default: debug("it has wrong type\n"); @@ -417,6 +428,7 @@ coap_get_tcp_header_length_for_transport(coap_transport_t transport) { return length; } +#endif size_t coap_get_opt_header_length(unsigned short key, size_t length) { @@ -447,7 +459,6 @@ coap_get_opt_header_length(unsigned short key, size_t length) { return headerLength; } -#endif void coap_add_code(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int code) { @@ -473,6 +484,11 @@ coap_add_code(const coap_pdu_t *pdu, coap_transport_t transport, unsigned int co case COAP_TCP_32BIT: pdu->transport_hdr->tcp_32bit.header_data[5] = coap_code; break; +#endif +#ifdef WITH_WS + case COAP_WS: + pdu->transport_hdr->ws.header_data[1] = coap_code; + break; #endif default: debug("it has wrong type\n"); @@ -501,6 +517,11 @@ coap_get_code(const coap_pdu_t *pdu, coap_transport_t transport) { case COAP_TCP_32BIT: code = pdu->transport_hdr->tcp_32bit.header_data[5]; break; +#endif +#ifdef WITH_WS + case COAP_WS: + code = pdu->transport_hdr->ws.header_data[1]; + break; #endif default: debug("it has wrong type\n"); @@ -554,6 +575,14 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, token = pdu->transport_hdr->tcp_32bit.token; pdu->length = token_len + COAP_TCP_HEADER_32_BIT; break; +#endif +#ifdef WITH_WS + case COAP_WS: + pdu->transport_hdr->ws.header_data[0] = + pdu->transport_hdr->ws.header_data[0] | token_len; + token = pdu->transport_hdr->ws.token; + pdu->length = token_len + COAP_WS_HEADER; + break; #endif default: debug("it has wrong type\n"); @@ -604,6 +633,12 @@ coap_get_token2(const coap_hdr_transport_t *pdu_hdr, coap_transport_t transport, *token_length = (pdu_hdr->tcp_32bit.header_data[0]) & 0x0f; *token = (unsigned char *)pdu_hdr->tcp_32bit.token; break; +#endif +#ifdef WITH_WS + case COAP_WS: + *token_length = (pdu_hdr->ws.header_data[0]) & 0x0f; + *token = (unsigned char *)pdu_hdr->ws.token; + break; #endif default: debug("it has wrong type\n"); @@ -621,7 +656,7 @@ coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data, coap_transport_t transport) { size_t optsize; coap_opt_t *opt; - + assert(pdu); pdu->data = NULL; @@ -644,6 +679,11 @@ coap_add_option2(coap_pdu_t *pdu, unsigned short type, unsigned int len, case COAP_TCP_32BIT: opt = (unsigned char *) &(pdu->transport_hdr->tcp_32bit) + pdu->length; break; +#endif +#ifdef WITH_WS + case COAP_WS: + opt = (unsigned char *) &(pdu->transport_hdr->ws) + pdu->length; + break; #endif default: opt = (unsigned char *) &(pdu->transport_hdr->udp) + pdu->length; @@ -832,6 +872,11 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, if (COAP_UDP == transport) { headerSize = sizeof(coap_hdr_t); } +#ifdef WITH_WS + else if(COAP_WS == transport) { + headerSize = COAP_WS_HEADER; + } +#endif #ifdef WITH_TCP else { headerSize = coap_get_tcp_header_length_for_transport(transport); @@ -844,7 +889,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, coap_opt_t *opt = NULL; unsigned int tokenLength = 0; -#ifdef WITH_TCP +#if defined(WITH_TCP) || defined(WITH_WS) switch (transport) { case COAP_UDP: break; @@ -882,6 +927,15 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, opt = ((unsigned char *) &(pdu->transport_hdr->tcp_32bit)) + headerSize + tokenLength; break; + case COAP_WS: + for (size_t i = 0 ; i < headerSize ; i++) { + pdu->transport_hdr->ws.header_data[i] = data[i]; + } + + tokenLength = data[0] & 0x0f; + opt = ((unsigned char *) &(pdu->transport_hdr->ws)) + + headerSize + tokenLength; + break; default: printf("it has wrong type\n"); } @@ -922,8 +976,8 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, length -= (tokenLength + headerSize); opt = (unsigned char *) (&(pdu->transport_hdr->udp) + 1) + tokenLength; } -#ifdef WITH_TCP - else { // common for tcp header setting +#if defined(WITH_TCP) || defined(WITH_WS) + else { // common for tcp and websocket header setting pdu->data = NULL; if (length < headerSize + tokenLength || tokenLength > 8) { From 5f2d2386f10ac675e176a1fda9c86b77a3ac8415 Mon Sep 17 00:00:00 2001 From: Koushik4082 Date: Thu, 17 May 2018 11:16:02 +0000 Subject: [PATCH 24/27] Update pdu.c --- src/pdu.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/pdu.c b/src/pdu.c index ddbc9c6b9f..b9cfd71cb9 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -598,6 +598,63 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, return 1; } +int coap_add_token_for_empty_message(coap_pdu_t *pdu, size_t len, const unsigned char *data, + coap_transport_t transport) +{ + const size_t HEADERLENGTH = len; + /* must allow for pdu == NULL as callers may rely on this */ + if (!pdu || len > 8) + return 0; + + unsigned char* token = NULL; + switch(transport) + { + case COAP_UDP: + pdu->transport_hdr->udp.token_length = len; + token = pdu->transport_hdr->udp.token; + pdu->length = HEADERLENGTH; + break; +#ifdef WITH_TCP + case COAP_TCP: + pdu->transport_hdr->tcp.header_data[0] = + pdu->transport_hdr->tcp.header_data[0] | len; + token = pdu->transport_hdr->tcp.token; + pdu->length = len + COAP_TCP_HEADER_NO_FIELD; + break; + case COAP_TCP_8BIT: + pdu->transport_hdr->tcp_8bit.header_data[0] = + pdu->transport_hdr->tcp_8bit.header_data[0] | len; + token = pdu->transport_hdr->tcp_8bit.token; + pdu->length = len + COAP_TCP_HEADER_8_BIT; + break; + case COAP_TCP_16BIT: + pdu->transport_hdr->tcp_16bit.header_data[0] = + pdu->transport_hdr->tcp_16bit.header_data[0] | len; + token = pdu->transport_hdr->tcp_16bit.token; + pdu->length = len + COAP_TCP_HEADER_16_BIT; + break; + case COAP_TCP_32BIT: + pdu->transport_hdr->tcp_32bit.header_data[0] = + pdu->transport_hdr->tcp_32bit.header_data[0] | len; + token = pdu->transport_hdr->tcp_32bit.token; + pdu->length = len + COAP_TCP_HEADER_32_BIT; + break; +#endif + default: + debug("it has wrong type\n"); + } + + if (len) + { + memcpy(token, data, len); + } + + pdu->max_delta = 0; + pdu->data = NULL; + + return 1; +} + void coap_get_token(const coap_hdr_t *pdu_hdr, unsigned char **token, unsigned int *token_length) { From 5dc2fdc0acb07bcfaf753d8b47df0bd04cac7922 Mon Sep 17 00:00:00 2001 From: Koushik4082 Date: Thu, 17 May 2018 11:21:09 +0000 Subject: [PATCH 25/27] Update pdu.c --- src/pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pdu.c b/src/pdu.c index b9cfd71cb9..d5bfded7a6 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -598,8 +598,8 @@ coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, return 1; } -int coap_add_token_for_empty_message(coap_pdu_t *pdu, size_t len, const unsigned char *data, - coap_transport_t transport) +int coap_add_token_to_empty_message(coap_pdu_t *pdu, size_t len, const unsigned char *data, + coap_transport_t transport) { const size_t HEADERLENGTH = len; /* must allow for pdu == NULL as callers may rely on this */ From bd60461ddf50646ba67808965db939688b275d74 Mon Sep 17 00:00:00 2001 From: Koushik4082 Date: Thu, 17 May 2018 11:22:41 +0000 Subject: [PATCH 26/27] Update pdu.h --- include/coap/pdu.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/coap/pdu.h b/include/coap/pdu.h index 92fe4e3af6..7cdc174ef2 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -612,6 +612,16 @@ int coap_add_token(coap_pdu_t *pdu, int coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, coap_transport_t transport); +/** + * @param pdu The pdu pointer. + * @param len The length of the new token. + * @param data The token to add. + * @param transport The transport type. + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token_to_empty_message(coap_pdu_t *pdu, size_t len, const unsigned char *data, + coap_transport_t transport); + /** * Get token from coap header * From b49710964baf246a0fb53e1581779438bd2faf20 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 13 Sep 2018 08:29:23 -0600 Subject: [PATCH 27/27] Fix for where WITH_TCP is defined, WITH_WS is not. The function coap_pdu_parse2() as changed by iotivity patches has a block of code bracketed by #if defined(WITH_TCP) || defined(WITH_WS) the problem is this block contains a reference to a structure member that is defined only if WITH_WS is defined, and it is possible to build this code in iotivity in the presence of WITH_TCP and the absence of WITH_WS. Whether that should ever happen is a separate question; the change keeps these two conditions separate so this can be used in the iotivity CI system which does build some targets in the way noted. Signed-off-by: Mats Wichmann --- include/coap/pdu.h | 2 +- src/pdu.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/coap/pdu.h b/include/coap/pdu.h index 7cdc174ef2..ca37071520 100644 --- a/include/coap/pdu.h +++ b/include/coap/pdu.h @@ -621,7 +621,7 @@ int coap_add_token2(coap_pdu_t *pdu, size_t len, const unsigned char *data, */ int coap_add_token_to_empty_message(coap_pdu_t *pdu, size_t len, const unsigned char *data, coap_transport_t transport); - + /** * Get token from coap header * diff --git a/src/pdu.c b/src/pdu.c index d5bfded7a6..5d531888ae 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -950,6 +950,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, switch (transport) { case COAP_UDP: break; +#if defined(WITH_TCP) case COAP_TCP: for (size_t i = 0 ; i < headerSize ; i++) { pdu->transport_hdr->tcp.header_data[i] = data[i]; @@ -984,6 +985,8 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, opt = ((unsigned char *) &(pdu->transport_hdr->tcp_32bit)) + headerSize + tokenLength; break; +#endif +#if defined(WITH_WS) case COAP_WS: for (size_t i = 0 ; i < headerSize ; i++) { pdu->transport_hdr->ws.header_data[i] = data[i]; @@ -993,6 +996,7 @@ coap_pdu_parse2(unsigned char *data, size_t length, coap_pdu_t *pdu, opt = ((unsigned char *) &(pdu->transport_hdr->ws)) + headerSize + tokenLength; break; +#endif default: printf("it has wrong type\n"); }