forked from espressif/arduino-esp32
update IDF libs and includes
This commit is contained in:
152
tools/sdk/include/coap/coap/address.h
Normal file
152
tools/sdk/include/coap/coap/address.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* address.h -- representation of network addresses
|
||||
*
|
||||
* Copyright (C) 2010-2011,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file address.h
|
||||
* @brief Representation of network addresses
|
||||
*/
|
||||
|
||||
#ifndef _COAP_ADDRESS_H_
|
||||
#define _COAP_ADDRESS_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include "libcoap.h"
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
typedef struct coap_address_t {
|
||||
uint16_t port;
|
||||
ip_addr_t addr;
|
||||
} coap_address_t;
|
||||
|
||||
#define _coap_address_equals_impl(A, B) (!!ip_addr_cmp(&(A)->addr,&(B)->addr))
|
||||
|
||||
#define _coap_address_isany_impl(A) ip_addr_isany(&(A)->addr)
|
||||
|
||||
#define _coap_is_mcast_impl(Address) ip_addr_ismulticast(&(Address)->addr)
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
#include "uip.h"
|
||||
|
||||
typedef struct coap_address_t {
|
||||
uip_ipaddr_t addr;
|
||||
unsigned short port;
|
||||
} coap_address_t;
|
||||
|
||||
#define _coap_address_equals_impl(A,B) \
|
||||
((A)->port == (B)->port \
|
||||
&& uip_ipaddr_cmp(&((A)->addr),&((B)->addr)))
|
||||
|
||||
/** @todo implementation of _coap_address_isany_impl() for Contiki */
|
||||
#define _coap_address_isany_impl(A) 0
|
||||
|
||||
#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr))
|
||||
#endif /* WITH_CONTIKI */
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
/** multi-purpose address abstraction */
|
||||
typedef struct coap_address_t {
|
||||
socklen_t size; /**< size of addr */
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage st;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} addr;
|
||||
} coap_address_t;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
*/
|
||||
int coap_address_equals(const coap_address_t *a, const coap_address_t *b);
|
||||
|
||||
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) {
|
||||
case AF_INET:
|
||||
return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
|
||||
case AF_INET6:
|
||||
return memcmp(&in6addr_any,
|
||||
&a->addr.sin6.sin6_addr,
|
||||
sizeof(in6addr_any)) == 0;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
/**
|
||||
* Resets the given coap_address_t object @p addr to its default values. In
|
||||
* particular, the member size must be initialized to the available size for
|
||||
* storing addresses.
|
||||
*
|
||||
* @param addr The coap_address_t object to initialize.
|
||||
*/
|
||||
static inline void
|
||||
coap_address_init(coap_address_t *addr) {
|
||||
assert(addr);
|
||||
memset(addr, 0, sizeof(coap_address_t));
|
||||
#ifdef WITH_POSIX
|
||||
/* lwip and Contiki have constant address sizes and doesn't need the .size part */
|
||||
addr->size = sizeof(addr->addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WITH_POSIX
|
||||
/**
|
||||
* 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_address_equals(const coap_address_t *a, const coap_address_t *b) {
|
||||
assert(a); assert(b);
|
||||
return _coap_address_equals_impl(a, b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks if given address object @p a denotes the wildcard address. This
|
||||
* 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_address_isany(const coap_address_t *a) {
|
||||
assert(a);
|
||||
return _coap_address_isany_impl(a);
|
||||
}
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
/**
|
||||
* 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 */
|
||||
/**
|
||||
* 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_is_mcast(const coap_address_t *a) {
|
||||
return a && _coap_is_mcast_impl(a);
|
||||
}
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
#endif /* _COAP_ADDRESS_H_ */
|
146
tools/sdk/include/coap/coap/async.h
Normal file
146
tools/sdk/include/coap/coap/async.h
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* async.h -- state management for asynchronous messages
|
||||
*
|
||||
* Copyright (C) 2010-2011 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file async.h
|
||||
* @brief State management for asynchronous messages
|
||||
*/
|
||||
|
||||
#ifndef _COAP_ASYNC_H_
|
||||
#define _COAP_ASYNC_H_
|
||||
|
||||
#include "net.h"
|
||||
|
||||
#ifndef WITHOUT_ASYNC
|
||||
|
||||
/**
|
||||
* @defgroup coap_async Asynchronous Messaging
|
||||
* @{
|
||||
* Structure for managing asynchronous state of CoAP resources. A
|
||||
* coap_resource_t object holds a list of coap_async_state_t objects that can be
|
||||
* used to generate a separate response in case a result of an operation cannot
|
||||
* be delivered in time, or the resource has been explicitly subscribed to with
|
||||
* the option @c observe.
|
||||
*/
|
||||
typedef struct coap_async_state_t {
|
||||
unsigned char flags; /**< holds the flags to control behaviour */
|
||||
|
||||
/**
|
||||
* Holds the internal time when the object was registered with a
|
||||
* resource. This field will be updated whenever
|
||||
* coap_register_async() is called for a specific resource.
|
||||
*/
|
||||
coap_tick_t created;
|
||||
|
||||
/**
|
||||
* This field can be used to register opaque application data with the
|
||||
* asynchronous state object.
|
||||
*/
|
||||
void *appdata;
|
||||
unsigned short message_id; /**< id of last message seen */
|
||||
coap_tid_t id; /**< transaction id */
|
||||
struct coap_async_state_t *next; /**< internally used for linking */
|
||||
coap_address_t peer; /**< the peer to notify */
|
||||
size_t tokenlen; /**< length of the token */
|
||||
unsigned char token[]; /**< the token to use in a response */
|
||||
} coap_async_state_t;
|
||||
|
||||
/* Definitions for Async Status Flags These flags can be used to control the
|
||||
* behaviour of asynchronous response generation.
|
||||
*/
|
||||
#define COAP_ASYNC_CONFIRM 0x01 /**< send confirmable response */
|
||||
#define COAP_ASYNC_SEPARATE 0x02 /**< send separate response */
|
||||
#define COAP_ASYNC_OBSERVED 0x04 /**< the resource is being observed */
|
||||
|
||||
/** release application data on destruction */
|
||||
#define COAP_ASYNC_RELEASE_DATA 0x08
|
||||
|
||||
/**
|
||||
* Allocates a new coap_async_state_t object and fills its fields according to
|
||||
* the given @p request. The @p flags are used to control generation of empty
|
||||
* ACK responses to stop retransmissions and to release registered @p data when
|
||||
* the resource is deleted by coap_free_async(). This function returns a pointer
|
||||
* to the registered coap_async_t object or @c NULL on error. Note that this
|
||||
* function will return @c NULL in case that an object with the same identifier
|
||||
* is already registered.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param peer The remote peer that is to be asynchronously notified.
|
||||
* @param request The request that is handled asynchronously.
|
||||
* @param flags Flags to control state management.
|
||||
* @param data Opaque application data to register. Note that the
|
||||
* storage occupied by @p data is released on destruction
|
||||
* only if flag COAP_ASYNC_RELEASE_DATA is set.
|
||||
*
|
||||
* @return A pointer to the registered coap_async_state_t object or @c
|
||||
* NULL in case of an error.
|
||||
*/
|
||||
coap_async_state_t *
|
||||
coap_register_async(coap_context_t *context,
|
||||
coap_address_t *peer,
|
||||
coap_pdu_t *request,
|
||||
unsigned char flags,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* Removes the state object identified by @p id from @p context. The removed
|
||||
* object is returned in @p s, if found. Otherwise, @p s is undefined. This
|
||||
* function returns @c 1 if the object was removed, @c 0 otherwise. Note that
|
||||
* the storage allocated for the stored object is not released by this
|
||||
* functions. You will have to call coap_free_async() to do so.
|
||||
*
|
||||
* @param context The context where the async object is registered.
|
||||
* @param id The identifier of the asynchronous transaction.
|
||||
* @param s Will be set to the object identified by @p id after removal.
|
||||
*
|
||||
* @return @c 1 if object was removed and @p s updated, or @c 0 if no
|
||||
* object was found with the given id. @p s is valid only if the
|
||||
* return value is @c 1.
|
||||
*/
|
||||
int coap_remove_async(coap_context_t *context,
|
||||
coap_tid_t id,
|
||||
coap_async_state_t **s);
|
||||
|
||||
/**
|
||||
* Releases the memory that was allocated by coap_async_state_init() for the
|
||||
* object @p s. The registered application data will be released automatically
|
||||
* if COAP_ASYNC_RELEASE_DATA is set.
|
||||
*
|
||||
* @param state The object to delete.
|
||||
*/
|
||||
void
|
||||
coap_free_async(coap_async_state_t *state);
|
||||
|
||||
/**
|
||||
* Retrieves the object identified by @p id from the list of asynchronous
|
||||
* transactions that are registered with @p context. This function returns a
|
||||
* pointer to that object or @c NULL if not found.
|
||||
*
|
||||
* @param context The context where the asynchronous objects are registered
|
||||
* with.
|
||||
* @param id The id of the object to retrieve.
|
||||
*
|
||||
* @return A pointer to the object identified by @p id or @c NULL if
|
||||
* not found.
|
||||
*/
|
||||
coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id);
|
||||
|
||||
/**
|
||||
* Updates the time stamp of @p s.
|
||||
*
|
||||
* @param s The state object to update.
|
||||
*/
|
||||
static inline void
|
||||
coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); }
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* WITHOUT_ASYNC */
|
||||
|
||||
#endif /* _COAP_ASYNC_H_ */
|
78
tools/sdk/include/coap/coap/bits.h
Normal file
78
tools/sdk/include/coap/coap/bits.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* bits.h -- bit vector manipulation
|
||||
*
|
||||
* Copyright (C) 2010-2011 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bits.h
|
||||
* @brief Bit vector manipulation
|
||||
*/
|
||||
|
||||
#ifndef _COAP_BITS_H_
|
||||
#define _COAP_BITS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Sets the bit @p bit in bit-vector @p vec. This function returns @c 1 if bit
|
||||
* was set or @c -1 on error (i.e. when the given bit does not fit in the
|
||||
* vector).
|
||||
*
|
||||
* @param vec The bit-vector to change.
|
||||
* @param size The size of @p vec in bytes.
|
||||
* @param bit The bit to set in @p vec.
|
||||
*
|
||||
* @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
|
||||
if (size <= (bit >> 3))
|
||||
return -1;
|
||||
|
||||
*(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the bit @p bit from bit-vector @p vec. This function returns @c 1 if
|
||||
* bit was cleared or @c -1 on error (i.e. when the given bit does not fit in
|
||||
* the vector).
|
||||
*
|
||||
* @param vec The bit-vector to change.
|
||||
* @param size The size of @p vec in bytes.
|
||||
* @param bit The bit to clear from @p vec.
|
||||
*
|
||||
* @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
bits_clrb(uint8_t *vec, size_t size, uint8_t bit) {
|
||||
if (size <= (bit >> 3))
|
||||
return -1;
|
||||
|
||||
*(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of bit @p bit from bit-vector @p vec. This function returns
|
||||
* @c 1 if the bit is set, @c 0 otherwise (even in case of an error).
|
||||
*
|
||||
* @param vec The bit-vector to read from.
|
||||
* @param size The size of @p vec in bytes.
|
||||
* @param bit The bit to get from @p vec.
|
||||
*
|
||||
* @return @c 1 if the bit is set, @c 0 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
bits_getb(const uint8_t *vec, size_t size, uint8_t bit) {
|
||||
if (size <= (bit >> 3))
|
||||
return -1;
|
||||
|
||||
return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0;
|
||||
}
|
||||
|
||||
#endif /* _COAP_BITS_H_ */
|
137
tools/sdk/include/coap/coap/block.h
Normal file
137
tools/sdk/include/coap/coap/block.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* block.h -- block transfer
|
||||
*
|
||||
* Copyright (C) 2010-2012,2014-2015 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_BLOCK_H_
|
||||
#define _COAP_BLOCK_H_
|
||||
|
||||
#include "encode.h"
|
||||
#include "option.h"
|
||||
#include "pdu.h"
|
||||
|
||||
/**
|
||||
* @defgroup block Block Transfer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef COAP_MAX_BLOCK_SZX
|
||||
/**
|
||||
* The largest value for the SZX component in a Block option. Note that
|
||||
* 1 << (COAP_MAX_BLOCK_SZX + 4) should not exceed COAP_MAX_PDU_SIZE.
|
||||
*/
|
||||
#define COAP_MAX_BLOCK_SZX 4
|
||||
#endif /* COAP_MAX_BLOCK_SZX */
|
||||
|
||||
/**
|
||||
* Structure of Block options.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int num; /**< block number */
|
||||
unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */
|
||||
unsigned int szx:3; /**< block size */
|
||||
} coap_block_t;
|
||||
|
||||
/**
|
||||
* Returns the value of the least significant byte of a Block option @p opt.
|
||||
* For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
|
||||
* returns @c NULL.
|
||||
*/
|
||||
#define COAP_OPT_BLOCK_LAST(opt) \
|
||||
(COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0)
|
||||
|
||||
/** Returns the value of the More-bit of a Block option @p opt. */
|
||||
#define COAP_OPT_BLOCK_MORE(opt) \
|
||||
(COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0)
|
||||
|
||||
/** Returns the value of the SZX-field of a Block option @p opt. */
|
||||
#define COAP_OPT_BLOCK_SZX(opt) \
|
||||
(COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0)
|
||||
|
||||
/**
|
||||
* Returns the value of field @c num in the given block option @p block_opt.
|
||||
*/
|
||||
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_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_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;
|
||||
else
|
||||
*(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) &= ~0x08;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes @p block from @p pdu. @p type must be either COAP_OPTION_BLOCK1
|
||||
* or COAP_OPTION_BLOCK2. When option @p type was found in @p pdu, @p block is
|
||||
* initialized with values from this option and the function returns the value
|
||||
* @c 1. Otherwise, @c 0 is returned.
|
||||
*
|
||||
* @param pdu The pdu to search for option @p type.
|
||||
* @param type The option to search for (must be COAP_OPTION_BLOCK1 or
|
||||
* COAP_OPTION_BLOCK2).
|
||||
* @param block The block structure to initilize.
|
||||
*
|
||||
* @return @c 1 on success, @c 0 otherwise.
|
||||
*/
|
||||
int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
|
||||
|
||||
/**
|
||||
* Writes a block option of type @p type to message @p pdu. If the requested
|
||||
* block size is too large to fit in @p pdu, it is reduced accordingly. An
|
||||
* exception is made for the final block when less space is required. The actual
|
||||
* length of the resource is specified in @p data_length.
|
||||
*
|
||||
* This function may change *block to reflect the values written to @p pdu. As
|
||||
* the function takes into consideration the remaining space @p pdu, no more
|
||||
* options should be added after coap_write_block_opt() has returned.
|
||||
*
|
||||
* @param block The block structure to use. On return, this object is
|
||||
* updated according to the values that have been written to
|
||||
* @p pdu.
|
||||
* @param type COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2.
|
||||
* @param pdu The message where the block option should be written.
|
||||
* @param data_length The length of the actual data that will be added the @p
|
||||
* pdu by calling coap_add_block().
|
||||
*
|
||||
* @return @c 1 on success, or a negative value on error.
|
||||
*/
|
||||
int coap_write_block_opt(coap_block_t *block,
|
||||
unsigned short type,
|
||||
coap_pdu_t *pdu,
|
||||
size_t data_length);
|
||||
|
||||
/**
|
||||
* Adds the @p block_num block of size 1 << (@p block_szx + 4) from source @p
|
||||
* data to @p pdu.
|
||||
*
|
||||
* @param pdu The message to add the block.
|
||||
* @param len The length of @p data.
|
||||
* @param data The source data to fill the block with.
|
||||
* @param block_num The actual block number.
|
||||
* @param block_szx Encoded size of block @p block_number.
|
||||
*
|
||||
* @return @c 1 on success, @c 0 otherwise.
|
||||
*/
|
||||
int coap_add_block(coap_pdu_t *pdu,
|
||||
unsigned int len,
|
||||
const unsigned char *data,
|
||||
unsigned int block_num,
|
||||
unsigned char block_szx);
|
||||
/**@}*/
|
||||
|
||||
#endif /* _COAP_BLOCK_H_ */
|
50
tools/sdk/include/coap/coap/coap.h
Normal file
50
tools/sdk/include/coap/coap/coap.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* Modify head file implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* define operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_H_
|
||||
#define _COAP_H_
|
||||
|
||||
#include "libcoap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "address.h"
|
||||
#include "async.h"
|
||||
#include "bits.h"
|
||||
#include "block.h"
|
||||
#include "coap_io.h"
|
||||
#include "coap_time.h"
|
||||
#include "debug.h"
|
||||
#include "encode.h"
|
||||
#include "mem.h"
|
||||
#include "net.h"
|
||||
#include "option.h"
|
||||
#include "pdu.h"
|
||||
#include "prng.h"
|
||||
#include "resource.h"
|
||||
#include "str.h"
|
||||
#include "subscribe.h"
|
||||
#include "uri.h"
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COAP_H_ */
|
59
tools/sdk/include/coap/coap/coap.h.in
Normal file
59
tools/sdk/include/coap/coap/coap.h.in
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_H_
|
||||
#define _COAP_H_
|
||||
|
||||
#include "libcoap.h"
|
||||
|
||||
/* Define the address where bug reports for libcoap should be sent. */
|
||||
#define LIBCOAP_PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@
|
||||
|
||||
/* Define the full name of libcoap. */
|
||||
#define LIBCOAP_PACKAGE_NAME @PACKAGE_NAME@
|
||||
|
||||
/* Define the full name and version of libcoap. */
|
||||
#define LIBCOAP_PACKAGE_STRING @PACKAGE_STRING@
|
||||
|
||||
/* Define the home page for libcoap. */
|
||||
#define LIBCOAP_PACKAGE_URL @PACKAGE_URL@
|
||||
|
||||
/* Define the version of libcoap this file belongs to. */
|
||||
#define LIBCOAP_PACKAGE_VERSION @PACKAGE_VERSION@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "address.h"
|
||||
#include "async.h"
|
||||
#include "bits.h"
|
||||
#include "block.h"
|
||||
#include "coap_io.h"
|
||||
#include "coap_time.h"
|
||||
#include "debug.h"
|
||||
#include "encode.h"
|
||||
#include "mem.h"
|
||||
#include "net.h"
|
||||
#include "option.h"
|
||||
#include "pdu.h"
|
||||
#include "prng.h"
|
||||
#include "resource.h"
|
||||
#include "str.h"
|
||||
#include "subscribe.h"
|
||||
#include "uri.h"
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COAP_H_ */
|
167
tools/sdk/include/coap/coap/coap_io.h
Normal file
167
tools/sdk/include/coap/coap/coap_io.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* coap_io.h -- Default network I/O functions for libcoap
|
||||
*
|
||||
* Copyright (C) 2012-2013 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_IO_H_
|
||||
#define _COAP_IO_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "address.h"
|
||||
|
||||
/**
|
||||
* Abstract handle that is used to identify a local network interface.
|
||||
*/
|
||||
typedef int coap_if_handle_t;
|
||||
|
||||
/** Invalid interface handle */
|
||||
#define COAP_IF_INVALID -1
|
||||
|
||||
struct coap_packet_t;
|
||||
typedef struct coap_packet_t coap_packet_t;
|
||||
|
||||
struct coap_context_t;
|
||||
|
||||
/**
|
||||
* Abstraction of virtual endpoint that can be attached to coap_context_t. The
|
||||
* tuple (handle, addr) must uniquely identify this endpoint.
|
||||
*/
|
||||
typedef struct coap_endpoint_t {
|
||||
#if defined(WITH_POSIX) || defined(WITH_CONTIKI)
|
||||
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
|
||||
struct udp_pcb *pcb;
|
||||
/**< @FIXME --chrysn
|
||||
* this was added in a hurry, not sure it confirms to the overall model */
|
||||
struct coap_context_t *context;
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
coap_address_t addr; /**< local interface address */
|
||||
int ifindex;
|
||||
int flags;
|
||||
} coap_endpoint_t;
|
||||
|
||||
#define COAP_ENDPOINT_NOSEC 0x00
|
||||
#define COAP_ENDPOINT_DTLS 0x01
|
||||
|
||||
coap_endpoint_t *coap_new_endpoint(const coap_address_t *addr, int flags);
|
||||
|
||||
void coap_free_endpoint(coap_endpoint_t *ep);
|
||||
|
||||
/**
|
||||
* Function interface for data transmission. This function returns the number of
|
||||
* bytes that have been transmitted, or a value less than zero on error.
|
||||
*
|
||||
* @param context The calling CoAP context.
|
||||
* @param local_interface The local interface to send the data.
|
||||
* @param dst The address of the receiver.
|
||||
* @param data The data to send.
|
||||
* @param datalen The actual length of @p data.
|
||||
*
|
||||
* @return The number of bytes written on success, or a value
|
||||
* less than zero on error.
|
||||
*/
|
||||
ssize_t coap_network_send(struct coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
unsigned char *data, size_t datalen);
|
||||
|
||||
/**
|
||||
* Function interface for reading data. This function returns the number of
|
||||
* bytes that have been read, or a value less than zero on error. In case of an
|
||||
* error, @p *packet is set to NULL.
|
||||
*
|
||||
* @param ep The endpoint that is used for reading data from the network.
|
||||
* @param packet A result parameter where a pointer to the received packet
|
||||
* structure is stored. The caller must call coap_free_packet to
|
||||
* release the storage used by this packet.
|
||||
*
|
||||
* @return The number of bytes received on success, or a value less than
|
||||
* zero on error.
|
||||
*/
|
||||
ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet);
|
||||
|
||||
#ifndef coap_mcast_interface
|
||||
# define coap_mcast_interface(Local) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Releases the storage allocated for @p packet.
|
||||
*/
|
||||
void coap_free_packet(coap_packet_t *packet);
|
||||
|
||||
/**
|
||||
* Populate the coap_endpoint_t *target from the incoming packet's destination
|
||||
* data.
|
||||
*
|
||||
* This is usually used to copy a packet's data into a node's local_if member.
|
||||
*/
|
||||
void coap_packet_populate_endpoint(coap_packet_t *packet,
|
||||
coap_endpoint_t *target);
|
||||
|
||||
/**
|
||||
* Given an incoming packet, copy its source address into an address struct.
|
||||
*/
|
||||
void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target);
|
||||
|
||||
/**
|
||||
* Given a packet, set msg and msg_len to an address and length of the packet's
|
||||
* data in memory.
|
||||
* */
|
||||
void coap_packet_get_memmapped(coap_packet_t *packet,
|
||||
unsigned char **address,
|
||||
size_t *length);
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
/**
|
||||
* Get the pbuf of a packet. The caller takes over responsibility for freeing
|
||||
* the pbuf.
|
||||
*/
|
||||
struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
/*
|
||||
* This is only included in coap_io.h instead of .c in order to be available for
|
||||
* sizeof in mem.c.
|
||||
*/
|
||||
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;
|
||||
int ifindex;
|
||||
void *session; /**< opaque session data */
|
||||
size_t length; /**< length of payload */
|
||||
unsigned char payload[]; /**< payload */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
/*
|
||||
* This is only included in coap_io.h instead of .c in order to be available for
|
||||
* sizeof in lwippools.h.
|
||||
* Simple carry-over of the incoming pbuf that is later turned into a node.
|
||||
*
|
||||
* Source address data is currently side-banded via ip_current_dest_addr & co
|
||||
* as the packets have limited lifetime anyway.
|
||||
*/
|
||||
struct coap_packet_t {
|
||||
struct pbuf *pbuf;
|
||||
const coap_endpoint_t *local_interface;
|
||||
uint16_t srcport;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _COAP_IO_H_ */
|
142
tools/sdk/include/coap/coap/coap_time.h
Normal file
142
tools/sdk/include/coap/coap/coap_time.h
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* coap_time.h -- Clock Handling
|
||||
*
|
||||
* Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file coap_time.h
|
||||
* @brief Clock Handling
|
||||
*/
|
||||
|
||||
#ifndef _COAP_TIME_H_
|
||||
#define _COAP_TIME_H_
|
||||
|
||||
/**
|
||||
* @defgroup clock Clock Handling
|
||||
* Default implementation of internal clock.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <lwip/sys.h>
|
||||
|
||||
/* lwIP provides ms in sys_now */
|
||||
#define COAP_TICKS_PER_SECOND 1000
|
||||
|
||||
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) {
|
||||
*t = sys_now();
|
||||
}
|
||||
|
||||
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) {
|
||||
return t / COAP_TICKS_PER_SECOND;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
#include "clock.h"
|
||||
|
||||
typedef clock_time_t coap_tick_t;
|
||||
typedef clock_time_t coap_time_t;
|
||||
|
||||
/**
|
||||
* This data type is used to represent the difference between two clock_tick_t
|
||||
* values. This data type must have the same size in memory as coap_tick_t to
|
||||
* allow wrapping.
|
||||
*/
|
||||
typedef int coap_tick_diff_t;
|
||||
|
||||
#define COAP_TICKS_PER_SECOND CLOCK_SECOND
|
||||
|
||||
static inline void coap_clock_init(void) {
|
||||
clock_init();
|
||||
}
|
||||
|
||||
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) {
|
||||
return t / COAP_TICKS_PER_SECOND;
|
||||
}
|
||||
#endif /* WITH_CONTIKI */
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
/**
|
||||
* This data type represents internal timer ticks with COAP_TICKS_PER_SECOND
|
||||
* resolution.
|
||||
*/
|
||||
typedef unsigned long coap_tick_t;
|
||||
|
||||
/**
|
||||
* CoAP time in seconds since epoch.
|
||||
*/
|
||||
typedef time_t coap_time_t;
|
||||
|
||||
/**
|
||||
* This data type is used to represent the difference between two clock_tick_t
|
||||
* values. This data type must have the same size in memory as coap_tick_t to
|
||||
* allow wrapping.
|
||||
*/
|
||||
typedef long coap_tick_diff_t;
|
||||
|
||||
/** Use ms resolution on POSIX systems */
|
||||
#define COAP_TICKS_PER_SECOND 1000
|
||||
|
||||
/**
|
||||
* Initializes the internal clock.
|
||||
*/
|
||||
void coap_clock_init(void);
|
||||
|
||||
/**
|
||||
* Sets @p t to the internal time with COAP_TICKS_PER_SECOND resolution.
|
||||
*/
|
||||
void coap_ticks(coap_tick_t *t);
|
||||
|
||||
/**
|
||||
* Helper function that converts coap ticks to wallclock time. On POSIX, this
|
||||
* function returns the number of seconds since the epoch. On other systems, it
|
||||
* may be the calculated number of seconds since last reboot or so.
|
||||
*
|
||||
* @param t Internal system ticks.
|
||||
*
|
||||
* @return The number of seconds that has passed since a specific reference
|
||||
* point (seconds since epoch on POSIX).
|
||||
*/
|
||||
coap_time_t coap_ticks_to_rt(coap_tick_t t);
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return ((coap_tick_diff_t)(a - b)) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return a == b || coap_time_lt(a,b);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _COAP_TIME_H_ */
|
85
tools/sdk/include/coap/coap/debug.h
Normal file
85
tools/sdk/include/coap/coap/debug.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* debug.h -- debug utilities
|
||||
*
|
||||
* Copyright (C) 2010-2011,2014 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_DEBUG_H_
|
||||
#define _COAP_DEBUG_H_
|
||||
|
||||
#ifndef COAP_DEBUG_FD
|
||||
#define COAP_DEBUG_FD stdout
|
||||
#endif
|
||||
|
||||
#ifndef COAP_ERR_FD
|
||||
#define COAP_ERR_FD stderr
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
typedef short coap_log_t;
|
||||
#else
|
||||
/** Pre-defined log levels akin to what is used in \b syslog. */
|
||||
typedef enum {
|
||||
LOG_EMERG=0,
|
||||
LOG_ALERT,
|
||||
LOG_CRIT,
|
||||
LOG_ERR,
|
||||
LOG_WARNING,
|
||||
LOG_NOTICE,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG
|
||||
} coap_log_t;
|
||||
#endif
|
||||
|
||||
/** Returns the current log level. */
|
||||
coap_log_t coap_get_log_level(void);
|
||||
|
||||
/** Sets the log level to the specified value. */
|
||||
void coap_set_log_level(coap_log_t level);
|
||||
|
||||
/** Returns a zero-terminated string with the name of this library. */
|
||||
const char *coap_package_name(void);
|
||||
|
||||
/** Returns a zero-terminated string with the library version. */
|
||||
const char *coap_package_version(void);
|
||||
|
||||
/**
|
||||
* Writes the given text to @c COAP_ERR_FD (for @p level <= @c LOG_CRIT) or @c
|
||||
* COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The text is output only when
|
||||
* @p level is below or equal to the log level that set by coap_set_log_level().
|
||||
*/
|
||||
void coap_log_impl(coap_log_t level, const char *format, ...);
|
||||
|
||||
#ifndef coap_log
|
||||
#define coap_log(...) coap_log_impl(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/* A set of convenience macros for common log levels. */
|
||||
#define info(...) coap_log(LOG_INFO, __VA_ARGS__)
|
||||
#define warn(...) coap_log(LOG_WARNING, __VA_ARGS__)
|
||||
#define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
#include "pdu.h"
|
||||
void coap_show_pdu(const coap_pdu_t *);
|
||||
|
||||
struct coap_address_t;
|
||||
size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t);
|
||||
|
||||
#else
|
||||
|
||||
#define debug(...)
|
||||
#define info(...)
|
||||
#define warn(...)
|
||||
|
||||
#define coap_show_pdu(x)
|
||||
#define coap_print_addr(...)
|
||||
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#endif /* _COAP_DEBUG_H_ */
|
52
tools/sdk/include/coap/coap/encode.h
Normal file
52
tools/sdk/include/coap/coap/encode.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* encode.h -- encoding and decoding of CoAP data types
|
||||
*
|
||||
* Copyright (C) 2010-2012 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_ENCODE_H_
|
||||
#define _COAP_ENCODE_H_
|
||||
|
||||
#if (BSD >= 199103) || defined(WITH_CONTIKI)
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#define Nn 8 /* duplicate definition of N if built on sky motes */
|
||||
#define ENCODE_HEADER_SIZE 4
|
||||
#define HIBIT (1 << (Nn - 1))
|
||||
#define EMASK ((1 << ENCODE_HEADER_SIZE) - 1)
|
||||
#define MMASK ((1 << Nn) - 1 - EMASK)
|
||||
#define MAX_VALUE ( (1 << Nn) - (1 << ENCODE_HEADER_SIZE) ) * (1 << ((1 << ENCODE_HEADER_SIZE) - 1))
|
||||
|
||||
#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK))
|
||||
|
||||
#ifndef HAVE_FLS
|
||||
/* include this only if fls() is not available */
|
||||
extern int coap_fls(unsigned int i);
|
||||
#else
|
||||
#define coap_fls(i) fls(i)
|
||||
#endif
|
||||
|
||||
/* ls and s must be integer variables */
|
||||
#define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls)
|
||||
#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<<ENCODE_HEADER_SIZE<<ls)-1)) >> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls))
|
||||
|
||||
/**
|
||||
* Decodes multiple-length byte sequences. buf points to an input byte sequence
|
||||
* of length len. Returns the decoded value.
|
||||
*/
|
||||
unsigned int coap_decode_var_bytes(unsigned char *buf,unsigned int len);
|
||||
|
||||
/**
|
||||
* Encodes multiple-length byte sequences. buf points to an output buffer of
|
||||
* sufficient length to store the encoded bytes. val is the value to encode.
|
||||
* Returns the number of bytes used to encode val or 0 on error.
|
||||
*/
|
||||
unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val);
|
||||
|
||||
#endif /* _COAP_ENCODE_H_ */
|
57
tools/sdk/include/coap/coap/hashkey.h
Normal file
57
tools/sdk/include/coap/coap/hashkey.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* hashkey.h -- definition of hash key type and helper functions
|
||||
*
|
||||
* Copyright (C) 2010-2011 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hashkey.h
|
||||
* @brief definition of hash key type and helper functions
|
||||
*/
|
||||
|
||||
#ifndef _COAP_HASHKEY_H_
|
||||
#define _COAP_HASHKEY_H_
|
||||
|
||||
#include "str.h"
|
||||
|
||||
typedef unsigned char coap_key_t[4];
|
||||
|
||||
#ifndef coap_hash
|
||||
/**
|
||||
* Calculates a fast hash over the given string @p s of length @p len and stores
|
||||
* the result into @p h. Depending on the exact implementation, this function
|
||||
* cannot be used as one-way function to check message integrity or simlar.
|
||||
*
|
||||
* @param s The string used for hash calculation.
|
||||
* @param len The length of @p s.
|
||||
* @param h The result buffer to store the calculated hash key.
|
||||
*/
|
||||
void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h);
|
||||
|
||||
#define coap_hash(String,Length,Result) \
|
||||
coap_hash_impl((String),(Length),(Result))
|
||||
|
||||
/* This is used to control the pre-set hash-keys for resources. */
|
||||
#define __COAP_DEFAULT_HASH
|
||||
#else
|
||||
#undef __COAP_DEFAULT_HASH
|
||||
#endif /* coap_hash */
|
||||
|
||||
/**
|
||||
* Calls coap_hash() with given @c str object as parameter.
|
||||
*
|
||||
* @param Str Must contain a pointer to a coap string object.
|
||||
* @param H A coap_key_t object to store the result.
|
||||
*
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define coap_str_hash(Str,H) { \
|
||||
assert(Str); \
|
||||
memset((H), 0, sizeof(coap_key_t)); \
|
||||
coap_hash((Str)->s, (Str)->length, (H)); \
|
||||
}
|
||||
|
||||
#endif /* _COAP_HASHKEY_H_ */
|
26
tools/sdk/include/coap/coap/libcoap.h
Normal file
26
tools/sdk/include/coap/coap/libcoap.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* libcoap.h -- platform specific header file for CoAP stack
|
||||
*
|
||||
* Copyright (C) 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _LIBCOAP_H_
|
||||
#define _LIBCOAP_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
|
||||
* CONTIKI environment and do *not* include the POSIX related network stuff. If
|
||||
* there are other platforms in future there need to be analogous environments.
|
||||
*
|
||||
* The CONTIKI variable is within the Contiki build environment! */
|
||||
|
||||
#if !defined (CONTIKI)
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif /* CONTIKI */
|
||||
|
||||
#endif /* _LIBCOAP_H_ */
|
57
tools/sdk/include/coap/coap/lwippools.h
Normal file
57
tools/sdk/include/coap/coap/lwippools.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/** Memory pool definitions for the libcoap when used with lwIP (which has its
|
||||
* own mechanism for quickly allocating chunks of data with known sizes). Has
|
||||
* to be findable by lwIP (ie. an #include <lwippools.h> must either directly
|
||||
* include this or include something more generic which includes this), and
|
||||
* MEMP_USE_CUSTOM_POOLS has to be set in lwipopts.h. */
|
||||
|
||||
#include "coap_config.h"
|
||||
#include <net.h>
|
||||
#include <resource.h>
|
||||
#include <subscribe.h>
|
||||
|
||||
#ifndef MEMP_NUM_COAPCONTEXT
|
||||
#define MEMP_NUM_COAPCONTEXT 1
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPENDPOINT
|
||||
#define MEMP_NUM_COAPENDPOINT 1
|
||||
#endif
|
||||
|
||||
/* 1 is sufficient as this is very short-lived */
|
||||
#ifndef MEMP_NUM_COAPPACKET
|
||||
#define MEMP_NUM_COAPPACKET 1
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPNODE
|
||||
#define MEMP_NUM_COAPNODE 4
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPPDU
|
||||
#define MEMP_NUM_COAPPDU MEMP_NUM_COAPNODE
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAP_SUBSCRIPTION
|
||||
#define MEMP_NUM_COAP_SUBSCRIPTION 4
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPRESOURCE
|
||||
#define MEMP_NUM_COAPRESOURCE 10
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPRESOURCEATTR
|
||||
#define MEMP_NUM_COAPRESOURCEATTR 20
|
||||
#endif
|
||||
|
||||
LWIP_MEMPOOL(COAP_CONTEXT, MEMP_NUM_COAPCONTEXT, sizeof(coap_context_t), "COAP_CONTEXT")
|
||||
LWIP_MEMPOOL(COAP_ENDPOINT, MEMP_NUM_COAPENDPOINT, sizeof(coap_endpoint_t), "COAP_ENDPOINT")
|
||||
LWIP_MEMPOOL(COAP_PACKET, MEMP_NUM_COAPPACKET, sizeof(coap_packet_t), "COAP_PACKET")
|
||||
LWIP_MEMPOOL(COAP_NODE, MEMP_NUM_COAPNODE, sizeof(coap_queue_t), "COAP_NODE")
|
||||
LWIP_MEMPOOL(COAP_PDU, MEMP_NUM_COAPPDU, sizeof(coap_pdu_t), "COAP_PDU")
|
||||
LWIP_MEMPOOL(COAP_subscription, MEMP_NUM_COAP_SUBSCRIPTION, sizeof(coap_subscription_t), "COAP_subscription")
|
||||
LWIP_MEMPOOL(COAP_RESOURCE, MEMP_NUM_COAPRESOURCE, sizeof(coap_resource_t), "COAP_RESOURCE")
|
||||
LWIP_MEMPOOL(COAP_RESOURCEATTR, MEMP_NUM_COAPRESOURCEATTR, sizeof(coap_attr_t), "COAP_RESOURCEATTR")
|
111
tools/sdk/include/coap/coap/mem.h
Normal file
111
tools/sdk/include/coap/coap/mem.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* mem.h -- CoAP memory handling
|
||||
*
|
||||
* Copyright (C) 2010-2011,2014-2015 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_MEM_H_
|
||||
#define _COAP_MEM_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef WITH_LWIP
|
||||
/**
|
||||
* Initializes libcoap's memory management.
|
||||
* This function must be called once before coap_malloc() can be used on
|
||||
* constrained devices.
|
||||
*/
|
||||
void coap_memory_init(void);
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
/**
|
||||
* Type specifiers for coap_malloc_type(). Memory objects can be typed to
|
||||
* facilitate arrays of type objects to be used instead of dynamic memory
|
||||
* management on constrained devices.
|
||||
*/
|
||||
typedef enum {
|
||||
COAP_STRING,
|
||||
COAP_ATTRIBUTE_NAME,
|
||||
COAP_ATTRIBUTE_VALUE,
|
||||
COAP_PACKET,
|
||||
COAP_NODE,
|
||||
COAP_CONTEXT,
|
||||
COAP_ENDPOINT,
|
||||
COAP_PDU,
|
||||
COAP_PDU_BUF,
|
||||
COAP_RESOURCE,
|
||||
COAP_RESOURCEATTR
|
||||
} coap_memory_tag_t;
|
||||
|
||||
#ifndef WITH_LWIP
|
||||
|
||||
/**
|
||||
* Allocates a chunk of @p size bytes and returns a pointer to the newly
|
||||
* allocated memory. The @p type is used to select the appropriate storage
|
||||
* container on constrained devices. The storage allocated by coap_malloc_type()
|
||||
* must be released with coap_free_type().
|
||||
*
|
||||
* @param type The type of object to be stored.
|
||||
* @param size The number of bytes requested.
|
||||
* @return A pointer to the allocated storage or @c NULL on error.
|
||||
*/
|
||||
void *coap_malloc_type(coap_memory_tag_t type, size_t size);
|
||||
|
||||
/**
|
||||
* Releases the memory that was allocated by coap_malloc_type(). The type tag @p
|
||||
* type must be the same that was used for allocating the object pointed to by
|
||||
* @p .
|
||||
*
|
||||
* @param type The type of the object to release.
|
||||
* @param p A pointer to memory that was allocated by coap_malloc_type().
|
||||
*/
|
||||
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) {
|
||||
return coap_malloc_type(COAP_STRING, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function to coap_free_type() for backwards compatibility.
|
||||
*/
|
||||
static inline void coap_free(void *object) {
|
||||
coap_free_type(COAP_STRING, object);
|
||||
}
|
||||
|
||||
#endif /* not WITH_LWIP */
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
|
||||
#include <lwip/memp.h>
|
||||
|
||||
/* 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) {}
|
||||
|
||||
/* 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
|
||||
* sourcing the custom memp pools and becoming dependent of its syntax
|
||||
*/
|
||||
#define coap_malloc_type(type, size) memp_malloc(MEMP_ ## type)
|
||||
#define coap_free_type(type, p) memp_free(MEMP_ ## type, p)
|
||||
|
||||
/* 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) {
|
||||
LWIP_ASSERT("coap_malloc must not be used in lwIP", 0);
|
||||
}
|
||||
|
||||
static inline void coap_free(void *pointer) {
|
||||
LWIP_ASSERT("coap_free must not be used in lwIP", 0);
|
||||
}
|
||||
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
#endif /* _COAP_MEM_H_ */
|
521
tools/sdk/include/coap/coap/net.h
Normal file
521
tools/sdk/include/coap/coap/net.h
Normal file
@ -0,0 +1,521 @@
|
||||
/*
|
||||
* net.h -- CoAP network interface
|
||||
*
|
||||
* Copyright (C) 2010-2015 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_NET_H_
|
||||
#define _COAP_NET_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
#include <lwip/ip_addr.h>
|
||||
#endif
|
||||
|
||||
#include "coap_io.h"
|
||||
#include "coap_time.h"
|
||||
#include "option.h"
|
||||
#include "pdu.h"
|
||||
#include "prng.h"
|
||||
|
||||
struct coap_queue_t;
|
||||
|
||||
typedef struct coap_queue_t {
|
||||
struct coap_queue_t *next;
|
||||
coap_tick_t t; /**< when to send PDU for the next time */
|
||||
unsigned char retransmit_cnt; /**< retransmission counter, will be removed
|
||||
* when zero */
|
||||
unsigned int timeout; /**< the randomized timeout value */
|
||||
coap_endpoint_t local_if; /**< the local address interface */
|
||||
coap_address_t remote; /**< remote address */
|
||||
coap_tid_t id; /**< unique transaction id */
|
||||
coap_pdu_t *pdu; /**< the CoAP PDU to send */
|
||||
} coap_queue_t;
|
||||
|
||||
/** Adds node to given queue, ordered by node->t. */
|
||||
int coap_insert_node(coap_queue_t **queue, coap_queue_t *node);
|
||||
|
||||
/** Destroys specified node. */
|
||||
int coap_delete_node(coap_queue_t *node);
|
||||
|
||||
/** Removes all items from given queue and frees the allocated storage. */
|
||||
void coap_delete_all(coap_queue_t *queue);
|
||||
|
||||
/** Creates a new node suitable for adding to the CoAP sendqueue. */
|
||||
coap_queue_t *coap_new_node(void);
|
||||
|
||||
struct coap_resource_t;
|
||||
struct coap_context_t;
|
||||
#ifndef WITHOUT_ASYNC
|
||||
struct coap_async_state_t;
|
||||
#endif
|
||||
|
||||
/** Message handler that is used as call-back in coap_context_t */
|
||||
typedef void (*coap_response_handler_t)(struct coap_context_t *,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *remote,
|
||||
coap_pdu_t *sent,
|
||||
coap_pdu_t *received,
|
||||
const coap_tid_t id);
|
||||
|
||||
#define COAP_MID_CACHE_SIZE 3
|
||||
typedef struct {
|
||||
unsigned char flags[COAP_MID_CACHE_SIZE];
|
||||
coap_key_t item[COAP_MID_CACHE_SIZE];
|
||||
} coap_mid_cache_t;
|
||||
|
||||
/** The CoAP stack's global state is stored in a coap_context_t object */
|
||||
typedef struct coap_context_t {
|
||||
coap_opt_filter_t known_options;
|
||||
struct coap_resource_t *resources; /**< hash table or list of known resources */
|
||||
|
||||
#ifndef WITHOUT_ASYNC
|
||||
/**
|
||||
* list of asynchronous transactions */
|
||||
struct coap_async_state_t *async_state;
|
||||
#endif /* WITHOUT_ASYNC */
|
||||
|
||||
/**
|
||||
* The time stamp in the first element of the sendqeue is relative
|
||||
* to sendqueue_basetime. */
|
||||
coap_tick_t sendqueue_basetime;
|
||||
coap_queue_t *sendqueue;
|
||||
coap_endpoint_t *endpoint; /**< the endpoint used for listening */
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
int sockfd; /**< send/receive socket */
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
struct uip_udp_conn *conn; /**< uIP connection object */
|
||||
struct etimer retransmit_timer; /**< fires when the next packet must be sent */
|
||||
struct etimer notify_timer; /**< used to check resources periodically */
|
||||
#endif /* WITH_CONTIKI */
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
uint8_t timer_configured; /**< Set to 1 when a retransmission is
|
||||
* scheduled using lwIP timers for this
|
||||
* context, otherwise 0. */
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
/**
|
||||
* The last message id that was used is stored in this field. The initial
|
||||
* value is set by coap_new_context() and is usually a random value. A new
|
||||
* message id can be created with coap_new_message_id().
|
||||
*/
|
||||
unsigned short message_id;
|
||||
|
||||
/**
|
||||
* The next value to be used for Observe. This field is global for all
|
||||
* resources and will be updated when notifications are created.
|
||||
*/
|
||||
unsigned int observe;
|
||||
|
||||
coap_response_handler_t response_handler;
|
||||
|
||||
ssize_t (*network_send)(struct coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
unsigned char *data, size_t datalen);
|
||||
|
||||
ssize_t (*network_read)(coap_endpoint_t *ep, coap_packet_t **packet);
|
||||
|
||||
} coap_context_t;
|
||||
|
||||
/**
|
||||
* Registers a new message handler that is called whenever a response was
|
||||
* received that matches an ongoing transaction.
|
||||
*
|
||||
* @param context The context to register the handler for.
|
||||
* @param handler The response handler to register.
|
||||
*/
|
||||
static inline void
|
||||
coap_register_response_handler(coap_context_t *context,
|
||||
coap_response_handler_t handler) {
|
||||
context->response_handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the option type @p type with the given context object @p ctx.
|
||||
*
|
||||
* @param ctx The context to use.
|
||||
* @param type The option type to register.
|
||||
*/
|
||||
inline static void
|
||||
coap_register_option(coap_context_t *ctx, unsigned char type) {
|
||||
coap_option_setb(ctx->known_options, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sendqueue_basetime in the given context object @p ctx to @p now. This
|
||||
* function returns the number of elements in the queue head that have timed
|
||||
* out.
|
||||
*/
|
||||
unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now);
|
||||
|
||||
/**
|
||||
* Returns the next pdu to send without removing from sendqeue.
|
||||
*/
|
||||
coap_queue_t *coap_peek_next( coap_context_t *context );
|
||||
|
||||
/**
|
||||
* Returns the next pdu to send and removes it from the sendqeue.
|
||||
*/
|
||||
coap_queue_t *coap_pop_next( coap_context_t *context );
|
||||
|
||||
/**
|
||||
* Creates a new coap_context_t object that will hold the CoAP stack status.
|
||||
*/
|
||||
coap_context_t *coap_new_context(const coap_address_t *listen_addr);
|
||||
|
||||
/**
|
||||
* Returns a new message id and updates @p context->message_id accordingly. The
|
||||
* message id is returned in network byte order to make it easier to read in
|
||||
* tracing tools.
|
||||
*
|
||||
* @param context The current coap_context_t object.
|
||||
*
|
||||
* @return Incremented message id in network byte order.
|
||||
*/
|
||||
static inline unsigned short
|
||||
coap_new_message_id(coap_context_t *context) {
|
||||
context->message_id++;
|
||||
#ifndef WITH_CONTIKI
|
||||
return htons(context->message_id);
|
||||
#else /* WITH_CONTIKI */
|
||||
return uip_htons(context->message_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* CoAP stack context must be released with coap_free_context(). This function
|
||||
* clears all entries from the receive queue and send queue and deletes the
|
||||
* resources that have been registered with @p context, and frees the attached
|
||||
* endpoints.
|
||||
*/
|
||||
void coap_free_context(coap_context_t *context);
|
||||
|
||||
|
||||
/**
|
||||
* Sends a confirmed CoAP message to given destination. The memory that is
|
||||
* allocated by pdu will not be released by coap_send_confirmed(). The caller
|
||||
* must release the memory.
|
||||
*
|
||||
* @param context The CoAP context to use.
|
||||
* @param local_interface The local network interface where the outbound
|
||||
* packet is sent.
|
||||
* @param dst The address to send to.
|
||||
* @param pdu The CoAP PDU to send.
|
||||
*
|
||||
* @return The message id of the sent message or @c
|
||||
* COAP_INVALID_TID on error.
|
||||
*/
|
||||
coap_tid_t coap_send_confirmed(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
coap_pdu_t *pdu);
|
||||
|
||||
/**
|
||||
* Creates a new ACK PDU with specified error @p code. The options specified by
|
||||
* the filter expression @p opts will be copied from the original request
|
||||
* contained in @p request. Unless @c SHORT_ERROR_RESPONSE was defined at build
|
||||
* time, the textual reason phrase for @p code will be added as payload, with
|
||||
* Content-Type @c 0.
|
||||
* This function returns a pointer to the new response message, or @c NULL on
|
||||
* error. The storage allocated for the new message must be relased with
|
||||
* coap_free().
|
||||
*
|
||||
* @param request Specification of the received (confirmable) request.
|
||||
* @param code The error code to set.
|
||||
* @param opts An option filter that specifies which options to copy from
|
||||
* the original request in @p node.
|
||||
*
|
||||
* @return A pointer to the new message or @c NULL on error.
|
||||
*/
|
||||
coap_pdu_t *coap_new_error_response(coap_pdu_t *request,
|
||||
unsigned char code,
|
||||
coap_opt_filter_t opts);
|
||||
|
||||
/**
|
||||
* Sends a non-confirmed CoAP message to given destination. The memory that is
|
||||
* allocated by pdu will not be released by coap_send().
|
||||
* The caller must release the memory.
|
||||
*
|
||||
* @param context The CoAP context to use.
|
||||
* @param local_interface The local network interface where the outbound packet
|
||||
* is sent.
|
||||
* @param dst The address to send to.
|
||||
* @param pdu The CoAP PDU to send.
|
||||
*
|
||||
* @return The message id of the sent message or @c
|
||||
* COAP_INVALID_TID on error.
|
||||
*/
|
||||
coap_tid_t coap_send(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
coap_pdu_t *pdu);
|
||||
|
||||
/**
|
||||
* Sends an error response with code @p code for request @p request to @p dst.
|
||||
* @p opts will be passed to coap_new_error_response() to copy marked options
|
||||
* from the request. This function returns the transaction id if the message was
|
||||
* sent, or @c COAP_INVALID_TID otherwise.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param request The original request to respond to.
|
||||
* @param local_interface The local network interface where the outbound packet
|
||||
* is sent.
|
||||
* @param dst The remote peer that sent the request.
|
||||
* @param code The response code.
|
||||
* @param opts A filter that specifies the options to copy from the
|
||||
* @p request.
|
||||
*
|
||||
* @return The transaction id if the message was sent, or @c
|
||||
* COAP_INVALID_TID otherwise.
|
||||
*/
|
||||
coap_tid_t coap_send_error(coap_context_t *context,
|
||||
coap_pdu_t *request,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
unsigned char code,
|
||||
coap_opt_filter_t opts);
|
||||
|
||||
/**
|
||||
* Helper funktion to create and send a message with @p type (usually ACK or
|
||||
* RST). This function returns @c COAP_INVALID_TID when the message was not
|
||||
* sent, a valid transaction id otherwise.
|
||||
*
|
||||
* @param context The CoAP context.
|
||||
* @param local_interface The local network interface where the outbound packet
|
||||
* is sent.
|
||||
* @param dst Where to send the context.
|
||||
* @param request The request that should be responded to.
|
||||
* @param type Which type to set.
|
||||
* @return transaction id on success or @c COAP_INVALID_TID
|
||||
* otherwise.
|
||||
*/
|
||||
coap_tid_t
|
||||
coap_send_message_type(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
coap_pdu_t *request,
|
||||
unsigned char type);
|
||||
|
||||
/**
|
||||
* Sends an ACK message with code @c 0 for the specified @p request to @p dst.
|
||||
* This function returns the corresponding transaction id if the message was
|
||||
* sent or @c COAP_INVALID_TID on error.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param local_interface The local network interface where the outbound packet
|
||||
* is sent.
|
||||
* @param dst The destination address.
|
||||
* @param request The request to be acknowledged.
|
||||
*
|
||||
* @return The transaction id if ACK was sent or @c
|
||||
* COAP_INVALID_TID on error.
|
||||
*/
|
||||
coap_tid_t coap_send_ack(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
coap_pdu_t *request);
|
||||
|
||||
/**
|
||||
* Sends an RST message with code @c 0 for the specified @p request to @p dst.
|
||||
* This function returns the corresponding transaction id if the message was
|
||||
* sent or @c COAP_INVALID_TID on error.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param local_interface The local network interface where the outbound packet
|
||||
* is sent.
|
||||
* @param dst The destination address.
|
||||
* @param request The request to be reset.
|
||||
*
|
||||
* @return The transaction id if RST was sent or @c
|
||||
* COAP_INVALID_TID on error.
|
||||
*/
|
||||
static inline coap_tid_t
|
||||
coap_send_rst(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *dst,
|
||||
coap_pdu_t *request) {
|
||||
return coap_send_message_type(context,
|
||||
local_interface,
|
||||
dst, request,
|
||||
COAP_MESSAGE_RST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles retransmissions of confirmable messages
|
||||
*/
|
||||
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node);
|
||||
|
||||
/**
|
||||
* Reads data from the network and tries to parse as CoAP PDU. On success, 0 is
|
||||
* returned and a new node with the parsed PDU is added to the receive queue in
|
||||
* the specified context object.
|
||||
*/
|
||||
int coap_read(coap_context_t *context);
|
||||
|
||||
/**
|
||||
* Parses and interprets a CoAP message with context @p ctx. This function
|
||||
* returns @c 0 if the message was handled, or a value less than zero on
|
||||
* error.
|
||||
*
|
||||
* @param ctx The current CoAP context.
|
||||
* @param packet The received packet.
|
||||
*
|
||||
* @return @c 0 if message was handled successfully, or less than zero on
|
||||
* error.
|
||||
*/
|
||||
int coap_handle_message(coap_context_t *ctx,
|
||||
coap_packet_t *packet);
|
||||
|
||||
/**
|
||||
* Calculates a unique transaction id from given arguments @p peer and @p pdu.
|
||||
* The id is returned in @p id.
|
||||
*
|
||||
* @param peer The remote party who sent @p pdu.
|
||||
* @param pdu The message that initiated the transaction.
|
||||
* @param id Set to the new id.
|
||||
*/
|
||||
void coap_transaction_id(const coap_address_t *peer,
|
||||
const coap_pdu_t *pdu,
|
||||
coap_tid_t *id);
|
||||
|
||||
/**
|
||||
* This function removes the element with given @p id from the list given list.
|
||||
* If @p id was found, @p node is updated to point to the removed element. Note
|
||||
* that the storage allocated by @p node is @b not released. The caller must do
|
||||
* this manually using coap_delete_node(). This function returns @c 1 if the
|
||||
* element with id @p id was found, @c 0 otherwise. For a return value of @c 0,
|
||||
* the contents of @p node is undefined.
|
||||
*
|
||||
* @param queue The queue to search for @p id.
|
||||
* @param id The node id to look for.
|
||||
* @param node If found, @p node is updated to point to the removed node. You
|
||||
* must release the storage pointed to by @p node manually.
|
||||
*
|
||||
* @return @c 1 if @p id was found, @c 0 otherwise.
|
||||
*/
|
||||
int coap_remove_from_queue(coap_queue_t **queue,
|
||||
coap_tid_t id,
|
||||
coap_queue_t **node);
|
||||
|
||||
/**
|
||||
* Removes the transaction identified by @p id from given @p queue. This is a
|
||||
* convenience function for coap_remove_from_queue() with automatic deletion of
|
||||
* the removed node.
|
||||
*
|
||||
* @param queue The queue to search for @p id.
|
||||
* @param id The transaction id.
|
||||
*
|
||||
* @return @c 1 if node was found, removed and destroyed, @c 0 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) {
|
||||
coap_queue_t *node;
|
||||
if (!coap_remove_from_queue(queue, id, &node))
|
||||
return 0;
|
||||
|
||||
coap_delete_node(node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves transaction from the queue.
|
||||
*
|
||||
* @param queue The transaction queue to be searched.
|
||||
* @param id Unique key of the transaction to find.
|
||||
*
|
||||
* @return A pointer to the transaction object or NULL if not found.
|
||||
*/
|
||||
coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id);
|
||||
|
||||
/**
|
||||
* Cancels all outstanding messages for peer @p dst that have the specified
|
||||
* token.
|
||||
*
|
||||
* @param context The context in use.
|
||||
* @param dst Destination address of the messages to remove.
|
||||
* @param token Message token.
|
||||
* @param token_length Actual length of @p token.
|
||||
*/
|
||||
void coap_cancel_all_messages(coap_context_t *context,
|
||||
const coap_address_t *dst,
|
||||
const unsigned char *token,
|
||||
size_t token_length);
|
||||
|
||||
/**
|
||||
* Dispatches the PDUs from the receive queue in given context.
|
||||
*/
|
||||
void coap_dispatch(coap_context_t *context, coap_queue_t *rcvd);
|
||||
|
||||
/**
|
||||
* Returns 1 if there are no messages to send or to dispatch in the context's
|
||||
* queues. */
|
||||
int coap_can_exit(coap_context_t *context);
|
||||
|
||||
/**
|
||||
* Returns the current value of an internal tick counter. The counter counts \c
|
||||
* COAP_TICKS_PER_SECOND ticks every second.
|
||||
*/
|
||||
void coap_ticks(coap_tick_t *);
|
||||
|
||||
/**
|
||||
* Verifies that @p pdu contains no unknown critical options. Options must be
|
||||
* registered at @p ctx, using the function coap_register_option(). A basic set
|
||||
* of options is registered automatically by coap_new_context(). This function
|
||||
* returns @c 1 if @p pdu is ok, @c 0 otherwise. The given filter object @p
|
||||
* unknown will be updated with the unknown options. As only @c COAP_MAX_OPT
|
||||
* options can be signalled this way, remaining options must be examined
|
||||
* manually.
|
||||
*
|
||||
* @code
|
||||
coap_opt_filter_t f = COAP_OPT_NONE;
|
||||
coap_opt_iterator_t opt_iter;
|
||||
|
||||
if (coap_option_check_critical(ctx, pdu, f) == 0) {
|
||||
coap_option_iterator_init(pdu, &opt_iter, f);
|
||||
|
||||
while (coap_option_next(&opt_iter)) {
|
||||
if (opt_iter.type & 0x01) {
|
||||
... handle unknown critical option in opt_iter ...
|
||||
}
|
||||
}
|
||||
}
|
||||
* @endcode
|
||||
*
|
||||
* @param ctx The context where all known options are registered.
|
||||
* @param pdu The PDU to check.
|
||||
* @param unknown The output filter that will be updated to indicate the
|
||||
* unknown critical options found in @p pdu.
|
||||
*
|
||||
* @return @c 1 if everything was ok, @c 0 otherwise.
|
||||
*/
|
||||
int coap_option_check_critical(coap_context_t *ctx,
|
||||
coap_pdu_t *pdu,
|
||||
coap_opt_filter_t unknown);
|
||||
|
||||
/**
|
||||
* Creates a new response for given @p request with the contents of @c
|
||||
* .well-known/core. The result is NULL on error or a newly allocated PDU that
|
||||
* must be released by coap_delete_pdu().
|
||||
*
|
||||
* @param context The current coap context to use.
|
||||
* @param request The request for @c .well-known/core .
|
||||
*
|
||||
* @return A new 2.05 response for @c .well-known/core or NULL on error.
|
||||
*/
|
||||
coap_pdu_t *coap_wellknown_response(coap_context_t *context,
|
||||
coap_pdu_t *request);
|
||||
|
||||
#endif /* _COAP_NET_H_ */
|
410
tools/sdk/include/coap/coap/option.h
Normal file
410
tools/sdk/include/coap/coap/option.h
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* option.h -- helpers for handling options in CoAP PDUs
|
||||
*
|
||||
* Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file option.h
|
||||
* @brief Helpers for handling options in CoAP PDUs
|
||||
*/
|
||||
|
||||
#ifndef _COAP_OPTION_H_
|
||||
#define _COAP_OPTION_H_
|
||||
|
||||
#include "bits.h"
|
||||
#include "pdu.h"
|
||||
|
||||
/**
|
||||
* Use byte-oriented access methods here because sliding a complex struct
|
||||
* coap_opt_t over the data buffer may cause bus error on certain platforms.
|
||||
*/
|
||||
typedef unsigned char coap_opt_t;
|
||||
#define PCHAR(p) ((coap_opt_t *)(p))
|
||||
|
||||
/** Representation of CoAP options. */
|
||||
typedef struct {
|
||||
unsigned short delta;
|
||||
size_t length;
|
||||
unsigned char *value;
|
||||
} coap_option_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
|
||||
* signaled when illegal delta or length values are encountered or when option
|
||||
* parsing would result in reading past the option (i.e. beyond opt + length).
|
||||
*
|
||||
* @param opt The beginning of the option to parse.
|
||||
* @param length The maximum length of @p opt.
|
||||
* @param result A pointer to the coap_option_t structure that is filled with
|
||||
* actual values iff coap_opt_parse() > 0.
|
||||
* @return The number of bytes parsed or @c 0 on error.
|
||||
*/
|
||||
size_t coap_opt_parse(const coap_opt_t *opt,
|
||||
size_t length,
|
||||
coap_option_t *result);
|
||||
|
||||
/**
|
||||
* Returns the size of the given option, taking into account a possible option
|
||||
* jump.
|
||||
*
|
||||
* @param opt An option jump or the beginning of the option.
|
||||
* @return The number of bytes between @p opt and the end of the option
|
||||
* starting at @p opt. In case of an error, this function returns
|
||||
* @c 0 as options need at least one byte storage space.
|
||||
*/
|
||||
size_t coap_opt_size(const coap_opt_t *opt);
|
||||
|
||||
/** @deprecated { Use coap_opt_size() instead. } */
|
||||
#define COAP_OPT_SIZE(opt) coap_opt_size(opt)
|
||||
|
||||
/**
|
||||
* Calculates the beginning of the PDU's option section.
|
||||
*
|
||||
* @param pdu The PDU containing the options.
|
||||
* @return A pointer to the first option if available, or @c NULL otherwise.
|
||||
*/
|
||||
coap_opt_t *options_start(coap_pdu_t *pdu);
|
||||
|
||||
/**
|
||||
* Interprets @p opt as pointer to a CoAP option and advances to
|
||||
* the next byte past this option.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define options_next(opt) \
|
||||
((coap_opt_t *)((unsigned char *)(opt) + COAP_OPT_SIZE(opt)))
|
||||
|
||||
/**
|
||||
* @defgroup opt_filter Option Filters
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The number of option types below 256 that can be stored in an
|
||||
* option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
|
||||
* at most 16. Each coap_option_filter_t object reserves
|
||||
* ((COAP_OPT_FILTER_SHORT + 1) / 2) * 2 bytes for short options.
|
||||
*/
|
||||
#define COAP_OPT_FILTER_SHORT 6
|
||||
|
||||
/**
|
||||
* The number of option types above 255 that can be stored in an
|
||||
* option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
|
||||
* at most 16. Each coap_option_filter_t object reserves
|
||||
* COAP_OPT_FILTER_LONG * 2 bytes for short options.
|
||||
*/
|
||||
#define COAP_OPT_FILTER_LONG 2
|
||||
|
||||
/* Ensure that COAP_OPT_FILTER_SHORT and COAP_OPT_FILTER_LONG are set
|
||||
* correctly. */
|
||||
#if (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16)
|
||||
#error COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be less or equal 16
|
||||
#endif /* (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) */
|
||||
|
||||
/** The number of elements in coap_opt_filter_t. */
|
||||
#define COAP_OPT_FILTER_SIZE \
|
||||
(((COAP_OPT_FILTER_SHORT + 1) >> 1) + COAP_OPT_FILTER_LONG) +1
|
||||
|
||||
/**
|
||||
* Fixed-size vector we use for option filtering. It is large enough
|
||||
* to hold COAP_OPT_FILTER_SHORT entries with an option number between
|
||||
* 0 and 255, and COAP_OPT_FILTER_LONG entries with an option number
|
||||
* between 256 and 65535. Its internal structure is
|
||||
*
|
||||
* @code
|
||||
struct {
|
||||
uint16_t mask;
|
||||
uint16_t long_opts[COAP_OPT_FILTER_LONG];
|
||||
uint8_t short_opts[COAP_OPT_FILTER_SHORT];
|
||||
}
|
||||
* @endcode
|
||||
*
|
||||
* The first element contains a bit vector that indicates which fields
|
||||
* in the remaining array are used. The first COAP_OPT_FILTER_LONG
|
||||
* bits correspond to the long option types that are stored in the
|
||||
* elements from index 1 to COAP_OPT_FILTER_LONG. The next
|
||||
* COAP_OPT_FILTER_SHORT bits correspond to the short option types
|
||||
* that are stored in the elements from index COAP_OPT_FILTER_LONG + 1
|
||||
* to COAP_OPT_FILTER_LONG + COAP_OPT_FILTER_SHORT. The latter
|
||||
* elements are treated as bytes.
|
||||
*/
|
||||
typedef uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE];
|
||||
|
||||
/** Pre-defined filter that includes all options. */
|
||||
#define COAP_OPT_ALL NULL
|
||||
|
||||
/**
|
||||
* Clears filter @p f.
|
||||
*
|
||||
* @param f The filter to clear.
|
||||
*/
|
||||
static inline void
|
||||
coap_option_filter_clear(coap_opt_filter_t f) {
|
||||
memset(f, 0, sizeof(coap_opt_filter_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the corresponding entry for @p type in @p filter. This
|
||||
* function returns @c 1 if bit was set or @c 0 on error (i.e. when
|
||||
* the given type does not fit in the filter).
|
||||
*
|
||||
* @param filter The filter object to change.
|
||||
* @param type The type for which the bit should be set.
|
||||
*
|
||||
* @return @c 1 if bit was set, @c 0 otherwise.
|
||||
*/
|
||||
int coap_option_filter_set(coap_opt_filter_t filter, unsigned short type);
|
||||
|
||||
/**
|
||||
* Clears the corresponding entry for @p type in @p filter. This
|
||||
* function returns @c 1 if bit was set or @c 0 on error (i.e. when
|
||||
* the given type does not fit in the filter).
|
||||
*
|
||||
* @param filter The filter object to change.
|
||||
* @param type The type that should be cleared from the filter.
|
||||
*
|
||||
* @return @c 1 if bit was set, @c 0 otherwise.
|
||||
*/
|
||||
int coap_option_filter_unset(coap_opt_filter_t filter, unsigned short type);
|
||||
|
||||
/**
|
||||
* Checks if @p type is contained in @p filter. This function returns
|
||||
* @c 1 if found, @c 0 if not, or @c -1 on error (i.e. when the given
|
||||
* type does not fit in the filter).
|
||||
*
|
||||
* @param filter The filter object to search.
|
||||
* @param type The type to search for.
|
||||
*
|
||||
* @return @c 1 if @p type was found, @c 0 otherwise, or @c -1 on error.
|
||||
*/
|
||||
int coap_option_filter_get(const coap_opt_filter_t filter, unsigned short type);
|
||||
|
||||
/**
|
||||
* Sets the corresponding bit for @p type in @p filter. This function returns @c
|
||||
* 1 if bit was set or @c -1 on error (i.e. when the given type does not fit in
|
||||
* the filter).
|
||||
*
|
||||
* @deprecated Use coap_option_filter_set() instead.
|
||||
*
|
||||
* @param filter The filter object to change.
|
||||
* @param type The type for which the bit should be set.
|
||||
*
|
||||
* @return @c 1 if bit was set, @c -1 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
coap_option_setb(coap_opt_filter_t filter, unsigned short type) {
|
||||
return coap_option_filter_set(filter, type) ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the corresponding bit for @p type in @p filter. This function returns
|
||||
* @c 1 if bit was cleared or @c -1 on error (i.e. when the given type does not
|
||||
* fit in the filter).
|
||||
*
|
||||
* @deprecated Use coap_option_filter_unset() instead.
|
||||
*
|
||||
* @param filter The filter object to change.
|
||||
* @param type The type for which the bit should be cleared.
|
||||
*
|
||||
* @return @c 1 if bit was set, @c -1 otherwise.
|
||||
*/
|
||||
inline static int
|
||||
coap_option_clrb(coap_opt_filter_t filter, unsigned short type) {
|
||||
return coap_option_filter_unset(filter, type) ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the corresponding bit for @p type in @p filter. This function returns @c
|
||||
* 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. when the given type
|
||||
* does not fit in the filter).
|
||||
*
|
||||
* @deprecated Use coap_option_filter_get() instead.
|
||||
*
|
||||
* @param filter The filter object to read bit from.
|
||||
* @param type The type for which the bit should be read.
|
||||
*
|
||||
* @return @c 1 if bit was set, @c 0 if not, @c -1 on error.
|
||||
*/
|
||||
inline static int
|
||||
coap_option_getb(const coap_opt_filter_t filter, unsigned short type) {
|
||||
return coap_option_filter_get(filter, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator to run through PDU options. This object must be
|
||||
* initialized with coap_option_iterator_init(). Call
|
||||
* coap_option_next() to walk through the list of options until
|
||||
* coap_option_next() returns @c NULL.
|
||||
*
|
||||
* @code
|
||||
* coap_opt_t *option;
|
||||
* coap_opt_iterator_t opt_iter;
|
||||
* coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
|
||||
*
|
||||
* while ((option = coap_option_next(&opt_iter))) {
|
||||
* ... do something with option ...
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
typedef struct {
|
||||
size_t length; /**< remaining length of PDU */
|
||||
unsigned short type; /**< decoded option type */
|
||||
unsigned int bad:1; /**< iterator object is ok if not set */
|
||||
unsigned int filtered:1; /**< denotes whether or not filter is used */
|
||||
coap_opt_t *next_option; /**< pointer to the unparsed next option */
|
||||
coap_opt_filter_t filter; /**< option filter */
|
||||
} coap_opt_iterator_t;
|
||||
|
||||
/**
|
||||
* Initializes the given option iterator @p oi to point to the beginning of the
|
||||
* @p pdu's option list. This function returns @p oi on success, @c NULL
|
||||
* otherwise (i.e. when no options exist). Note that a length check on the
|
||||
* option list must be performed before coap_option_iterator_init() is called.
|
||||
*
|
||||
* @param pdu The PDU the options of which should be walked through.
|
||||
* @param oi An iterator object that will be initilized.
|
||||
* @param filter An optional option type filter.
|
||||
* With @p type != @c COAP_OPT_ALL, coap_option_next()
|
||||
* will return only options matching this bitmask.
|
||||
* Fence-post options @c 14, @c 28, @c 42, ... are always
|
||||
* skipped.
|
||||
*
|
||||
* @return The iterator object @p oi on success, @c NULL otherwise.
|
||||
*/
|
||||
coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu,
|
||||
coap_opt_iterator_t *oi,
|
||||
const coap_opt_filter_t filter);
|
||||
|
||||
/**
|
||||
* Updates the iterator @p oi to point to the next option. This function returns
|
||||
* a pointer to that option or @c NULL if no more options exist. The contents of
|
||||
* @p oi will be updated. In particular, @c oi->n specifies the current option's
|
||||
* ordinal number (counted from @c 1), @c oi->type is the option's type code,
|
||||
* and @c oi->option points to the beginning of the current option itself. When
|
||||
* advanced past the last option, @c oi->option will be @c NULL.
|
||||
*
|
||||
* Note that options are skipped whose corresponding bits in the filter
|
||||
* specified with coap_option_iterator_init() are @c 0. Options with type codes
|
||||
* that do not fit in this filter hence will always be returned.
|
||||
*
|
||||
* @param oi The option iterator to update.
|
||||
*
|
||||
* @return The next option or @c NULL if no more options exist.
|
||||
*/
|
||||
coap_opt_t *coap_option_next(coap_opt_iterator_t *oi);
|
||||
|
||||
/**
|
||||
* Retrieves the first option of type @p type from @p pdu. @p oi must point to a
|
||||
* coap_opt_iterator_t object that will be initialized by this function to
|
||||
* filter only options with code @p type. This function returns the first option
|
||||
* with this type, or @c NULL if not found.
|
||||
*
|
||||
* @param pdu The PDU to parse for options.
|
||||
* @param type The option type code to search for.
|
||||
* @param oi An iterator object to use.
|
||||
*
|
||||
* @return A pointer to the first option of type @p type, or @c NULL if
|
||||
* not found.
|
||||
*/
|
||||
coap_opt_t *coap_check_option(coap_pdu_t *pdu,
|
||||
unsigned short type,
|
||||
coap_opt_iterator_t *oi);
|
||||
|
||||
/**
|
||||
* Encodes the given delta and length values into @p opt. This function returns
|
||||
* the number of bytes that were required to encode @p delta and @p length or @c
|
||||
* 0 on error. Note that the result indicates by how many bytes @p opt must be
|
||||
* advanced to encode the option value.
|
||||
*
|
||||
* @param opt The option buffer space where @p delta and @p length are
|
||||
* written.
|
||||
* @param maxlen The maximum length of @p opt.
|
||||
* @param delta The actual delta value to encode.
|
||||
* @param length The actual length value to encode.
|
||||
*
|
||||
* @return The number of bytes used or @c 0 on error.
|
||||
*/
|
||||
size_t coap_opt_setheader(coap_opt_t *opt,
|
||||
size_t maxlen,
|
||||
unsigned short delta,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* Encodes option with given @p delta into @p opt. This function returns the
|
||||
* number of bytes written to @p opt or @c 0 on error. This happens especially
|
||||
* when @p opt does not provide sufficient space to store the option value,
|
||||
* delta, and option jumps when required.
|
||||
*
|
||||
* @param opt The option buffer space where @p val is written.
|
||||
* @param n Maximum length of @p opt.
|
||||
* @param delta The option delta.
|
||||
* @param val The option value to copy into @p opt.
|
||||
* @param length The actual length of @p val.
|
||||
*
|
||||
* @return The number of bytes that have been written to @p opt or @c 0 on
|
||||
* error. The return value will always be less than @p n.
|
||||
*/
|
||||
size_t coap_opt_encode(coap_opt_t *opt,
|
||||
size_t n,
|
||||
unsigned short delta,
|
||||
const unsigned char *val,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* Decodes the delta value of the next option. This function returns the number
|
||||
* of bytes read or @c 0 on error. The caller of this function must ensure that
|
||||
* it does not read over the boundaries of @p opt (e.g. by calling
|
||||
* coap_opt_check_delta().
|
||||
*
|
||||
* @param opt The option to examine.
|
||||
*
|
||||
* @return The number of bytes read or @c 0 on error.
|
||||
*/
|
||||
unsigned short coap_opt_delta(const coap_opt_t *opt);
|
||||
|
||||
/** @deprecated { Use coap_opt_delta() instead. } */
|
||||
#define COAP_OPT_DELTA(opt) coap_opt_delta(opt)
|
||||
|
||||
/** @deprecated { Use coap_opt_encode() instead. } */
|
||||
#define COAP_OPT_SETDELTA(opt,val) \
|
||||
coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0)
|
||||
|
||||
/**
|
||||
* Returns the length of the given option. @p opt must point to an option jump
|
||||
* or the beginning of the option. This function returns @c 0 when @p opt is not
|
||||
* an option or the actual length of @p opt (which can be @c 0 as well).
|
||||
*
|
||||
* @note {The rationale for using @c 0 in case of an error is that in most
|
||||
* contexts, the result of this function is used to skip the next
|
||||
* coap_opt_length() bytes.}
|
||||
*
|
||||
* @param opt The option whose length should be returned.
|
||||
*
|
||||
* @return The option's length or @c 0 when undefined.
|
||||
*/
|
||||
unsigned short coap_opt_length(const coap_opt_t *opt);
|
||||
|
||||
/** @deprecated { Use coap_opt_length() instead. } */
|
||||
#define COAP_OPT_LENGTH(opt) coap_opt_length(opt)
|
||||
|
||||
/**
|
||||
* Returns a pointer to the value of the given option. @p opt must point to an
|
||||
* option jump or the beginning of the option. This function returns @c NULL if
|
||||
* @p opt is not a valid option.
|
||||
*
|
||||
* @param opt The option whose value should be returned.
|
||||
*
|
||||
* @return A pointer to the option value or @c NULL on error.
|
||||
*/
|
||||
unsigned char *coap_opt_value(coap_opt_t *opt);
|
||||
|
||||
/** @deprecated { Use coap_opt_value() instead. } */
|
||||
#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt)
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _OPTION_H_ */
|
388
tools/sdk/include/coap/coap/pdu.h
Normal file
388
tools/sdk/include/coap/coap/pdu.h
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* pdu.h -- CoAP message structure
|
||||
*
|
||||
* Copyright (C) 2010-2014 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pdu.h
|
||||
* @brief Pre-defined constants that reflect defaults for CoAP
|
||||
*/
|
||||
|
||||
#ifndef _COAP_PDU_H_
|
||||
#define _COAP_PDU_H_
|
||||
|
||||
#include "uri.h"
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
#include <lwip/pbuf.h>
|
||||
#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
|
||||
#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU */
|
||||
#endif /* COAP_MAX_PDU_SIZE */
|
||||
|
||||
#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */
|
||||
#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
|
||||
|
||||
/** well-known resources URI */
|
||||
#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core"
|
||||
|
||||
#ifdef __COAP_DEFAULT_HASH
|
||||
/* pre-calculated hash key for the default well-known URI */
|
||||
#define COAP_DEFAULT_WKC_HASHKEY "\345\130\144\245"
|
||||
#endif
|
||||
|
||||
/* CoAP message types */
|
||||
|
||||
#define COAP_MESSAGE_CON 0 /* confirmable message (requires ACK/RST) */
|
||||
#define COAP_MESSAGE_NON 1 /* non-confirmable message (one-shot message) */
|
||||
#define COAP_MESSAGE_ACK 2 /* used to acknowledge confirmable messages */
|
||||
#define COAP_MESSAGE_RST 3 /* indicates error in received messages */
|
||||
|
||||
/* CoAP request methods */
|
||||
|
||||
#define COAP_REQUEST_GET 1
|
||||
#define COAP_REQUEST_POST 2
|
||||
#define COAP_REQUEST_PUT 3
|
||||
#define COAP_REQUEST_DELETE 4
|
||||
|
||||
/* CoAP option types (be sure to update check_critical when adding options */
|
||||
|
||||
#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_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) */
|
||||
#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT
|
||||
#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */
|
||||
#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */
|
||||
#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */
|
||||
#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
|
||||
#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */
|
||||
#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 RFC 7641 */
|
||||
|
||||
#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 RFC 7959 */
|
||||
|
||||
#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */
|
||||
#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */
|
||||
|
||||
/* selected option types from RFC 7967 */
|
||||
|
||||
#define COAP_OPTION_NORESPONSE 258 /* N, uint, 0--1 B, 0 */
|
||||
|
||||
#define COAP_MAX_OPT 65535 /**< the highest option number we know */
|
||||
|
||||
/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */
|
||||
|
||||
/* As of draft-ietf-core-coap-04, response codes are encoded to base
|
||||
* 32, i.e. the three upper bits determine the response class while
|
||||
* the remaining five fine-grained information specific to that class.
|
||||
*/
|
||||
#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100)
|
||||
|
||||
/* Determines the class of response code C */
|
||||
#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF)
|
||||
|
||||
#ifndef SHORT_ERROR_RESPONSE
|
||||
/**
|
||||
* Returns a human-readable response phrase for the specified CoAP response @p
|
||||
* code. This function returns @c NULL if not found.
|
||||
*
|
||||
* @param code The response code for which the literal phrase should be
|
||||
* retrieved.
|
||||
*
|
||||
* @return A zero-terminated string describing the error, or @c NULL if not
|
||||
* found.
|
||||
*/
|
||||
char *coap_response_phrase(unsigned char code);
|
||||
|
||||
#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */
|
||||
|
||||
#else
|
||||
#define coap_response_phrase(x) ((char *)NULL)
|
||||
|
||||
#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */
|
||||
#endif /* SHORT_ERROR_RESPONSE */
|
||||
|
||||
/* The following definitions exist for backwards compatibility */
|
||||
#if 0 /* this does not exist any more */
|
||||
#define COAP_RESPONSE_100 40 /* 100 Continue */
|
||||
#endif
|
||||
#define COAP_RESPONSE_200 COAP_RESPONSE_CODE(200) /* 2.00 OK */
|
||||
#define COAP_RESPONSE_201 COAP_RESPONSE_CODE(201) /* 2.01 Created */
|
||||
#define COAP_RESPONSE_304 COAP_RESPONSE_CODE(203) /* 2.03 Valid */
|
||||
#define COAP_RESPONSE_400 COAP_RESPONSE_CODE(400) /* 4.00 Bad Request */
|
||||
#define COAP_RESPONSE_404 COAP_RESPONSE_CODE(404) /* 4.04 Not Found */
|
||||
#define COAP_RESPONSE_405 COAP_RESPONSE_CODE(405) /* 4.05 Method Not Allowed */
|
||||
#define COAP_RESPONSE_415 COAP_RESPONSE_CODE(415) /* 4.15 Unsupported Media Type */
|
||||
#define COAP_RESPONSE_500 COAP_RESPONSE_CODE(500) /* 5.00 Internal Server Error */
|
||||
#define COAP_RESPONSE_501 COAP_RESPONSE_CODE(501) /* 5.01 Not Implemented */
|
||||
#define COAP_RESPONSE_503 COAP_RESPONSE_CODE(503) /* 5.03 Service Unavailable */
|
||||
#define COAP_RESPONSE_504 COAP_RESPONSE_CODE(504) /* 5.04 Gateway Timeout */
|
||||
#if 0 /* these response codes do not have a valid code any more */
|
||||
# define COAP_RESPONSE_X_240 240 /* Token Option required by server */
|
||||
# define COAP_RESPONSE_X_241 241 /* Uri-Authority Option required by server */
|
||||
#endif
|
||||
#define COAP_RESPONSE_X_242 COAP_RESPONSE_CODE(402) /* Critical Option not supported */
|
||||
|
||||
/* CoAP media type encoding */
|
||||
|
||||
#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */
|
||||
#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */
|
||||
#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */
|
||||
#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */
|
||||
#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */
|
||||
#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */
|
||||
#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */
|
||||
#define COAP_MEDIATYPE_APPLICATION_CBOR 60 /* application/cbor */
|
||||
|
||||
/* Note that identifiers for registered media types are in the range 0-65535. We
|
||||
* use an unallocated type here and hope for the best. */
|
||||
#define COAP_MEDIATYPE_ANY 0xff /* any media type */
|
||||
|
||||
/**
|
||||
* coap_tid_t is used to store CoAP transaction id, i.e. a hash value
|
||||
* built from the remote transport address and the message id of a
|
||||
* CoAP PDU. Valid transaction ids are greater or equal zero.
|
||||
*/
|
||||
typedef int coap_tid_t;
|
||||
|
||||
/** Indicates an invalid transaction id. */
|
||||
#define COAP_INVALID_TID -1
|
||||
|
||||
/**
|
||||
* Indicates that a response is suppressed. This will occur for error
|
||||
* responses if the request was received via IP multicast.
|
||||
*/
|
||||
#define COAP_DROPPED_RESPONSE -2
|
||||
|
||||
#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;
|
||||
#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;
|
||||
#endif
|
||||
|
||||
#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0)
|
||||
#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \
|
||||
&& ((MSG)->code < 32))
|
||||
#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64)
|
||||
|
||||
#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list
|
||||
* in a CoAP message is limited by 0b11110000
|
||||
* marker */
|
||||
|
||||
#define COAP_OPT_END 0xF0 /* end marker */
|
||||
|
||||
#define COAP_PAYLOAD_START 0xFF /* payload marker */
|
||||
|
||||
/**
|
||||
* Structures for more convenient handling of options. (To be used with ordered
|
||||
* coap_list_t.) The option's data will be added to the end of the coap_option
|
||||
* structure (see macro COAP_OPTION_DATA).
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned short key; /* the option key (no delta coding) */
|
||||
unsigned int length;
|
||||
} coap_option;
|
||||
|
||||
#define COAP_OPTION_KEY(option) (option).key
|
||||
#define COAP_OPTION_LENGTH(option) (option).length
|
||||
#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option))
|
||||
|
||||
/**
|
||||
* Header structure for CoAP PDUs
|
||||
*/
|
||||
|
||||
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. */
|
||||
unsigned short max_delta; /**< highest option number */
|
||||
unsigned short length; /**< PDU length (including header, options, data) */
|
||||
unsigned char *data; /**< payload */
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
struct pbuf *pbuf; /**< lwIP PBUF. The package data will always reside
|
||||
* inside the pbuf's payload, but this pointer
|
||||
* has to be kept because no exact offset can be
|
||||
* given. This field must not be accessed from
|
||||
* outside, because the pbuf's reference count
|
||||
* is checked to be 1 when the pbuf is assigned
|
||||
* to the pdu, and the pbuf stays exclusive to
|
||||
* this pdu. */
|
||||
#endif
|
||||
} coap_pdu_t;
|
||||
|
||||
/**
|
||||
* Options in coap_pdu_t are accessed with the macro COAP_OPTION.
|
||||
*/
|
||||
#define COAP_OPTION(node) ((coap_option *)(node)->options)
|
||||
|
||||
#ifdef WITH_LWIP
|
||||
/**
|
||||
* Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to this
|
||||
* function.
|
||||
*
|
||||
* The pbuf is checked for being contiguous, and for having only one reference.
|
||||
* The reference is stored in the PDU and will be freed when the PDU is freed.
|
||||
*
|
||||
* (For now, these are fatal errors; in future, a new pbuf might be allocated,
|
||||
* the data copied and the passed pbuf freed).
|
||||
*
|
||||
* This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards
|
||||
* copying the contents of the pbuf to the pdu.
|
||||
*
|
||||
* @return A pointer to the new PDU object or @c NULL on error.
|
||||
*/
|
||||
coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates a new CoAP PDU of given @p size (must be large enough to hold the
|
||||
* basic CoAP message header (coap_hdr_t). The function returns a pointer to the
|
||||
* node coap_pdu_t object on success, or @c NULL on error. The storage allocated
|
||||
* for the result must be released with coap_delete_pdu().
|
||||
*
|
||||
* @param type The type of the PDU (one of COAP_MESSAGE_CON, COAP_MESSAGE_NON,
|
||||
* COAP_MESSAGE_ACK, COAP_MESSAGE_RST).
|
||||
* @param code The message code.
|
||||
* @param id The message id to set or COAP_INVALID_TID if unknown.
|
||||
* @param size The number of bytes to allocate for the actual message.
|
||||
*
|
||||
* @return A pointer to the new PDU object or @c NULL on error.
|
||||
*/
|
||||
coap_pdu_t *
|
||||
coap_pdu_init(unsigned char type,
|
||||
unsigned char code,
|
||||
unsigned short id,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Clears any contents from @p pdu and resets @c version field, @c
|
||||
* length and @c data pointers. @c max_size is set to @p size, any
|
||||
* other field is set to @c 0. Note that @p pdu must be a valid
|
||||
* pointer to a coap_pdu_t object created e.g. by coap_pdu_init().
|
||||
*/
|
||||
void coap_pdu_clear(coap_pdu_t *pdu, size_t size);
|
||||
|
||||
/**
|
||||
* 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_init() instead.
|
||||
*/
|
||||
coap_pdu_t *coap_new_pdu(void);
|
||||
|
||||
void coap_delete_pdu(coap_pdu_t *);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return A value greater than zero on success or @c 0 on error.
|
||||
*/
|
||||
int coap_pdu_parse(unsigned char *data,
|
||||
size_t length,
|
||||
coap_pdu_t *result);
|
||||
|
||||
/**
|
||||
* 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_token() 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 where the token is to be added.
|
||||
* @param len The length of the new token.
|
||||
* @param data The token to add.
|
||||
*
|
||||
* @return A value greater than zero on success, or @c 0 on error.
|
||||
*/
|
||||
int coap_add_token(coap_pdu_t *pdu,
|
||||
size_t len,
|
||||
const unsigned char *data);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* called. This function returns the number of bytes written or @c 0 on error.
|
||||
*/
|
||||
size_t coap_add_option(coap_pdu_t *pdu,
|
||||
unsigned short type,
|
||||
unsigned int len,
|
||||
const unsigned char *data);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* sequence (i.e. after token and before data). This function returns a memory
|
||||
* address to which the option data has to be written before the PDU can be
|
||||
* sent, or @c NULL on error.
|
||||
*/
|
||||
unsigned char *coap_add_option_later(coap_pdu_t *pdu,
|
||||
unsigned short type,
|
||||
unsigned int len);
|
||||
|
||||
/**
|
||||
* Adds given data to the pdu that is passed as first parameter. Note that the
|
||||
* PDU's data is destroyed by coap_add_option(). coap_add_data() must be called
|
||||
* only once per PDU, otherwise the result is undefined.
|
||||
*/
|
||||
int coap_add_data(coap_pdu_t *pdu,
|
||||
unsigned int len,
|
||||
const unsigned char *data);
|
||||
|
||||
/**
|
||||
* Retrieves the length and data pointer of specified PDU. Returns 0 on error or
|
||||
* 1 if *len and *data have correct values. Note that these values are destroyed
|
||||
* with the pdu.
|
||||
*/
|
||||
int coap_get_data(coap_pdu_t *pdu,
|
||||
size_t *len,
|
||||
unsigned char **data);
|
||||
|
||||
#endif /* _COAP_PDU_H_ */
|
106
tools/sdk/include/coap/coap/prng.h
Normal file
106
tools/sdk/include/coap/coap/prng.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* prng.h -- Pseudo Random Numbers
|
||||
*
|
||||
* Copyright (C) 2010-2011 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file prng.h
|
||||
* @brief Pseudo Random Numbers
|
||||
*/
|
||||
|
||||
#ifndef _COAP_PRNG_H_
|
||||
#define _COAP_PRNG_H_
|
||||
|
||||
/**
|
||||
* @defgroup prng Pseudo Random Numbers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(WITH_POSIX) || (defined(WITH_LWIP) && !defined(LWIP_RAND))
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Fills \p buf with \p len random bytes. This is the default implementation for
|
||||
* prng(). You might want to change prng() to use a better PRNG on your specific
|
||||
* platform.
|
||||
*/
|
||||
static inline int
|
||||
coap_prng_impl(unsigned char *buf, size_t len) {
|
||||
while (len--)
|
||||
*buf++ = rand() & 0xFF;
|
||||
return 1;
|
||||
}
|
||||
#endif /* WITH_POSIX */
|
||||
|
||||
#ifdef WITH_CONTIKI
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Fills \p buf with \p len random bytes. This is the default implementation for
|
||||
* prng(). You might want to change prng() to use a better PRNG on your specific
|
||||
* platform.
|
||||
*/
|
||||
static inline int
|
||||
contiki_prng_impl(unsigned char *buf, size_t len) {
|
||||
unsigned short v = random_rand();
|
||||
while (len > sizeof(v)) {
|
||||
memcpy(buf, &v, sizeof(v));
|
||||
len -= sizeof(v);
|
||||
buf += sizeof(v);
|
||||
v = random_rand();
|
||||
}
|
||||
|
||||
memcpy(buf, &v, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define prng(Buf,Length) contiki_prng_impl((Buf), (Length))
|
||||
#define prng_init(Value) random_init((unsigned short)(Value))
|
||||
#endif /* WITH_CONTIKI */
|
||||
|
||||
#if defined(WITH_LWIP) && defined(LWIP_RAND)
|
||||
static inline int
|
||||
lwip_prng_impl(unsigned char *buf, size_t len) {
|
||||
u32_t v = LWIP_RAND();
|
||||
while (len > sizeof(v)) {
|
||||
memcpy(buf, &v, sizeof(v));
|
||||
len -= sizeof(v);
|
||||
buf += sizeof(v);
|
||||
v = LWIP_RAND();
|
||||
}
|
||||
|
||||
memcpy(buf, &v, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define prng(Buf,Length) lwip_prng_impl((Buf), (Length))
|
||||
#define prng_init(Value)
|
||||
|
||||
#endif /* WITH_LWIP */
|
||||
|
||||
#ifndef prng
|
||||
/**
|
||||
* Fills \p Buf with \p Length bytes of random data.
|
||||
*
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define prng(Buf,Length) coap_prng_impl((Buf), (Length))
|
||||
#endif
|
||||
|
||||
#ifndef prng_init
|
||||
/**
|
||||
* Called to set the PRNG seed. You may want to re-define this to allow for a
|
||||
* better PRNG.
|
||||
*
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define prng_init(Value) srand((unsigned long)(Value))
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _COAP_PRNG_H_ */
|
408
tools/sdk/include/coap/coap/resource.h
Normal file
408
tools/sdk/include/coap/coap/resource.h
Normal file
@ -0,0 +1,408 @@
|
||||
/*
|
||||
* resource.h -- generic resource handling
|
||||
*
|
||||
* Copyright (C) 2010,2011,2014,2015 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file resource.h
|
||||
* @brief Generic resource handling
|
||||
*/
|
||||
|
||||
#ifndef _COAP_RESOURCE_H_
|
||||
#define _COAP_RESOURCE_H_
|
||||
|
||||
# include <assert.h>
|
||||
|
||||
#ifndef COAP_RESOURCE_CHECK_TIME
|
||||
/** The interval in seconds to check if resources have changed. */
|
||||
#define COAP_RESOURCE_CHECK_TIME 2
|
||||
#endif /* COAP_RESOURCE_CHECK_TIME */
|
||||
|
||||
#ifdef COAP_RESOURCES_NOHASH
|
||||
# include "utlist.h"
|
||||
#else
|
||||
# include "uthash.h"
|
||||
#endif
|
||||
|
||||
#include "hashkey.h"
|
||||
#include "async.h"
|
||||
#include "str.h"
|
||||
#include "pdu.h"
|
||||
#include "net.h"
|
||||
#include "subscribe.h"
|
||||
|
||||
/**
|
||||
* Definition of message handler function (@sa coap_resource_t).
|
||||
*/
|
||||
typedef void (*coap_method_handler_t)
|
||||
(coap_context_t *,
|
||||
struct coap_resource_t *,
|
||||
const coap_endpoint_t *,
|
||||
coap_address_t *,
|
||||
coap_pdu_t *,
|
||||
str * /* token */,
|
||||
coap_pdu_t * /* response */);
|
||||
|
||||
#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1
|
||||
#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2
|
||||
|
||||
typedef struct coap_attr_t {
|
||||
struct coap_attr_t *next;
|
||||
str name;
|
||||
str value;
|
||||
int flags;
|
||||
} coap_attr_t;
|
||||
|
||||
/** The URI passed to coap_resource_init() is free'd by coap_delete_resource(). */
|
||||
#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1
|
||||
|
||||
/**
|
||||
* Notifications will be sent non-confirmable by default. RFC 7641 Section 4.5
|
||||
* https://tools.ietf.org/html/rfc7641#section-4.5
|
||||
*/
|
||||
#define COAP_RESOURCE_FLAGS_NOTIFY_NON 0x0
|
||||
|
||||
/**
|
||||
* Notifications will be sent confirmable by default. RFC 7641 Section 4.5
|
||||
* https://tools.ietf.org/html/rfc7641#section-4.5
|
||||
*/
|
||||
#define COAP_RESOURCE_FLAGS_NOTIFY_CON 0x2
|
||||
|
||||
typedef struct coap_resource_t {
|
||||
unsigned int dirty:1; /**< set to 1 if resource has changed */
|
||||
unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet
|
||||
* been notified of the last change */
|
||||
unsigned int observable:1; /**< can be observed */
|
||||
unsigned int cacheable:1; /**< can be cached */
|
||||
|
||||
/**
|
||||
* Used to store handlers for the four coap methods @c GET, @c POST, @c PUT,
|
||||
* and @c DELETE. coap_dispatch() will pass incoming requests to the handler
|
||||
* that corresponds to its request method or generate a 4.05 response if no
|
||||
* handler is available.
|
||||
*/
|
||||
coap_method_handler_t handler[4];
|
||||
|
||||
coap_key_t key; /**< the actual key bytes for this resource */
|
||||
|
||||
#ifdef COAP_RESOURCES_NOHASH
|
||||
struct coap_resource_t *next;
|
||||
#else
|
||||
UT_hash_handle hh;
|
||||
#endif
|
||||
|
||||
coap_attr_t *link_attr; /**< attributes to be included with the link format */
|
||||
coap_subscription_t *subscribers; /**< list of observers for this resource */
|
||||
|
||||
/**
|
||||
* Request URI for this resource. This field will point into the static
|
||||
* memory.
|
||||
*/
|
||||
str uri;
|
||||
int flags;
|
||||
|
||||
} coap_resource_t;
|
||||
|
||||
/**
|
||||
* Creates a new resource object and initializes the link field to the string
|
||||
* of length @p len. This function returns the new coap_resource_t object.
|
||||
*
|
||||
* @param uri The URI path of the new resource.
|
||||
* @param len The length of @p uri.
|
||||
* @param flags Flags for memory management (in particular release of memory).
|
||||
*
|
||||
* @return A pointer to the new object or @c NULL on error.
|
||||
*/
|
||||
coap_resource_t *coap_resource_init(const unsigned char *uri,
|
||||
size_t len, int flags);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the notification message type of resource @p r to given
|
||||
* @p mode which must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON
|
||||
* or @c COAP_RESOURCE_FLAGS_NOTIFY_CON.
|
||||
*/
|
||||
static inline void
|
||||
coap_resource_set_mode(coap_resource_t *r, int mode) {
|
||||
r->flags = (r->flags & !COAP_RESOURCE_FLAGS_NOTIFY_CON) | mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given @p resource for @p context. The resource must have been
|
||||
* created by coap_resource_init(), the storage allocated for the resource will
|
||||
* be released by coap_delete_resource().
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param resource The resource to store.
|
||||
*/
|
||||
void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
|
||||
|
||||
/**
|
||||
* Deletes a resource identified by @p key. The storage allocated for that
|
||||
* resource is freed.
|
||||
*
|
||||
* @param context The context where the resources are stored.
|
||||
* @param key The unique key for the resource to delete.
|
||||
*
|
||||
* @return @c 1 if the resource was found (and destroyed),
|
||||
* @c 0 otherwise.
|
||||
*/
|
||||
int coap_delete_resource(coap_context_t *context, coap_key_t key);
|
||||
|
||||
/**
|
||||
* Deletes all resources from given @p context and frees their storage.
|
||||
*
|
||||
* @param context The CoAP context with the resources to be deleted.
|
||||
*/
|
||||
void coap_delete_all_resources(coap_context_t *context);
|
||||
|
||||
/**
|
||||
* Registers a new attribute with the given @p resource. As the
|
||||
* attributes str fields will point to @p name and @p val the
|
||||
* caller must ensure that these pointers are valid during the
|
||||
* attribute's lifetime.
|
||||
*
|
||||
* @param resource The resource to register the attribute with.
|
||||
* @param name The attribute's name.
|
||||
* @param nlen Length of @p name.
|
||||
* @param val The attribute's value or @c NULL if none.
|
||||
* @param vlen Length of @p val if specified.
|
||||
* @param flags Flags for memory management (in particular release of
|
||||
* memory).
|
||||
*
|
||||
* @return A pointer to the new attribute or @c NULL on error.
|
||||
*/
|
||||
coap_attr_t *coap_add_attr(coap_resource_t *resource,
|
||||
const unsigned char *name,
|
||||
size_t nlen,
|
||||
const unsigned char *val,
|
||||
size_t vlen,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Returns @p resource's coap_attr_t object with given @p name if found, @c NULL
|
||||
* otherwise.
|
||||
*
|
||||
* @param resource The resource to search for attribute @p name.
|
||||
* @param name Name of the requested attribute.
|
||||
* @param nlen Actual length of @p name.
|
||||
* @return The first attribute with specified @p name or @c NULL if none
|
||||
* was found.
|
||||
*/
|
||||
coap_attr_t *coap_find_attr(coap_resource_t *resource,
|
||||
const unsigned char *name,
|
||||
size_t nlen);
|
||||
|
||||
/**
|
||||
* Deletes an attribute.
|
||||
*
|
||||
* @param attr Pointer to a previously created attribute.
|
||||
*
|
||||
*/
|
||||
void coap_delete_attr(coap_attr_t *attr);
|
||||
|
||||
/**
|
||||
* Status word to encode the result of conditional print or copy operations such
|
||||
* as coap_print_link(). The lower 28 bits of coap_print_status_t are used to
|
||||
* encode the number of characters that has actually been printed, bits 28 to 31
|
||||
* encode the status. When COAP_PRINT_STATUS_ERROR is set, an error occurred
|
||||
* during output. In this case, the other bits are undefined.
|
||||
* COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, i.e. the
|
||||
* printing would have exceeded the current buffer.
|
||||
*/
|
||||
typedef unsigned int coap_print_status_t;
|
||||
|
||||
#define COAP_PRINT_STATUS_MASK 0xF0000000u
|
||||
#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK)
|
||||
#define COAP_PRINT_STATUS_ERROR 0x80000000u
|
||||
#define COAP_PRINT_STATUS_TRUNC 0x40000000u
|
||||
|
||||
/**
|
||||
* Writes a description of this resource in link-format to given text buffer. @p
|
||||
* len must be initialized to the maximum length of @p buf and will be set to
|
||||
* the number of characters actually written if successful. This function
|
||||
* returns @c 1 on success or @c 0 on error.
|
||||
*
|
||||
* @param resource The resource to describe.
|
||||
* @param buf The output buffer to write the description to.
|
||||
* @param len Must be initialized to the length of @p buf and
|
||||
* will be set to the length of the printed link description.
|
||||
* @param offset The offset within the resource description where to
|
||||
* start writing into @p buf. This is useful for dealing
|
||||
* with the Block2 option. @p offset is updated during
|
||||
* output as it is consumed.
|
||||
*
|
||||
* @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise,
|
||||
* the lower 28 bits will indicate the number of characters that
|
||||
* have actually been output into @p buffer. The flag
|
||||
* COAP_PRINT_STATUS_TRUNC indicates that the output has been
|
||||
* truncated.
|
||||
*/
|
||||
coap_print_status_t coap_print_link(const coap_resource_t *resource,
|
||||
unsigned char *buf,
|
||||
size_t *len,
|
||||
size_t *offset);
|
||||
|
||||
/**
|
||||
* Registers the specified @p handler as message handler for the request type @p
|
||||
* method
|
||||
*
|
||||
* @param resource The resource for which the handler shall be registered.
|
||||
* @param method The CoAP request method to handle.
|
||||
* @param handler The handler to register with @p resource.
|
||||
*/
|
||||
static inline void
|
||||
coap_register_handler(coap_resource_t *resource,
|
||||
unsigned char method,
|
||||
coap_method_handler_t handler) {
|
||||
assert(resource);
|
||||
assert(method > 0 && (size_t)(method-1) < sizeof(resource->handler)/sizeof(coap_method_handler_t));
|
||||
resource->handler[method-1] = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource identified by the unique string @p key. If no resource
|
||||
* was found, this function returns @c NULL.
|
||||
*
|
||||
* @param context The context to look for this resource.
|
||||
* @param key The unique key of the resource.
|
||||
*
|
||||
* @return A pointer to the resource or @c NULL if not found.
|
||||
*/
|
||||
coap_resource_t *coap_get_resource_from_key(coap_context_t *context,
|
||||
coap_key_t key);
|
||||
|
||||
/**
|
||||
* Calculates the hash key for the resource requested by the Uri-Options of @p
|
||||
* request. This function calls coap_hash() for every path segment.
|
||||
*
|
||||
* @param request The requesting pdu.
|
||||
* @param key The resulting hash is stored in @p key.
|
||||
*/
|
||||
void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key);
|
||||
|
||||
/**
|
||||
* @addtogroup observe
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds the specified peer as observer for @p resource. The subscription is
|
||||
* identified by the given @p token. This function returns the registered
|
||||
* subscription information if the @p observer has been added, or @c NULL on
|
||||
* error.
|
||||
*
|
||||
* @param resource The observed resource.
|
||||
* @param local_interface The local network interface where the observer is
|
||||
* attached to.
|
||||
* @param observer The remote peer that wants to received status updates.
|
||||
* @param token The token that identifies this subscription.
|
||||
* @return A pointer to the added/updated subscription
|
||||
* information or @c NULL on error.
|
||||
*/
|
||||
coap_subscription_t *coap_add_observer(coap_resource_t *resource,
|
||||
const coap_endpoint_t *local_interface,
|
||||
const coap_address_t *observer,
|
||||
const str *token);
|
||||
|
||||
/**
|
||||
* Returns a subscription object for given @p peer.
|
||||
*
|
||||
* @param resource The observed resource.
|
||||
* @param peer The address to search for.
|
||||
* @param token The token that identifies this subscription or @c NULL for
|
||||
* any token.
|
||||
* @return A valid subscription if exists or @c NULL otherwise.
|
||||
*/
|
||||
coap_subscription_t *coap_find_observer(coap_resource_t *resource,
|
||||
const coap_address_t *peer,
|
||||
const str *token);
|
||||
|
||||
/**
|
||||
* Marks an observer as alive.
|
||||
*
|
||||
* @param context The CoAP context to use.
|
||||
* @param observer The transport address of the observer.
|
||||
* @param token The corresponding token that has been used for the
|
||||
* subscription.
|
||||
*/
|
||||
void coap_touch_observer(coap_context_t *context,
|
||||
const coap_address_t *observer,
|
||||
const str *token);
|
||||
|
||||
/**
|
||||
* Removes any subscription for @p observer from @p resource and releases the
|
||||
* allocated storage. The result is @c 1 if an observation relationship with @p
|
||||
* observer and @p token existed, @c 0 otherwise.
|
||||
*
|
||||
* @param resource The observed resource.
|
||||
* @param observer The observer's address.
|
||||
* @param token The token that identifies this subscription or @c NULL for
|
||||
* any token.
|
||||
* @return @c 1 if the observer has been deleted, @c 0 otherwise.
|
||||
*/
|
||||
int coap_delete_observer(coap_resource_t *resource,
|
||||
const coap_address_t *observer,
|
||||
const str *token);
|
||||
|
||||
/**
|
||||
* Checks for all known resources, if they are dirty and notifies subscribed
|
||||
* observers.
|
||||
*/
|
||||
void coap_check_notify(coap_context_t *context);
|
||||
|
||||
#ifdef COAP_RESOURCES_NOHASH
|
||||
|
||||
#define RESOURCES_ADD(r, obj) \
|
||||
LL_PREPEND((r), (obj))
|
||||
|
||||
#define RESOURCES_DELETE(r, obj) \
|
||||
LL_DELETE((r), (obj))
|
||||
|
||||
#define RESOURCES_ITER(r,tmp) \
|
||||
coap_resource_t *tmp; \
|
||||
LL_FOREACH((r), tmp)
|
||||
|
||||
#define RESOURCES_FIND(r, k, res) { \
|
||||
coap_resource_t *tmp; \
|
||||
(res) = tmp = NULL; \
|
||||
LL_FOREACH((r), tmp) { \
|
||||
if (memcmp((k), tmp->key, sizeof(coap_key_t)) == 0) { \
|
||||
(res) = tmp; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else /* COAP_RESOURCES_NOHASH */
|
||||
|
||||
#define RESOURCES_ADD(r, obj) \
|
||||
HASH_ADD(hh, (r), key, sizeof(coap_key_t), (obj))
|
||||
|
||||
#define RESOURCES_DELETE(r, obj) \
|
||||
HASH_DELETE(hh, (r), (obj))
|
||||
|
||||
#define RESOURCES_ITER(r,tmp) \
|
||||
coap_resource_t *tmp, *rtmp; \
|
||||
HASH_ITER(hh, (r), tmp, rtmp)
|
||||
|
||||
#define RESOURCES_FIND(r, k, res) { \
|
||||
HASH_FIND(hh, (r), (k), sizeof(coap_key_t), (res)); \
|
||||
}
|
||||
|
||||
#endif /* COAP_RESOURCES_NOHASH */
|
||||
|
||||
/** @} */
|
||||
|
||||
coap_print_status_t coap_print_wellknown(coap_context_t *,
|
||||
unsigned char *,
|
||||
size_t *, size_t,
|
||||
coap_opt_t *);
|
||||
|
||||
void coap_handle_failed_notify(coap_context_t *,
|
||||
const coap_address_t *,
|
||||
const str *);
|
||||
|
||||
#endif /* _COAP_RESOURCE_H_ */
|
33
tools/sdk/include/coap/coap/str.h
Normal file
33
tools/sdk/include/coap/coap/str.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* str.h -- strings to be used in the CoAP library
|
||||
*
|
||||
* Copyright (C) 2010-2011 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_STR_H_
|
||||
#define _COAP_STR_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
size_t length; /* length of string */
|
||||
unsigned char *s; /* string data */
|
||||
} str;
|
||||
|
||||
#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); }
|
||||
|
||||
/**
|
||||
* Returns a new string object with at least size bytes storage allocated. The
|
||||
* string must be released using coap_delete_string();
|
||||
*/
|
||||
str *coap_new_string(size_t size);
|
||||
|
||||
/**
|
||||
* Deletes the given string and releases any memory allocated.
|
||||
*/
|
||||
void coap_delete_string(str *);
|
||||
|
||||
#endif /* _COAP_STR_H_ */
|
72
tools/sdk/include/coap/coap/subscribe.h
Normal file
72
tools/sdk/include/coap/coap/subscribe.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* subscribe.h -- subscription handling for CoAP
|
||||
* see draft-ietf-core-observe-16
|
||||
*
|
||||
* Copyright (C) 2010-2012,2014-2015 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _COAP_SUBSCRIBE_H_
|
||||
#define _COAP_SUBSCRIBE_H_
|
||||
|
||||
#include "address.h"
|
||||
#include "coap_io.h"
|
||||
|
||||
/**
|
||||
* @defgroup observe Resource observation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The value COAP_OBSERVE_ESTABLISH in a GET request indicates a new observe
|
||||
* relationship for (sender address, token) is requested.
|
||||
*/
|
||||
#define COAP_OBSERVE_ESTABLISH 0
|
||||
|
||||
/**
|
||||
* The value COAP_OBSERVE_CANCEL in a GET request indicates that the observe
|
||||
* relationship for (sender address, token) must be cancelled.
|
||||
*/
|
||||
#define COAP_OBSERVE_CANCEL 1
|
||||
|
||||
#ifndef COAP_OBS_MAX_NON
|
||||
/**
|
||||
* Number of notifications that may be sent non-confirmable before a confirmable
|
||||
* message is sent to detect if observers are alive. The maximum allowed value
|
||||
* here is @c 15.
|
||||
*/
|
||||
#define COAP_OBS_MAX_NON 5
|
||||
#endif /* COAP_OBS_MAX_NON */
|
||||
|
||||
#ifndef COAP_OBS_MAX_FAIL
|
||||
/**
|
||||
* Number of confirmable notifications that may fail (i.e. time out without
|
||||
* being ACKed) before an observer is removed. The maximum value for
|
||||
* COAP_OBS_MAX_FAIL is @c 3.
|
||||
*/
|
||||
#define COAP_OBS_MAX_FAIL 3
|
||||
#endif /* COAP_OBS_MAX_FAIL */
|
||||
|
||||
/** Subscriber information */
|
||||
typedef struct coap_subscription_t {
|
||||
struct coap_subscription_t *next; /**< next element in linked list */
|
||||
coap_endpoint_t local_if; /**< local communication interface */
|
||||
coap_address_t subscriber; /**< address and port of subscriber */
|
||||
|
||||
unsigned int non_cnt:4; /**< up to 15 non-confirmable notifies allowed */
|
||||
unsigned int fail_cnt:2; /**< up to 3 confirmable notifies can fail */
|
||||
unsigned int dirty:1; /**< set if the notification temporarily could not be
|
||||
* sent (in that case, the resource's partially
|
||||
* dirty flag is set too) */
|
||||
size_t token_length; /**< actual length of token */
|
||||
unsigned char token[8]; /**< token used for subscription */
|
||||
} coap_subscription_t;
|
||||
|
||||
void coap_subscription_init(coap_subscription_t *);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _COAP_SUBSCRIBE_H_ */
|
121
tools/sdk/include/coap/coap/uri.h
Normal file
121
tools/sdk/include/coap/coap/uri.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* uri.h -- helper functions for URI treatment
|
||||
*
|
||||
* Copyright (C) 2010-2011,2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _COAP_URI_H_
|
||||
#define _COAP_URI_H_
|
||||
|
||||
#include "hashkey.h"
|
||||
#include "str.h"
|
||||
|
||||
/**
|
||||
* Representation of parsed URI. Components may be filled from a string with
|
||||
* coap_split_uri() and can be used as input for option-creation functions.
|
||||
*/
|
||||
typedef struct {
|
||||
str host; /**< host part of the URI */
|
||||
unsigned short port; /**< The port in host byte order */
|
||||
str path; /**< Beginning of the first path segment.
|
||||
Use coap_split_path() to create Uri-Path options */
|
||||
str query; /**< The query part if present */
|
||||
} coap_uri_t;
|
||||
|
||||
/**
|
||||
* Creates a new coap_uri_t object from the specified URI. Returns the new
|
||||
* object or NULL on error. The memory allocated by the new coap_uri_t
|
||||
* must be released using coap_free().
|
||||
*
|
||||
* @param uri The URI path to copy.
|
||||
* @param length The length of uri.
|
||||
*
|
||||
* @return New URI object or NULL on error.
|
||||
*/
|
||||
coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length);
|
||||
|
||||
/**
|
||||
* Clones the specified coap_uri_t object. Thie function allocates sufficient
|
||||
* memory to hold the coap_uri_t structure and its contents. The object must
|
||||
* be released with coap_free(). */
|
||||
coap_uri_t *coap_clone_uri(const coap_uri_t *uri);
|
||||
|
||||
/**
|
||||
* Calculates a hash over the given path and stores the result in
|
||||
* @p key. This function returns @c 0 on error or @c 1 on success.
|
||||
*
|
||||
* @param path The URI path to generate hash for.
|
||||
* @param len The length of @p path.
|
||||
* @param key The output buffer.
|
||||
*
|
||||
* @return @c 1 if @p key was set, @c 0 otherwise.
|
||||
*/
|
||||
int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key);
|
||||
|
||||
/**
|
||||
* @defgroup uri_parse URI Parsing Functions
|
||||
*
|
||||
* CoAP PDUs contain normalized URIs with their path and query split into
|
||||
* multiple segments. The functions in this module help splitting strings.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses a given string into URI components. The identified syntactic
|
||||
* components are stored in the result parameter @p uri. Optional URI
|
||||
* components that are not specified will be set to { 0, 0 }, except for the
|
||||
* port which is set to @c COAP_DEFAULT_PORT. This function returns @p 0 if
|
||||
* parsing succeeded, a value less than zero otherwise.
|
||||
*
|
||||
* @param str_var The string to split up.
|
||||
* @param len The actual length of @p str_var
|
||||
* @param uri The coap_uri_t object to store the result.
|
||||
* @return @c 0 on success, or < 0 on error.
|
||||
*
|
||||
*/
|
||||
int coap_split_uri(const unsigned char *str_var, size_t len, coap_uri_t *uri);
|
||||
|
||||
/**
|
||||
* Splits the given URI path into segments. Each segment is preceded
|
||||
* by an option pseudo-header with delta-value 0 and the actual length
|
||||
* of the respective segment after percent-decoding.
|
||||
*
|
||||
* @param s The path string to split.
|
||||
* @param length The actual length of @p s.
|
||||
* @param buf Result buffer for parsed segments.
|
||||
* @param buflen Maximum length of @p buf. Will be set to the actual number
|
||||
* of bytes written into buf on success.
|
||||
*
|
||||
* @return The number of segments created or @c -1 on error.
|
||||
*/
|
||||
int coap_split_path(const unsigned char *s,
|
||||
size_t length,
|
||||
unsigned char *buf,
|
||||
size_t *buflen);
|
||||
|
||||
/**
|
||||
* Splits the given URI query into segments. Each segment is preceded
|
||||
* by an option pseudo-header with delta-value 0 and the actual length
|
||||
* of the respective query term.
|
||||
*
|
||||
* @param s The query string to split.
|
||||
* @param length The actual length of @p s.
|
||||
* @param buf Result buffer for parsed segments.
|
||||
* @param buflen Maximum length of @p buf. Will be set to the actual number
|
||||
* of bytes written into buf on success.
|
||||
*
|
||||
* @return The number of segments created or @c -1 on error.
|
||||
*
|
||||
* @bug This function does not reserve additional space for delta > 12.
|
||||
*/
|
||||
int coap_split_query(const unsigned char *s,
|
||||
size_t length,
|
||||
unsigned char *buf,
|
||||
size_t *buflen);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _COAP_URI_H_ */
|
963
tools/sdk/include/coap/coap/uthash.h
Normal file
963
tools/sdk/include/coap/coap/uthash.h
Normal file
@ -0,0 +1,963 @@
|
||||
/*
|
||||
Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#include <string.h> /* memcmp,strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit() */
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ source) this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#if defined(_MSC_VER) /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define DECLTYPE(x) (decltype(x))
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#endif
|
||||
#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#endif
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
char **_da_dst = (char**)(&(dst)); \
|
||||
*_da_dst = (char*)(src); \
|
||||
} while(0)
|
||||
#else
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
(dst) = DECLTYPE(dst)(src); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
|
||||
#if defined (_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#elif defined(__WATCOMC__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define UTHASH_VERSION 1.9.9
|
||||
|
||||
#ifndef uthash_fatal
|
||||
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
|
||||
#endif
|
||||
#ifndef uthash_malloc
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#endif
|
||||
#ifndef uthash_free
|
||||
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
|
||||
#endif
|
||||
|
||||
#ifndef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
|
||||
#endif
|
||||
#ifndef uthash_expand_fyi
|
||||
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
||||
#endif
|
||||
|
||||
/* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
|
||||
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
|
||||
|
||||
/* calculate the element whose hash handle address is hhe */
|
||||
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
||||
|
||||
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
||||
do { \
|
||||
out=NULL; \
|
||||
if (head) { \
|
||||
unsigned _hf_bkt,_hf_hashv; \
|
||||
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
|
||||
keyptr,keylen,out); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef HASH_BLOOM
|
||||
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
|
||||
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
|
||||
#define HASH_BLOOM_MAKE(tbl) \
|
||||
do { \
|
||||
(tbl)->bloom_nbits = HASH_BLOOM; \
|
||||
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
||||
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
|
||||
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
|
||||
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_FREE(tbl) \
|
||||
do { \
|
||||
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) \
|
||||
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
|
||||
|
||||
#else
|
||||
#define HASH_BLOOM_MAKE(tbl)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_BYTELEN 0
|
||||
#endif
|
||||
|
||||
#define HASH_MAKE_TABLE(hh,head) \
|
||||
do { \
|
||||
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
|
||||
sizeof(UT_hash_table)); \
|
||||
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
|
||||
(head)->hh.tbl->tail = &((head)->hh); \
|
||||
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
||||
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
||||
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
||||
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl->buckets, 0, \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_MAKE((head)->hh.tbl); \
|
||||
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
||||
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
|
||||
|
||||
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
||||
do { \
|
||||
replaced=NULL; \
|
||||
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
|
||||
if (replaced!=NULL) { \
|
||||
HASH_DELETE(hh,head,replaced); \
|
||||
}; \
|
||||
HASH_ADD(hh,head,fieldname,keylen_in,add); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
||||
do { \
|
||||
unsigned _ha_bkt; \
|
||||
(add)->hh.next = NULL; \
|
||||
(add)->hh.key = (char*)(keyptr); \
|
||||
(add)->hh.keylen = (unsigned)(keylen_in); \
|
||||
if (!(head)) { \
|
||||
head = (add); \
|
||||
(head)->hh.prev = NULL; \
|
||||
HASH_MAKE_TABLE(hh,head); \
|
||||
} else { \
|
||||
(head)->hh.tbl->tail->next = (add); \
|
||||
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
||||
(head)->hh.tbl->tail = &((add)->hh); \
|
||||
} \
|
||||
(head)->hh.tbl->num_items++; \
|
||||
(add)->hh.tbl = (head)->hh.tbl; \
|
||||
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
|
||||
(add)->hh.hashv, _ha_bkt); \
|
||||
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
||||
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
||||
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
||||
do { \
|
||||
bkt = ((hashv) & ((num_bkts) - 1)); \
|
||||
} while(0)
|
||||
|
||||
/* delete "delptr" from the hash table.
|
||||
* "the usual" patch-up process for the app-order doubly-linked-list.
|
||||
* The use of _hd_hh_del below deserves special explanation.
|
||||
* These used to be expressed using (delptr) but that led to a bug
|
||||
* if someone used the same symbol for the head and deletee, like
|
||||
* HASH_DELETE(hh,users,users);
|
||||
* We want that to work, but by changing the head (users) below
|
||||
* we were forfeiting our ability to further refer to the deletee (users)
|
||||
* in the patch-up process. Solution: use scratch space to
|
||||
* copy the deletee pointer, then the latter references are via that
|
||||
* scratch pointer rather than through the repointed (users) symbol.
|
||||
*/
|
||||
#define HASH_DELETE(hh,head,delptr) \
|
||||
do { \
|
||||
struct UT_hash_handle *_hd_hh_del; \
|
||||
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
head = NULL; \
|
||||
} else { \
|
||||
unsigned _hd_bkt; \
|
||||
_hd_hh_del = &((delptr)->hh); \
|
||||
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
|
||||
(head)->hh.tbl->tail = \
|
||||
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho); \
|
||||
} \
|
||||
if ((delptr)->hh.prev) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
|
||||
} else { \
|
||||
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
|
||||
} \
|
||||
if (_hd_hh_del->next) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
|
||||
(head)->hh.tbl->hho))->prev = \
|
||||
_hd_hh_del->prev; \
|
||||
} \
|
||||
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
||||
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
||||
(head)->hh.tbl->num_items--; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
||||
#define HASH_FIND_STR(head,findstr,out) \
|
||||
HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
|
||||
#define HASH_ADD_STR(head,strfield,add) \
|
||||
HASH_ADD(hh,head,strfield[0],strlen(add->strfield),add)
|
||||
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
|
||||
#define HASH_FIND_INT(head,findint,out) \
|
||||
HASH_FIND(hh,head,findint,sizeof(int),out)
|
||||
#define HASH_ADD_INT(head,intfield,add) \
|
||||
HASH_ADD(hh,head,intfield,sizeof(int),add)
|
||||
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
|
||||
#define HASH_FIND_PTR(head,findptr,out) \
|
||||
HASH_FIND(hh,head,findptr,sizeof(void *),out)
|
||||
#define HASH_ADD_PTR(head,ptrfield,add) \
|
||||
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
|
||||
#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
|
||||
#define HASH_DEL(head,delptr) \
|
||||
HASH_DELETE(hh,head,delptr)
|
||||
|
||||
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
|
||||
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
||||
*/
|
||||
#ifdef HASH_DEBUG
|
||||
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
|
||||
#define HASH_FSCK(hh,head) \
|
||||
do { \
|
||||
struct UT_hash_handle *_thh; \
|
||||
if (head) { \
|
||||
unsigned _bkt_i; \
|
||||
unsigned _count; \
|
||||
char *_prev; \
|
||||
_count = 0; \
|
||||
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
|
||||
unsigned _bkt_count = 0; \
|
||||
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
||||
_prev = NULL; \
|
||||
while (_thh) { \
|
||||
if (_prev != (char*)(_thh->hh_prev)) { \
|
||||
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
|
||||
_thh->hh_prev, _prev ); \
|
||||
} \
|
||||
_bkt_count++; \
|
||||
_prev = (char*)(_thh); \
|
||||
_thh = _thh->hh_next; \
|
||||
} \
|
||||
_count += _bkt_count; \
|
||||
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
||||
HASH_OOPS("invalid bucket count %u, actual %u\n", \
|
||||
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
||||
} \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid hh item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
/* traverse hh in app order; check next/prev integrity, count */ \
|
||||
_count = 0; \
|
||||
_prev = NULL; \
|
||||
_thh = &(head)->hh; \
|
||||
while (_thh) { \
|
||||
_count++; \
|
||||
if (_prev !=(char*)(_thh->prev)) { \
|
||||
HASH_OOPS("invalid prev %p, actual %p\n", \
|
||||
_thh->prev, _prev ); \
|
||||
} \
|
||||
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
||||
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
|
||||
(head)->hh.tbl->hho) : NULL ); \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid app item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_FSCK(hh,head)
|
||||
#endif
|
||||
|
||||
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
||||
* the descriptor to which this macro is defined for tuning the hash function.
|
||||
* The app can #include <unistd.h> to get the prototype for write(2). */
|
||||
#ifdef HASH_EMIT_KEYS
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
||||
do { \
|
||||
unsigned _klen = fieldlen; \
|
||||
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
||||
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#ifdef HASH_FUNCTION
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
||||
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hb_keylen=keylen; \
|
||||
char *_hb_key=(char*)(key); \
|
||||
(hashv) = 0; \
|
||||
while (_hb_keylen--) { (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; } \
|
||||
bkt = (hashv) & (num_bkts-1); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
char *_hs_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
|
||||
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while (0)
|
||||
/* FNV-1a variation */
|
||||
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _fn_i; \
|
||||
char *_hf_key=(char*)(key); \
|
||||
hashv = 2166136261UL; \
|
||||
for(_fn_i=0; _fn_i < keylen; _fn_i++) { \
|
||||
hashv = hashv ^ _hf_key[_fn_i]; \
|
||||
hashv = hashv * 16777619; \
|
||||
} \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _ho_i; \
|
||||
char *_ho_key=(char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
|
||||
hashv += _ho_key[_ho_i]; \
|
||||
hashv += (hashv << 10); \
|
||||
hashv ^= (hashv >> 6); \
|
||||
} \
|
||||
hashv += (hashv << 3); \
|
||||
hashv ^= (hashv >> 11); \
|
||||
hashv += (hashv << 15); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_JEN_MIX(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hj_i,_hj_j,_hj_k; \
|
||||
unsigned char *_hj_key=(unsigned char*)(key); \
|
||||
hashv = 0xfeedbeef; \
|
||||
_hj_i = _hj_j = 0x9e3779b9; \
|
||||
_hj_k = (unsigned)(keylen); \
|
||||
while (_hj_k >= 12) { \
|
||||
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[2] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[3] << 24 ) ); \
|
||||
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[6] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[7] << 24 ) ); \
|
||||
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[10] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[11] << 24 ) ); \
|
||||
\
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
\
|
||||
_hj_key += 12; \
|
||||
_hj_k -= 12; \
|
||||
} \
|
||||
hashv += keylen; \
|
||||
switch ( _hj_k ) { \
|
||||
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
|
||||
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
|
||||
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
|
||||
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
|
||||
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
|
||||
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
|
||||
case 5: _hj_j += _hj_key[4]; \
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
/* case 0: nothing left to add */ \
|
||||
default: /* make gcc -Wswitch-default happy */ \
|
||||
; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
/* The Paul Hsieh hash function */
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned char *_sfh_key=(unsigned char*)(key); \
|
||||
uint32_t _sfh_tmp, _sfh_len = keylen; \
|
||||
\
|
||||
int _sfh_rem = _sfh_len & 3; \
|
||||
_sfh_len >>= 2; \
|
||||
hashv = 0xcafebabe; \
|
||||
\
|
||||
/* Main loop */ \
|
||||
for (;_sfh_len > 0; _sfh_len--) { \
|
||||
hashv += get16bits (_sfh_key); \
|
||||
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
|
||||
hashv = (hashv << 16) ^ _sfh_tmp; \
|
||||
_sfh_key += 2*sizeof (uint16_t); \
|
||||
hashv += hashv >> 11; \
|
||||
} \
|
||||
\
|
||||
/* Handle end cases */ \
|
||||
switch (_sfh_rem) { \
|
||||
case 3: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 16; \
|
||||
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
|
||||
hashv += hashv >> 11; \
|
||||
break; \
|
||||
case 2: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 11; \
|
||||
hashv += hashv >> 17; \
|
||||
break; \
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
hashv ^= hashv << 3; \
|
||||
hashv += hashv >> 5; \
|
||||
hashv ^= hashv << 4; \
|
||||
hashv += hashv >> 17; \
|
||||
hashv ^= hashv << 25; \
|
||||
hashv += hashv >> 6; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
|
||||
#ifdef HASH_USING_NO_STRICT_ALIASING
|
||||
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
|
||||
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
|
||||
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
|
||||
*
|
||||
* Note the preprocessor built-in defines can be emitted using:
|
||||
*
|
||||
* gcc -m64 -dM -E - < /dev/null (on gcc)
|
||||
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
|
||||
*/
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
|
||||
#define MUR_GETBLOCK(p,i) p[i]
|
||||
#else /* non intel */
|
||||
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
|
||||
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
|
||||
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
|
||||
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
|
||||
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
|
||||
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
|
||||
#else /* assume little endian non-intel */
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
|
||||
#endif
|
||||
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
|
||||
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
|
||||
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
|
||||
MUR_ONE_THREE(p))))
|
||||
#endif
|
||||
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
#define MUR_FMIX(_h) \
|
||||
do { \
|
||||
_h ^= _h >> 16; \
|
||||
_h *= 0x85ebca6b; \
|
||||
_h ^= _h >> 13; \
|
||||
_h *= 0xc2b2ae35l; \
|
||||
_h ^= _h >> 16; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const uint8_t *_mur_data = (const uint8_t*)(key); \
|
||||
const int _mur_nblocks = (keylen) / 4; \
|
||||
uint32_t _mur_h1 = 0xf88D5353; \
|
||||
uint32_t _mur_c1 = 0xcc9e2d51; \
|
||||
uint32_t _mur_c2 = 0x1b873593; \
|
||||
uint32_t _mur_k1 = 0; \
|
||||
const uint8_t *_mur_tail; \
|
||||
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
|
||||
int _mur_i; \
|
||||
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
|
||||
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
\
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
|
||||
_mur_h1 = _mur_h1*5+0xe6546b64; \
|
||||
} \
|
||||
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
|
||||
_mur_k1=0; \
|
||||
switch((keylen) & 3) { \
|
||||
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
|
||||
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
|
||||
case 1: _mur_k1 ^= _mur_tail[0]; \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
} \
|
||||
_mur_h1 ^= (keylen); \
|
||||
MUR_FMIX(_mur_h1); \
|
||||
hashv = _mur_h1; \
|
||||
bkt = hashv & (num_bkts-1); \
|
||||
} while(0)
|
||||
#endif /* HASH_USING_NO_STRICT_ALIASING */
|
||||
|
||||
/* key comparison function; return 0 if keys equal */
|
||||
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
|
||||
|
||||
/* iterate over items in a known bucket to find desired item */
|
||||
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
|
||||
do { \
|
||||
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
|
||||
else out=NULL; \
|
||||
while (out) { \
|
||||
if ((out)->hh.keylen == keylen_in) { \
|
||||
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
|
||||
} \
|
||||
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
|
||||
else out = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* add an item to a bucket */
|
||||
#define HASH_ADD_TO_BKT(head,addhh) \
|
||||
do { \
|
||||
head.count++; \
|
||||
(addhh)->hh_next = head.hh_head; \
|
||||
(addhh)->hh_prev = NULL; \
|
||||
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
|
||||
(head).hh_head=addhh; \
|
||||
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
|
||||
&& (addhh)->tbl->noexpand != 1) { \
|
||||
HASH_EXPAND_BUCKETS((addhh)->tbl); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* remove an item from a given bucket */
|
||||
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
|
||||
(head).count--; \
|
||||
if ((head).hh_head == hh_del) { \
|
||||
(head).hh_head = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_prev) { \
|
||||
hh_del->hh_prev->hh_next = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_next) { \
|
||||
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
|
||||
}
|
||||
|
||||
/* Bucket expansion has the effect of doubling the number of buckets
|
||||
* and redistributing the items into the new buckets. Ideally the
|
||||
* items will distribute more or less evenly into the new buckets
|
||||
* (the extent to which this is true is a measure of the quality of
|
||||
* the hash function as it applies to the key domain).
|
||||
*
|
||||
* With the items distributed into more buckets, the chain length
|
||||
* (item count) in each bucket is reduced. Thus by expanding buckets
|
||||
* the hash keeps a bound on the chain length. This bounded chain
|
||||
* length is the essence of how a hash provides constant time lookup.
|
||||
*
|
||||
* The calculation of tbl->ideal_chain_maxlen below deserves some
|
||||
* explanation. First, keep in mind that we're calculating the ideal
|
||||
* maximum chain length based on the *new* (doubled) bucket count.
|
||||
* In fractions this is just n/b (n=number of items,b=new num buckets).
|
||||
* Since the ideal chain length is an integer, we want to calculate
|
||||
* ceil(n/b). We don't depend on floating point arithmetic in this
|
||||
* hash, so to calculate ceil(n/b) with integers we could write
|
||||
*
|
||||
* ceil(n/b) = (n/b) + ((n%b)?1:0)
|
||||
*
|
||||
* and in fact a previous version of this hash did just that.
|
||||
* But now we have improved things a bit by recognizing that b is
|
||||
* always a power of two. We keep its base 2 log handy (call it lb),
|
||||
* so now we can write this with a bit shift and logical AND:
|
||||
*
|
||||
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
||||
*
|
||||
*/
|
||||
#define HASH_EXPAND_BUCKETS(tbl) \
|
||||
do { \
|
||||
unsigned _he_bkt; \
|
||||
unsigned _he_bkt_i; \
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset(_he_new_buckets, 0, \
|
||||
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
tbl->ideal_chain_maxlen = \
|
||||
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
|
||||
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
|
||||
tbl->nonideal_items = 0; \
|
||||
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
|
||||
{ \
|
||||
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
|
||||
while (_he_thh) { \
|
||||
_he_hh_nxt = _he_thh->hh_next; \
|
||||
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
|
||||
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
|
||||
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
|
||||
tbl->nonideal_items++; \
|
||||
_he_newbkt->expand_mult = _he_newbkt->count / \
|
||||
tbl->ideal_chain_maxlen; \
|
||||
} \
|
||||
_he_thh->hh_prev = NULL; \
|
||||
_he_thh->hh_next = _he_newbkt->hh_head; \
|
||||
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
|
||||
_he_thh; \
|
||||
_he_newbkt->hh_head = _he_thh; \
|
||||
_he_thh = _he_hh_nxt; \
|
||||
} \
|
||||
} \
|
||||
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
tbl->num_buckets *= 2; \
|
||||
tbl->log2_num_buckets++; \
|
||||
tbl->buckets = _he_new_buckets; \
|
||||
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
|
||||
(tbl->ineff_expands+1) : 0; \
|
||||
if (tbl->ineff_expands > 1) { \
|
||||
tbl->noexpand=1; \
|
||||
uthash_noexpand_fyi(tbl); \
|
||||
} \
|
||||
uthash_expand_fyi(tbl); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
|
||||
/* Note that HASH_SORT assumes the hash handle name to be hh.
|
||||
* HASH_SRT was added to allow the hash handle name to be passed in. */
|
||||
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
|
||||
#define HASH_SRT(hh,head,cmpfcn) \
|
||||
do { \
|
||||
unsigned _hs_i; \
|
||||
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
||||
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
||||
if (head) { \
|
||||
_hs_insize = 1; \
|
||||
_hs_looping = 1; \
|
||||
_hs_list = &((head)->hh); \
|
||||
while (_hs_looping) { \
|
||||
_hs_p = _hs_list; \
|
||||
_hs_list = NULL; \
|
||||
_hs_tail = NULL; \
|
||||
_hs_nmerges = 0; \
|
||||
while (_hs_p) { \
|
||||
_hs_nmerges++; \
|
||||
_hs_q = _hs_p; \
|
||||
_hs_psize = 0; \
|
||||
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
|
||||
_hs_psize++; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
if (! (_hs_q) ) break; \
|
||||
} \
|
||||
_hs_qsize = _hs_insize; \
|
||||
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
|
||||
if (_hs_psize == 0) { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else if (( \
|
||||
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
|
||||
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
|
||||
) <= 0) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} \
|
||||
if ( _hs_tail ) { \
|
||||
_hs_tail->next = ((_hs_e) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
|
||||
} else { \
|
||||
_hs_list = _hs_e; \
|
||||
} \
|
||||
if (_hs_e) { \
|
||||
_hs_e->prev = ((_hs_tail) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
|
||||
} \
|
||||
_hs_tail = _hs_e; \
|
||||
} \
|
||||
_hs_p = _hs_q; \
|
||||
} \
|
||||
if (_hs_tail){ \
|
||||
_hs_tail->next = NULL; \
|
||||
} \
|
||||
if ( _hs_nmerges <= 1 ) { \
|
||||
_hs_looping=0; \
|
||||
(head)->hh.tbl->tail = _hs_tail; \
|
||||
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
||||
} \
|
||||
_hs_insize *= 2; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This function selects items from one hash into another hash.
|
||||
* The end result is that the selected items have dual presence
|
||||
* in both hashes. There is no copy of the items made; rather
|
||||
* they are added into the new hash through a secondary hash
|
||||
* hash handle that must be present in the structure. */
|
||||
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
||||
do { \
|
||||
unsigned _src_bkt, _dst_bkt; \
|
||||
void *_last_elt=NULL, *_elt; \
|
||||
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
||||
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
|
||||
if (src) { \
|
||||
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
||||
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
||||
_src_hh; \
|
||||
_src_hh = _src_hh->hh_next) { \
|
||||
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
||||
if (cond(_elt)) { \
|
||||
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
|
||||
_dst_hh->key = _src_hh->key; \
|
||||
_dst_hh->keylen = _src_hh->keylen; \
|
||||
_dst_hh->hashv = _src_hh->hashv; \
|
||||
_dst_hh->prev = _last_elt; \
|
||||
_dst_hh->next = NULL; \
|
||||
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
|
||||
if (!dst) { \
|
||||
DECLTYPE_ASSIGN(dst,_elt); \
|
||||
HASH_MAKE_TABLE(hh_dst,dst); \
|
||||
} else { \
|
||||
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
||||
} \
|
||||
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
||||
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
|
||||
(dst)->hh_dst.tbl->num_items++; \
|
||||
_last_elt = _elt; \
|
||||
_last_elt_hh = _dst_hh; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
HASH_FSCK(hh_dst,dst); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_CLEAR(hh,head) \
|
||||
do { \
|
||||
if (head) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
(head)=NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OVERHEAD(hh,head) \
|
||||
((head) ? ( \
|
||||
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
|
||||
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
|
||||
(sizeof(UT_hash_table)) + \
|
||||
(HASH_BLOOM_BYTELEN)))) : 0)
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
|
||||
#else
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
|
||||
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
|
||||
#endif
|
||||
|
||||
/* obtain a count of items in the hash */
|
||||
#define HASH_COUNT(head) HASH_CNT(hh,head)
|
||||
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
|
||||
|
||||
typedef struct UT_hash_bucket {
|
||||
struct UT_hash_handle *hh_head;
|
||||
unsigned count;
|
||||
|
||||
/* expand_mult is normally set to 0. In this situation, the max chain length
|
||||
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
|
||||
* the bucket's chain exceeds this length, bucket expansion is triggered).
|
||||
* However, setting expand_mult to a non-zero value delays bucket expansion
|
||||
* (that would be triggered by additions to this particular bucket)
|
||||
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
|
||||
* (The multiplier is simply expand_mult+1). The whole idea of this
|
||||
* multiplier is to reduce bucket expansions, since they are expensive, in
|
||||
* situations where we know that a particular bucket tends to be overused.
|
||||
* It is better to let its chain length grow to a longer yet-still-bounded
|
||||
* value, than to do an O(n) bucket expansion too often.
|
||||
*/
|
||||
unsigned expand_mult;
|
||||
|
||||
} UT_hash_bucket;
|
||||
|
||||
/* random signature used only to find hash tables in external analysis */
|
||||
#define HASH_SIGNATURE 0xa0111fe1
|
||||
#define HASH_BLOOM_SIGNATURE 0xb12220f2
|
||||
|
||||
typedef struct UT_hash_table {
|
||||
UT_hash_bucket *buckets;
|
||||
unsigned num_buckets, log2_num_buckets;
|
||||
unsigned num_items;
|
||||
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
|
||||
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
|
||||
|
||||
/* in an ideal situation (all buckets used equally), no bucket would have
|
||||
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
|
||||
unsigned ideal_chain_maxlen;
|
||||
|
||||
/* nonideal_items is the number of items in the hash whose chain position
|
||||
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
|
||||
* hash distribution; reaching them in a chain traversal takes >ideal steps */
|
||||
unsigned nonideal_items;
|
||||
|
||||
/* ineffective expands occur when a bucket doubling was performed, but
|
||||
* afterward, more than half the items in the hash had nonideal chain
|
||||
* positions. If this happens on two consecutive expansions we inhibit any
|
||||
* further expansion, as it's not helping; this happens when the hash
|
||||
* function isn't a good fit for the key domain. When expansion is inhibited
|
||||
* the hash will still work, albeit no longer in constant time. */
|
||||
unsigned ineff_expands, noexpand;
|
||||
|
||||
uint32_t signature; /* used only to find hash tables in external analysis */
|
||||
#ifdef HASH_BLOOM
|
||||
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
|
||||
uint8_t *bloom_bv;
|
||||
char bloom_nbits;
|
||||
#endif
|
||||
|
||||
} UT_hash_table;
|
||||
|
||||
typedef struct UT_hash_handle {
|
||||
struct UT_hash_table *tbl;
|
||||
void *prev; /* prev element in app order */
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
#endif /* UTHASH_H */
|
757
tools/sdk/include/coap/coap/utlist.h
Normal file
757
tools/sdk/include/coap/coap/utlist.h
Normal file
@ -0,0 +1,757 @@
|
||||
/*
|
||||
Copyright (c) 2007-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTLIST_H
|
||||
#define UTLIST_H
|
||||
|
||||
#define UTLIST_VERSION 1.9.9
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* This file contains macros to manipulate singly and doubly-linked lists.
|
||||
*
|
||||
* 1. LL_ macros: singly-linked lists.
|
||||
* 2. DL_ macros: doubly-linked lists.
|
||||
* 3. CDL_ macros: circular doubly-linked lists.
|
||||
*
|
||||
* To use singly-linked lists, your structure must have a "next" pointer.
|
||||
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
|
||||
* Either way, the pointer to the head of the list must be initialized to NULL.
|
||||
*
|
||||
* ----------------.EXAMPLE -------------------------
|
||||
* struct item {
|
||||
* int id;
|
||||
* struct item *prev, *next;
|
||||
* }
|
||||
*
|
||||
* struct item *list = NULL:
|
||||
*
|
||||
* int main() {
|
||||
* struct item *item;
|
||||
* ... allocate and populate item ...
|
||||
* DL_APPEND(list, item);
|
||||
* }
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* For doubly-linked lists, the append and delete macros are O(1)
|
||||
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
|
||||
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
|
||||
*/
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ code), this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#ifdef _MSC_VER /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define LDECLTYPE(x) decltype(x)
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define LDECLTYPE(x) char*
|
||||
#endif
|
||||
#elif defined(__ICCARM__)
|
||||
#define NO_DECLTYPE
|
||||
#define LDECLTYPE(x) char*
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define LDECLTYPE(x) __typeof(x)
|
||||
#endif
|
||||
|
||||
/* for VS2008 we use some workarounds to get around the lack of decltype,
|
||||
* namely, we always reassign our tmp variable to the list head if we need
|
||||
* to dereference its prev/next pointers, and save/restore the real head.*/
|
||||
#ifdef NO_DECLTYPE
|
||||
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
|
||||
#define _NEXT(elt,list,next) ((char*)((list)->next))
|
||||
#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
|
||||
/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
|
||||
#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
|
||||
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
|
||||
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
|
||||
#else
|
||||
#define _SV(elt,list)
|
||||
#define _NEXT(elt,list,next) ((elt)->next)
|
||||
#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
|
||||
/* #define _PREV(elt,list,prev) ((elt)->prev) */
|
||||
#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
|
||||
#define _RS(list)
|
||||
#define _CASTASGN(a,b) (a)=(b)
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
|
||||
* Unwieldy variable names used here to avoid shadowing passed-in variables. *
|
||||
*****************************************************************************/
|
||||
#define LL_SORT(list, cmp) \
|
||||
LL_SORT2(list, cmp, next)
|
||||
|
||||
#define LL_SORT2(list, cmp, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
|
||||
} \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define DL_SORT(list, cmp) \
|
||||
DL_SORT2(list, cmp, prev, next)
|
||||
|
||||
#define DL_SORT2(list, cmp, prev, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev, _ls_tail); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_SORT(list, cmp) \
|
||||
CDL_SORT2(list, cmp, prev, next)
|
||||
|
||||
#define CDL_SORT2(list, cmp, prev, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
LDECLTYPE(list) _ls_oldhead; \
|
||||
LDECLTYPE(list) _tmp; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
_CASTASGN(_ls_oldhead,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); \
|
||||
if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
|
||||
_ls_q = NULL; \
|
||||
} else { \
|
||||
_ls_q = _NEXT(_ls_q,list,next); \
|
||||
} \
|
||||
_RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev,_ls_tail); \
|
||||
_CASTASGN(_tmp,list); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************
|
||||
* singly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define LL_PREPEND(head,add) \
|
||||
LL_PREPEND2(head,add,next)
|
||||
|
||||
#define LL_PREPEND2(head,add,next) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
head = add; \
|
||||
} while (0)
|
||||
|
||||
#define LL_CONCAT(head1,head2) \
|
||||
LL_CONCAT2(head1,head2,next)
|
||||
|
||||
#define LL_CONCAT2(head1,head2,next) \
|
||||
do { \
|
||||
LDECLTYPE(head1) _tmp; \
|
||||
if (head1) { \
|
||||
_tmp = head1; \
|
||||
while (_tmp->next) { _tmp = _tmp->next; } \
|
||||
_tmp->next=(head2); \
|
||||
} else { \
|
||||
(head1)=(head2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_APPEND(head,add) \
|
||||
LL_APPEND2(head,add,next)
|
||||
|
||||
#define LL_APPEND2(head,add,next) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
(add)->next=NULL; \
|
||||
if (head) { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next) { _tmp = _tmp->next; } \
|
||||
_tmp->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE(head,del) \
|
||||
LL_DELETE2(head,del,next)
|
||||
|
||||
#define LL_DELETE2(head,del,next) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (del))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = ((del)->next); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
|
||||
#define LL_APPEND_VS2008(head,add) \
|
||||
LL_APPEND2_VS2008(head,add,next)
|
||||
|
||||
#define LL_APPEND2_VS2008(head,add,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->next = head; /* use add->next as a temp variable */ \
|
||||
while ((add)->next->next) { (add)->next = (add)->next->next; } \
|
||||
(add)->next->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
(add)->next=NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE_VS2008(head,del) \
|
||||
LL_DELETE2_VS2008(head,del,next)
|
||||
|
||||
#define LL_DELETE2_VS2008(head,del,next) \
|
||||
do { \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
char *_tmp = (char*)(head); \
|
||||
while ((head)->next && ((head)->next != (del))) { \
|
||||
head = (head)->next; \
|
||||
} \
|
||||
if ((head)->next) { \
|
||||
(head)->next = ((del)->next); \
|
||||
} \
|
||||
{ \
|
||||
char **_head_alias = (char**)&(head); \
|
||||
*_head_alias = _tmp; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#ifdef NO_DECLTYPE
|
||||
#undef LL_APPEND
|
||||
#define LL_APPEND LL_APPEND_VS2008
|
||||
#undef LL_DELETE
|
||||
#define LL_DELETE LL_DELETE_VS2008
|
||||
#undef LL_DELETE2
|
||||
#define LL_DELETE2 LL_DELETE2_VS2008
|
||||
#undef LL_APPEND2
|
||||
#define LL_APPEND2 LL_APPEND2_VS2008
|
||||
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
|
||||
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
|
||||
#endif
|
||||
/* end VS2008 replacements */
|
||||
|
||||
#define LL_COUNT(head,el,counter) \
|
||||
LL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define LL_COUNT2(head,el,counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
LL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define LL_FOREACH(head,el) \
|
||||
LL_FOREACH2(head,el,next)
|
||||
|
||||
#define LL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=(el)->next)
|
||||
|
||||
#define LL_FOREACH_SAFE(head,el,tmp) \
|
||||
LL_FOREACH_SAFE2(head,el,tmp,next)
|
||||
|
||||
#define LL_FOREACH_SAFE2(head,el,tmp,next) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
#define LL_SEARCH_SCALAR(head,out,field,val) \
|
||||
LL_SEARCH_SCALAR2(head,out,field,val,next)
|
||||
|
||||
#define LL_SEARCH_SCALAR2(head,out,field,val,next) \
|
||||
do { \
|
||||
LL_FOREACH2(head,out,next) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_SEARCH(head,out,elt,cmp) \
|
||||
LL_SEARCH2(head,out,elt,cmp,next)
|
||||
|
||||
#define LL_SEARCH2(head,out,elt,cmp,next) \
|
||||
do { \
|
||||
LL_FOREACH2(head,out,next) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el)->next; \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (el))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (el))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* doubly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define DL_PREPEND(head,add) \
|
||||
DL_PREPEND2(head,add,prev,next)
|
||||
|
||||
#define DL_PREPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
} \
|
||||
(head) = (add); \
|
||||
} while (0)
|
||||
|
||||
#define DL_APPEND(head,add) \
|
||||
DL_APPEND2(head,add,prev,next)
|
||||
|
||||
#define DL_APPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev->next = (add); \
|
||||
(head)->prev = (add); \
|
||||
(add)->next = NULL; \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
(head)->prev = (head); \
|
||||
(head)->next = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_CONCAT(head1,head2) \
|
||||
DL_CONCAT2(head1,head2,prev,next)
|
||||
|
||||
#define DL_CONCAT2(head1,head2,prev,next) \
|
||||
do { \
|
||||
LDECLTYPE(head1) _tmp; \
|
||||
if (head2) { \
|
||||
if (head1) { \
|
||||
_tmp = (head2)->prev; \
|
||||
(head2)->prev = (head1)->prev; \
|
||||
(head1)->prev->next = (head2); \
|
||||
(head1)->prev = _tmp; \
|
||||
} else { \
|
||||
(head1)=(head2); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_DELETE(head,del) \
|
||||
DL_DELETE2(head,del,prev,next)
|
||||
|
||||
#define DL_DELETE2(head,del,prev,next) \
|
||||
do { \
|
||||
assert((del)->prev != NULL); \
|
||||
if ((del)->prev == (del)) { \
|
||||
(head)=NULL; \
|
||||
} else if ((del)==(head)) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(head) = (del)->next; \
|
||||
} else { \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del)->next) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
} else { \
|
||||
(head)->prev = (del)->prev; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_COUNT(head,el,counter) \
|
||||
DL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define DL_COUNT2(head,el,counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
DL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define DL_FOREACH(head,el) \
|
||||
DL_FOREACH2(head,el,next)
|
||||
|
||||
#define DL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=(el)->next)
|
||||
|
||||
/* this version is safe for deleting the elements during iteration */
|
||||
#define DL_FOREACH_SAFE(head,el,tmp) \
|
||||
DL_FOREACH_SAFE2(head,el,tmp,next)
|
||||
|
||||
#define DL_FOREACH_SAFE2(head,el,tmp,next) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
/* these are identical to their singly-linked list counterparts */
|
||||
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
|
||||
#define DL_SEARCH LL_SEARCH
|
||||
#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
|
||||
#define DL_SEARCH2 LL_SEARCH2
|
||||
|
||||
#define DL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
(add)->next = (el)->next; \
|
||||
if ((el)->next == NULL) { \
|
||||
(add)->prev = (add); \
|
||||
} else { \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->next->prev = (add); \
|
||||
} \
|
||||
} else { \
|
||||
(add)->next = (el)->next; \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->prev->next = (add); \
|
||||
if ((el)->next == NULL) { \
|
||||
(head)->prev = (add); \
|
||||
} else { \
|
||||
(add)->next->prev = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
(add)->prev = (el)->prev; \
|
||||
(el)->prev = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
(add)->prev->next = (add); \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* circular doubly linked list macros *
|
||||
*****************************************************************************/
|
||||
#define CDL_PREPEND(head,add) \
|
||||
CDL_PREPEND2(head,add,prev,next)
|
||||
|
||||
#define CDL_PREPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(add)->next = (head); \
|
||||
(head)->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
(add)->next = (add); \
|
||||
} \
|
||||
(head)=(add); \
|
||||
} while (0)
|
||||
|
||||
#define CDL_DELETE(head,del) \
|
||||
CDL_DELETE2(head,del,prev,next)
|
||||
|
||||
#define CDL_DELETE2(head,del,prev,next) \
|
||||
do { \
|
||||
if ( ((head)==(del)) && ((head)->next == (head))) { \
|
||||
(head) = 0L; \
|
||||
} else { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del) == (head)) (head)=(del)->next; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_COUNT(head,el,counter) \
|
||||
CDL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define CDL_COUNT2(head, el, counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
CDL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define CDL_FOREACH(head,el) \
|
||||
CDL_FOREACH2(head,el,next)
|
||||
|
||||
#define CDL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
|
||||
|
||||
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
|
||||
CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
|
||||
|
||||
#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
|
||||
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
|
||||
(el) && ((tmp2)=(el)->next, 1); \
|
||||
((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
|
||||
|
||||
#define CDL_SEARCH_SCALAR(head,out,field,val) \
|
||||
CDL_SEARCH_SCALAR2(head,out,field,val,next)
|
||||
|
||||
#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
|
||||
do { \
|
||||
CDL_FOREACH2(head,out,next) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CDL_SEARCH(head,out,elt,cmp) \
|
||||
CDL_SEARCH2(head,out,elt,cmp,next)
|
||||
|
||||
#define CDL_SEARCH2(head,out,elt,cmp,next) \
|
||||
do { \
|
||||
CDL_FOREACH2(head,out,next) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CDL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
if ((el)->next == (el)) { \
|
||||
(add)->next = (add); \
|
||||
(add)->prev = (add); \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
(add)->next = (el)->next; \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->next->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
(add)->prev = (el)->prev; \
|
||||
(el)->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
#endif /* UTLIST_H */
|
||||
|
39
tools/sdk/include/coap/coap_config.h
Normal file
39
tools/sdk/include/coap/coap_config.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* libcoap configure implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* configure operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
#include "coap_config_posix.h"
|
||||
#endif
|
||||
|
||||
#define HAVE_STDIO_H
|
||||
#define HAVE_ASSERT_H
|
||||
|
||||
#define PACKAGE_STRING PACKAGE_NAME PACKAGE_VERSION
|
||||
|
||||
/* it's just provided by libc. i hope we don't get too many of those, as
|
||||
* actually we'd need autotools again to find out what environment we're
|
||||
* building in */
|
||||
#define HAVE_STRNLEN 1
|
||||
|
||||
#define HAVE_LIMITS_H
|
||||
|
||||
#define COAP_RESOURCES_NOHASH
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
41
tools/sdk/include/coap/coap_config_posix.h
Normal file
41
tools/sdk/include/coap/coap_config_posix.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* libcoap configure implementation for ESP32 platform.
|
||||
*
|
||||
* Uses libcoap software implementation for failover when concurrent
|
||||
* configure operations are in use.
|
||||
*
|
||||
* coap.h -- main header file for CoAP stack of libcoap
|
||||
*
|
||||
* Copyright (C) 2010-2012,2015-2016 Olaf Bergmann <bergmann@tzi.org>
|
||||
* 2015 Carsten Schoenert <c.schoenert@t-online.de>
|
||||
*
|
||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef COAP_CONFIG_POSIX_H_
|
||||
#define COAP_CONFIG_POSIX_H_
|
||||
|
||||
#ifdef WITH_POSIX
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define HAVE_SYS_SOCKET_H
|
||||
#define HAVE_MALLOC
|
||||
#define HAVE_ARPA_INET_H
|
||||
|
||||
#define IP_PKTINFO IP_MULTICAST_IF
|
||||
#define IPV6_PKTINFO IPV6_V6ONLY
|
||||
|
||||
#define PACKAGE_NAME "libcoap-posix"
|
||||
#define PACKAGE_VERSION "?"
|
||||
|
||||
#define CUSTOM_COAP_NETWORK_ENDPOINT
|
||||
#define CUSTOM_COAP_NETWORK_SEND
|
||||
#define CUSTOM_COAP_NETWORK_READ
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* COAP_CONFIG_POSIX_H_ */
|
Reference in New Issue
Block a user