Initial Esp32c3 Support (#5060)

This commit is contained in:
Me No Dev
2021-04-14 18:10:05 +03:00
committed by GitHub
parent 371f382db7
commit 404a31f445
1929 changed files with 382833 additions and 190 deletions

View File

@ -0,0 +1,177 @@
/*
* 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"
#if defined(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) \
((A)->port == (B)->port \
&& (!!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)
#elif defined(WITH_CONTIKI)
#include "uip.h"
typedef struct coap_address_t {
uip_ipaddr_t addr;
uint16_t 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))
#else /* WITH_LWIP || WITH_CONTIKI */
/** multi-purpose address abstraction */
typedef struct coap_address_t {
socklen_t size; /**< size of addr */
union {
struct sockaddr sa;
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);
COAP_STATIC_INLINE int
_coap_address_isany_impl(const coap_address_t *a) {
/* need to compare only relevant parts of sockaddr_in6 */
switch (a->addr.sa.sa_family) {
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_LWIP || WITH_CONTIKI */
/**
* 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.
*/
COAP_STATIC_INLINE void
coap_address_init(coap_address_t *addr) {
assert(addr);
memset(addr, 0, sizeof(coap_address_t));
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
/* lwip and Contiki have constant address sizes and doesn't need the .size part */
addr->size = sizeof(addr->addr);
#endif
}
/* Convenience function to copy IPv6 addresses without garbage. */
COAP_STATIC_INLINE void
coap_address_copy( coap_address_t *dst, const coap_address_t *src ) {
#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
memcpy( dst, src, sizeof( coap_address_t ) );
#else
memset( dst, 0, sizeof( coap_address_t ) );
dst->size = src->size;
if ( src->addr.sa.sa_family == AF_INET6 ) {
dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
} else if ( src->addr.sa.sa_family == AF_INET ) {
dst->addr.sin = src->addr.sin;
} else {
memcpy( &dst->addr, &src->addr, src->size );
}
#endif
}
#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
/**
* Compares given address objects @p a and @p b. This function returns @c 1 if
* addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be
* @c NULL;
*/
COAP_STATIC_INLINE int
coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
assert(a); assert(b);
return _coap_address_equals_impl(a, b);
}
#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;
*/
COAP_STATIC_INLINE int
coap_address_isany(const coap_address_t *a) {
assert(a);
return _coap_address_isany_impl(a);
}
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
/**
* 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_LWIP && !WITH_CONTIKI */
/**
* Checks if given address @p a denotes a multicast address. This function
* returns @c 1 if @p a is multicast, @c 0 otherwise.
*/
COAP_STATIC_INLINE int
coap_is_mcast(const coap_address_t *a) {
return a && _coap_is_mcast_impl(a);
}
#endif /* !WITH_LWIP && !WITH_CONTIKI */
#endif /* COAP_ADDRESS_H_ */

View File

@ -0,0 +1,148 @@
/*
* 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;
coap_session_t *session; /**< transaction session */
coap_tid_t id; /**< transaction id */
struct coap_async_state_t *next; /**< internally used for linking */
size_t tokenlen; /**< length of the token */
uint8_t token[8]; /**< 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 session The session that is used for asynchronous transmissions.
* @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_session_t *session,
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 session The session that is used for asynchronous transmissions.
* @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_session_t *session,
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 session The session that is used for asynchronous transmissions.
* @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_session_t *session, coap_tid_t id);
/**
* Updates the time stamp of @p s.
*
* @param s The state object to update.
*/
COAP_STATIC_INLINE void
coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); }
/** @} */
#endif /* WITHOUT_ASYNC */
#endif /* COAP_ASYNC_H_ */

View 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.
*/
COAP_STATIC_INLINE int
bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
if (size <= ((size_t)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.
*/
COAP_STATIC_INLINE int
bits_clrb(uint8_t *vec, size_t size, uint8_t bit) {
if (size <= ((size_t)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.
*/
COAP_STATIC_INLINE int
bits_getb(const uint8_t *vec, size_t size, uint8_t bit) {
if (size <= ((size_t)bit >> 3))
return -1;
return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0;
}
#endif /* COAP_BITS_H_ */

View File

@ -0,0 +1,173 @@
/*
* 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"
struct coap_resource_t;
struct coap_session_t;
/**
* @defgroup block Block Transfer
* API functions for handling PDUs using CoAP BLOCK options
* @{
*/
#ifndef COAP_MAX_BLOCK_SZX
/**
* The largest value for the SZX component in a Block option.
*/
#define COAP_MAX_BLOCK_SZX 6
#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).
*/
COAP_STATIC_INLINE int
coap_more_blocks(size_t data_len, unsigned int num, uint16_t szx) {
return ((num+1) << (szx + 4)) < data_len;
}
#if 0
/** Sets the More-bit in @p block_opt */
COAP_STATIC_INLINE void
coap_opt_block_set_m(coap_opt_t *block_opt, int m) {
if (m)
*(coap_opt_value(block_opt) + (coap_opt_length(block_opt) - 1)) |= 0x08;
else
*(coap_opt_value(block_opt) + (coap_opt_length(block_opt) - 1)) &= ~0x08;
}
#endif
/**
* 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, uint16_t 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,
uint16_t 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 uint8_t *data,
unsigned int block_num,
unsigned char block_szx);
/**
* Adds the appropriate part of @p data to the @p response pdu. If blocks are
* required, then the appropriate block will be added to the PDU and sent.
* Adds a ETAG option that is the hash of the entire data if the data is to be
* split into blocks
* Used by a GET request handler.
*
* @param resource The resource the data is associated with.
* @param session The coap session.
* @param request The requesting pdu.
* @param response The response pdu.
* @param token The token taken from the (original) requesting pdu.
* @param media_type The format of the data.
* @param maxage The maxmimum life of the data. If @c -1, then there
* is no maxage.
* @param length The total length of the data.
* @param data The entire data block to transmit.
*
*/
void
coap_add_data_blocked_response(struct coap_resource_t *resource,
struct coap_session_t *session,
coap_pdu_t *request,
coap_pdu_t *response,
const coap_binary_t *token,
uint16_t media_type,
int maxage,
size_t length,
const uint8_t* data);
/**@}*/
#endif /* COAP_BLOCK_H_ */

View File

@ -0,0 +1,209 @@
/*
* coap_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_
/**
* @defgroup logging Logging Support
* API functions for logging support
* @{
*/
#ifndef COAP_DEBUG_FD
/**
* Used for output for @c LOG_DEBUG to @c LOG_ERR.
*/
#define COAP_DEBUG_FD stdout
#endif
#ifndef COAP_ERR_FD
/**
* Used for output for @c LOG_CRIT to @c LOG_EMERG.
*/
#define COAP_ERR_FD stderr
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
/**
* Logging type. One of LOG_* from @b syslog.
*/
typedef short coap_log_t;
#else
/** Pre-defined log levels akin to what is used in \b syslog. */
typedef enum {
LOG_EMERG=0, /**< Emergency */
LOG_ALERT, /**< Alert */
LOG_CRIT, /**< Critical */
LOG_ERR, /**< Error */
LOG_WARNING, /**< Warning */
LOG_NOTICE, /**< Notice */
LOG_INFO, /**< Information */
LOG_DEBUG /**< Debug */
} coap_log_t;
#endif
/**
* Get the current logging level.
*
* @return One of the LOG_* values.
*/
coap_log_t coap_get_log_level(void);
/**
* Sets the log level to the specified value.
*
* @param level One of the LOG_* values.
*/
void coap_set_log_level(coap_log_t level);
/**
* Logging call-back handler definition.
*
* @param level One of the LOG_* values.
* @param message Zero-terminated string message to log.
*/
typedef void (*coap_log_handler_t) (coap_log_t level, const char *message);
/**
* Add a custom log callback handler.
*
* @param handler The logging handler to use or @p NULL to use default handler.
*/
void coap_set_log_handler(coap_log_handler_t handler);
/**
* Get the library package name.
*
* @return Zero-terminated string with the name of this library.
*/
const char *coap_package_name(void);
/**
* Get the library package version.
*
* @return 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_ERR). The text is output only when
* @p level is below or equal to the log level that set by coap_set_log_level().
*
* Internal function.
*
* @param level One of the LOG_* values.
& @param format The format string to use.
*/
#if (defined(__GNUC__))
void coap_log_impl(coap_log_t level,
const char *format, ...) __attribute__ ((format(printf, 2, 3)));
#else
void coap_log_impl(coap_log_t level, const char *format, ...);
#endif
#ifndef coap_log
/**
* Logging function.
* 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_ERR). The text is output only when
* @p level is below or equal to the log level that set by coap_set_log_level().
*
* @param level One of the LOG_* values.
*/
#define coap_log(level, ...) do { \
if ((int)((level))<=(int)coap_get_log_level()) \
coap_log_impl((level), __VA_ARGS__); \
} while(0)
#endif
#include "pdu.h"
/**
* Defines the output mode for the coap_show_pdu() function.
*
* @param use_fprintf @p 1 if the output is to use fprintf() (the default)
* @p 0 if the output is to use coap_log().
*/
void coap_set_show_pdu_output(int use_fprintf);
/**
* Display the contents of the specified @p pdu.
* Note: The output method of coap_show_pdu() is dependent on the setting of
* coap_set_show_pdu_output().
*
* @param level The required minimum logging level.
* @param pdu The PDU to decode.
*/
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu);
/**
* Display the current (D)TLS library linked with and built for version.
*
* @param level The required minimum logging level.
*/
void coap_show_tls_version(coap_log_t level);
/**
* Build a string containing the current (D)TLS library linked with and
* built for version.
*
* @param buffer The buffer to put the string into.
* @param bufsize The size of the buffer to put the string into.
*
* @return A pointer to the provided buffer.
*/
char *coap_string_tls_version(char *buffer, size_t bufsize);
struct coap_address_t;
/**
* Print the address into the defined buffer.
*
* Internal Function.
*
* @param address The address to print.
* @param buffer The buffer to print into.
* @param size The size of the buffer to print into.
*
* @return The amount written into the buffer.
*/
size_t coap_print_addr(const struct coap_address_t *address,
unsigned char *buffer, size_t size);
/** @} */
/**
* Set the packet loss level for testing. This can be in one of two forms.
*
* Percentage : 0% to 100%. Use the specified probability.
* 0% is send all packets, 100% is drop all packets.
*
* List: A comma separated list of numbers or number ranges that are the
* packets to drop.
*
* @param loss_level The defined loss level (percentage or list).
*
* @return @c 1 If loss level set, @c 0 if there is an error.
*/
int coap_debug_set_packet_loss(const char *loss_level);
/**
* Check to see whether a packet should be sent or not.
*
* Internal function
*
* @return @c 1 if packet is to be sent, @c 0 if packet is to be dropped.
*/
int coap_debug_send_packet(void);
#endif /* COAP_DEBUG_H_ */

View File

@ -0,0 +1,611 @@
/*
* coap_dtls.h -- (Datagram) Transport Layer Support for libcoap
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
*
* This file is part of the CoAP library libcoap. Please see README for terms
* of use.
*/
#ifndef COAP_DTLS_H_
#define COAP_DTLS_H_
#include "coap_time.h"
struct coap_context_t;
struct coap_session_t;
struct coap_dtls_pki_t;
/**
* @defgroup dtls DTLS Support
* API functions for interfacing with DTLS libraries.
* @{
*/
/**
* Check whether DTLS is available.
*
* @return @c 1 if support for DTLS is enabled, or @c 0 otherwise.
*/
int coap_dtls_is_supported(void);
/**
* Check whether TLS is available.
*
* @return @c 1 if support for TLS is enabled, or @c 0 otherwise.
*/
int coap_tls_is_supported(void);
#define COAP_TLS_LIBRARY_NOTLS 0 /**< No DTLS library */
#define COAP_TLS_LIBRARY_TINYDTLS 1 /**< Using TinyDTLS library */
#define COAP_TLS_LIBRARY_OPENSSL 2 /**< Using OpenSSL library */
#define COAP_TLS_LIBRARY_GNUTLS 3 /**< Using GnuTLS library */
/**
* The structure used for returning the underlying (D)TLS library
* information.
*/
typedef struct coap_tls_version_t {
uint64_t version; /**< (D)TLS runtime Library Version */
int type; /**< Library type. One of COAP_TLS_LIBRARY_* */
uint64_t built_version; /**< (D)TLS Built against Library Version */
} coap_tls_version_t;
/**
* Determine the type and version of the underlying (D)TLS library.
*
* @return The version and type of library libcoap was compiled against.
*/
coap_tls_version_t *coap_get_tls_library_version(void);
/**
* Additional Security setup handler that can be set up by
* coap_context_set_pki().
* Invoked when libcoap has done the validation checks at the TLS level,
* but the application needs to do some additional checks/changes/updates.
*
* @param tls_session The security session definition - e.g. SSL * for OpenSSL.
* NULL if server call-back.
* This will be dependent on the underlying TLS library -
* see coap_get_tls_library_version()
* @param setup_data A structure containing setup data originally passed into
* coap_context_set_pki() or coap_new_client_session_pki().
*
* @return @c 1 if successful, else @c 0.
*/
typedef int (*coap_dtls_security_setup_t)(void* tls_session,
struct coap_dtls_pki_t *setup_data);
/**
* CN Validation call-back that can be set up by coap_context_set_pki().
* Invoked when libcoap has done the validation checks at the TLS level,
* but the application needs to check that the CN is allowed.
* CN is the SubjectAltName in the cert, if not present, then the leftmost
* Common Name (CN) component of the subject name.
*
* @param cn The determined CN from the certificate
* @param asn1_public_cert The ASN.1 DER encoded X.509 certificate
* @param asn1_length The ASN.1 length
* @param coap_session The CoAP session associated with the certificate update
* @param depth Depth in cert chain. If 0, then client cert, else a CA
* @param validated TLS layer can find no issues if 1
* @param arg The same as was passed into coap_context_set_pki()
* in setup_data->cn_call_back_arg
*
* @return @c 1 if accepted, else @c 0 if to be rejected.
*/
typedef int (*coap_dtls_cn_callback_t)(const char *cn,
const uint8_t *asn1_public_cert,
size_t asn1_length,
struct coap_session_t *coap_session,
unsigned depth,
int validated,
void *arg);
/**
* The enum used for determining the provided PKI ASN.1 (DER) Private Key
* formats.
*/
typedef enum coap_asn1_privatekey_type_t {
COAP_ASN1_PKEY_NONE, /**< NONE */
COAP_ASN1_PKEY_RSA, /**< RSA type */
COAP_ASN1_PKEY_RSA2, /**< RSA2 type */
COAP_ASN1_PKEY_DSA, /**< DSA type */
COAP_ASN1_PKEY_DSA1, /**< DSA1 type */
COAP_ASN1_PKEY_DSA2, /**< DSA2 type */
COAP_ASN1_PKEY_DSA3, /**< DSA3 type */
COAP_ASN1_PKEY_DSA4, /**< DSA4 type */
COAP_ASN1_PKEY_DH, /**< DH type */
COAP_ASN1_PKEY_DHX, /**< DHX type */
COAP_ASN1_PKEY_EC, /**< EC type */
COAP_ASN1_PKEY_HMAC, /**< HMAC type */
COAP_ASN1_PKEY_CMAC, /**< CMAC type */
COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */
COAP_ASN1_PKEY_HKDF /**< HKDF type */
} coap_asn1_privatekey_type_t;
/**
* The enum used for determining the PKI key formats.
*/
typedef enum coap_pki_key_t {
COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM */
COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) */
} coap_pki_key_t;
/**
* The structure that holds the PKI PEM definitions.
*/
typedef struct coap_pki_key_pem_t {
const char *ca_file; /**< File location of Common CA in PEM format */
const char *public_cert; /**< File location of Public Cert in PEM format */
const char *private_key; /**< File location of Private Key in PEM format */
} coap_pki_key_pem_t;
/**
* The structure that holds the PKI ASN.1 (DER) definitions.
*/
typedef struct coap_pki_key_asn1_t {
const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */
const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */
const uint8_t *private_key; /**< ASN1 (DER) Private Key */
size_t ca_cert_len; /**< ASN1 CA Cert length */
size_t public_cert_len; /**< ASN1 Public Cert length */
size_t private_key_len; /**< ASN1 Private Key length */
coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */
} coap_pki_key_asn1_t;
/**
* The structure that holds the PKI key information.
*/
typedef struct coap_dtls_key_t {
coap_pki_key_t key_type; /**< key format type */
union {
coap_pki_key_pem_t pem; /**< for PEM keys */
coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) keys */
} key;
} coap_dtls_key_t;
/**
* Server Name Indication (SNI) Validation call-back that can be set up by
* coap_context_set_pki().
* Invoked if the SNI is not previously seen and prior to sending a certificate
* set back to the client so that the appropriate certificate set can be used
* based on the requesting SNI.
*
* @param sni The requested SNI
* @param arg The same as was passed into coap_context_set_pki()
* in setup_data->sni_call_back_arg
*
* @return New set of certificates to use, or @c NULL if SNI is to be rejected.
*/
typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
void* arg);
#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */
/**
* The structure used for defining the PKI setup data to be used.
*/
typedef struct coap_dtls_pki_t {
uint8_t version; /** Set to 1 to support this version of the struct */
/* Options to enable different TLS functionality in libcoap */
uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */
uint8_t require_peer_cert; /**< 1 if peer cert is required */
uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */
uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */
uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */
uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */
uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */
uint8_t allow_no_crl; /**< 1 ignore if CRL not there */
uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */
uint8_t reserved[6]; /**< Reserved - must be set to 0 for
future compatibility */
/* Size of 6 chosen to align to next
* parameter, so if newly defined option
* it can use one of the reserverd slot so
* no need to change
* COAP_DTLS_PKI_SETUP_VERSION and just
* decrement the reserved[] count.
*/
/** CN check call-back function.
* If not NULL, is called when the TLS connection has passed the configured
* TLS options above for the application to verify if the CN is valid.
*/
coap_dtls_cn_callback_t validate_cn_call_back;
void *cn_call_back_arg; /**< Passed in to the CN call-back function */
/** SNI check call-back function.
* If not @p NULL, called if the SNI is not previously seen and prior to
* sending a certificate set back to the client so that the appropriate
* certificate set can be used based on the requesting SNI.
*/
coap_dtls_sni_callback_t validate_sni_call_back;
void *sni_call_back_arg; /**< Passed in to the sni call-back function */
/** Additional Security call-back handler that is invoked when libcoap has
* done the standerd, defined validation checks at the TLS level,
* If not @p NULL, called from within the TLS Client Hello connection
* setup.
*/
coap_dtls_security_setup_t additional_tls_setup_call_back;
char* client_sni; /**< If not NULL, SNI to use in client TLS setup.
Owned by the client app and must remain valid
during the call to coap_new_client_session_pki() */
coap_dtls_key_t pki_key; /**< PKI key definition */
} coap_dtls_pki_t;
/** @} */
/**
* @defgroup dtls_internal DTLS Support (Internal)
* Internal API functions for interfacing with DTLS libraries.
* @{
*/
/**
* Creates a new DTLS context for the given @p coap_context. This function
* returns a pointer to a new DTLS context object or @c NULL on error.
*
* Internal function.
*
* @param coap_context The CoAP context where the DTLS object shall be used.
*
* @return A DTLS context object or @c NULL on error.
*/
void *
coap_dtls_new_context(struct coap_context_t *coap_context);
typedef enum coap_dtls_role_t {
COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */
COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */
} coap_dtls_role_t;
/**
* Set the DTLS context's default PSK information.
* This does the PSK specifics following coap_dtls_new_context().
* If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set.
* If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
* TLS library's context (from which sessions are derived).
* If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
* TLS library's session.
*
* Internal function.
*
* @param coap_context The CoAP context.
* @param identity_hint The default PSK server identity hint sent to a client.
* Required parameter. If @p NULL, will be set to "".
* Empty string is a valid hint.
* This parameter is ignored if COAP_DTLS_ROLE_CLIENT
* @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_psk(struct coap_context_t *coap_context,
const char *identity_hint,
coap_dtls_role_t role);
/**
* Set the DTLS context's default server PKI information.
* This does the PKI specifics following coap_dtls_new_context().
* If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
* TLS library's context (from which sessions are derived).
* If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
* TLS library's session.
*
* Internal function.
*
* @param coap_context The CoAP context.
* @param setup_data Setup information defining how PKI is to be setup.
* Required parameter. If @p NULL, PKI will not be
* set up.
* @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_pki(struct coap_context_t *coap_context,
coap_dtls_pki_t *setup_data,
coap_dtls_role_t role);
/**
* Set the dtls context's default Root CA information for a client or server.
*
* Internal function.
*
* @param coap_context The current coap_context_t object.
* @param ca_file If not @p NULL, is the full path name of a PEM encoded
* file containing all the Root CAs to be used.
* @param ca_dir If not @p NULL, points to a directory containing PEM
* encoded files containing all the Root CAs to be used.
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context,
const char *ca_file,
const char *ca_dir);
/**
* Check whether one of the coap_dtls_context_set_{psk|pki}() functions have
* been called.
*
* Internal function.
*
* @param coap_context The current coap_context_t object.
*
* @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0.
*/
int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context);
/**
* Releases the storage allocated for @p dtls_context.
*
* Internal function.
*
* @param dtls_context The DTLS context as returned by coap_dtls_new_context().
*/
void coap_dtls_free_context(void *dtls_context);
/**
* Create a new client-side session. This should send a HELLO to the server.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_dtls_new_client_session(struct coap_session_t *coap_session);
/**
* Create a new DTLS server-side session.
* Called after coap_dtls_hello() has returned @c 1, signalling that a validated
* HELLO was received from a client.
* This should send a HELLO to the server.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the DTLS session.
*/
void *coap_dtls_new_server_session(struct coap_session_t *coap_session);
/**
* Terminates the DTLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_free_session(struct coap_session_t *coap_session);
/**
* Notify of a change in the CoAP session's MTU, for example after
* a PMTU update.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_session_update_mtu(struct coap_session_t *coap_session);
/**
* Send data to a DTLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this would be blocking, @c -1 if there is an error or the
* number of cleartext bytes sent.
*/
int coap_dtls_send(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Check if timeout is handled per CoAP session or per CoAP context.
*
* Internal function.
*
* @return @c 1 of timeout and retransmit is per context, @c 0 if it is
* per session.
*/
int coap_dtls_is_context_timeout(void);
/**
* Do all pending retransmits and get next timeout
*
* Internal function.
*
* @param dtls_context The DTLS context.
*
* @return @c 0 if no event is pending or date of the next retransmit.
*/
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context);
/**
* Get next timeout for this session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param now The current time in ticks.
*
* @return @c 0 If no event is pending or ticks time of the next retransmit.
*/
coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session,
coap_tick_t now);
/**
* Handle a DTLS timeout expiration.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_handle_timeout(struct coap_session_t *coap_session);
/**
* Handling incoming data from a DTLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return Result of coap_handle_dgram on the decrypted CoAP PDU
* or @c -1 for error.
*/
int coap_dtls_receive(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Handling client HELLO messages from a new candiate peer.
* Note that session->tls is empty.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return @c 0 if a cookie verification message has been sent, @c 1 if the
* HELLO contains a valid cookie and a server session should be created,
* @c -1 if the message is invalid.
*/
int coap_dtls_hello(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Get DTLS overhead over cleartext PDUs.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Maximum number of bytes added by DTLS layer.
*/
unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session);
/**
* Create a new TLS client-side session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param connected Updated with whether the connection is connected yet or not.
* @c 0 is not connected, @c 1 is connected.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected);
/**
* Create a TLS new server-side session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param connected Updated with whether the connection is connected yet or not.
* @c 0 is not connected, @c 1 is connected.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected);
/**
* Terminates the TLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_tls_free_session( struct coap_session_t *coap_session );
/**
* Send data to a TLS peer, with implicit flush.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes sent.
*/
ssize_t coap_tls_write(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len
);
/**
* Read some data from a TLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Maximum number of bytes to read.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes read.
*/
ssize_t coap_tls_read(struct coap_session_t *coap_session,
uint8_t *data,
size_t data_len
);
/**
* Initialize the underlying (D)TLS Library layer.
*
* Internal function.
*
*/
void coap_dtls_startup(void);
/** @} */
/**
* @ingroup logging
* Sets the (D)TLS logging level to the specified @p level.
* Note: coap_log_level() will influence output if at a specified level.
*
* @param level The logging level to use - LOG_*
*/
void coap_dtls_set_log_level(int level);
/**
* @ingroup logging
* Get the current (D)TLS logging.
*
* @return The current log level (one of LOG_*).
*/
int coap_dtls_get_log_level(void);
#endif /* COAP_DTLS_H */

View File

@ -0,0 +1,102 @@
/*
* coap_event.h -- libcoap Event API
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see README for terms
* of use.
*/
#ifndef COAP_EVENT_H_
#define COAP_EVENT_H_
#include "libcoap.h"
struct coap_context_t;
struct coap_session_t;
/**
* @defgroup events Event API
* API functions for event delivery from lower-layer library functions.
* @{
*/
/**
* Scalar type to represent different events, e.g. DTLS events or
* retransmission timeouts.
*/
typedef unsigned int coap_event_t;
/**
* (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
*/
#define COAP_EVENT_DTLS_CLOSED 0x0000
#define COAP_EVENT_DTLS_CONNECTED 0x01DE
#define COAP_EVENT_DTLS_RENEGOTIATE 0x01DF
#define COAP_EVENT_DTLS_ERROR 0x0200
/**
* TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS
*/
#define COAP_EVENT_TCP_CONNECTED 0x1001
#define COAP_EVENT_TCP_CLOSED 0x1002
#define COAP_EVENT_TCP_FAILED 0x1003
/**
* CSM exchange events for reliable protocols only
*/
#define COAP_EVENT_SESSION_CONNECTED 0x2001
#define COAP_EVENT_SESSION_CLOSED 0x2002
#define COAP_EVENT_SESSION_FAILED 0x2003
/**
* Type for event handler functions that can be registered with a CoAP
* context using the unction coap_set_event_handler(). When called by
* the library, the first argument will be the coap_context_t object
* where the handler function has been registered. The second argument
* is the event type that may be complemented by event-specific data
* passed as the third argument.
*/
typedef int (*coap_event_handler_t)(struct coap_context_t *,
coap_event_t event,
struct coap_session_t *session);
/**
* Registers the function @p hnd as callback for events from the given
* CoAP context @p context. Any event handler that has previously been
* registered with @p context will be overwritten by this operation.
*
* @param context The CoAP context to register the event handler with.
* @param hnd The event handler to be registered. @c NULL if to be
* de-registered.
*/
void coap_register_event_handler(struct coap_context_t *context,
coap_event_handler_t hnd);
/**
* Registers the function @p hnd as callback for events from the given
* CoAP context @p context. Any event handler that has previously been
* registered with @p context will be overwritten by this operation.
*
* @deprecated Use coap_register_event_handler() instead.
*
* @param context The CoAP context to register the event handler with.
* @param hnd The event handler to be registered.
*/
COAP_DEPRECATED
void coap_set_event_handler(struct coap_context_t *context,
coap_event_handler_t hnd);
/**
* Clears the event handler registered with @p context.
*
* @deprecated Use coap_register_event_handler() instead with NULL for hnd.
*
* @param context The CoAP context whose event handler is to be removed.
*/
COAP_DEPRECATED
void coap_clear_event_handler(struct coap_context_t *context);
/** @} */
#endif /* COAP_EVENT_H */

View File

@ -0,0 +1,59 @@
/*
* coap_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 coap_hashkey.h
* @brief definition of hash key type and helper functions
*/
#ifndef COAP_HASHKEY_H_
#define COAP_HASHKEY_H_
#include "libcoap.h"
#include "uthash.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 coap_string_t 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_ */

View File

@ -0,0 +1,210 @@
/*
* 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"
#ifndef COAP_RXBUFFER_SIZE
#define COAP_RXBUFFER_SIZE 1472
#endif /* COAP_RXBUFFER_SIZE */
#ifdef _WIN32
typedef SOCKET coap_fd_t;
#define coap_closesocket closesocket
#define COAP_SOCKET_ERROR SOCKET_ERROR
#define COAP_INVALID_SOCKET INVALID_SOCKET
#else
typedef int coap_fd_t;
#define coap_closesocket close
#define COAP_SOCKET_ERROR (-1)
#define COAP_INVALID_SOCKET (-1)
#endif
struct coap_packet_t;
struct coap_session_t;
struct coap_pdu_t;
typedef uint16_t coap_socket_flags_t;
typedef struct coap_socket_t {
#if defined(WITH_LWIP)
struct udp_pcb *pcb;
#elif defined(WITH_CONTIKI)
void *conn;
#else
coap_fd_t fd;
#endif /* WITH_LWIP */
coap_socket_flags_t flags;
} coap_socket_t;
/**
* coap_socket_flags_t values
*/
#define COAP_SOCKET_EMPTY 0x0000 /**< the socket is not used */
#define COAP_SOCKET_NOT_EMPTY 0x0001 /**< the socket is not empty */
#define COAP_SOCKET_BOUND 0x0002 /**< the socket is bound */
#define COAP_SOCKET_CONNECTED 0x0004 /**< the socket is connected */
#define COAP_SOCKET_WANT_READ 0x0010 /**< non blocking socket is waiting for reading */
#define COAP_SOCKET_WANT_WRITE 0x0020 /**< non blocking socket is waiting for writing */
#define COAP_SOCKET_WANT_ACCEPT 0x0040 /**< non blocking server socket is waiting for accept */
#define COAP_SOCKET_WANT_CONNECT 0x0080 /**< non blocking client socket is waiting for connect */
#define COAP_SOCKET_CAN_READ 0x0100 /**< non blocking socket can now read without blocking */
#define COAP_SOCKET_CAN_WRITE 0x0200 /**< non blocking socket can now write without blocking */
#define COAP_SOCKET_CAN_ACCEPT 0x0400 /**< non blocking server socket can now accept without blocking */
#define COAP_SOCKET_CAN_CONNECT 0x0800 /**< non blocking client socket can now connect without blocking */
#define COAP_SOCKET_MULTICAST 0x1000 /**< socket is used for multicast communication */
struct coap_endpoint_t *coap_malloc_endpoint( void );
void coap_mfree_endpoint( struct coap_endpoint_t *ep );
int
coap_socket_connect_udp(coap_socket_t *sock,
const coap_address_t *local_if,
const coap_address_t *server,
int default_port,
coap_address_t *local_addr,
coap_address_t *remote_addr);
int
coap_socket_bind_udp(coap_socket_t *sock,
const coap_address_t *listen_addr,
coap_address_t *bound_addr );
int
coap_socket_connect_tcp1(coap_socket_t *sock,
const coap_address_t *local_if,
const coap_address_t *server,
int default_port,
coap_address_t *local_addr,
coap_address_t *remote_addr);
int
coap_socket_connect_tcp2(coap_socket_t *sock,
coap_address_t *local_addr,
coap_address_t *remote_addr);
int
coap_socket_bind_tcp(coap_socket_t *sock,
const coap_address_t *listen_addr,
coap_address_t *bound_addr);
int
coap_socket_accept_tcp(coap_socket_t *server,
coap_socket_t *new_client,
coap_address_t *local_addr,
coap_address_t *remote_addr);
void coap_socket_close(coap_socket_t *sock);
ssize_t
coap_socket_send( coap_socket_t *sock, struct coap_session_t *session,
const uint8_t *data, size_t data_len );
ssize_t
coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len);
ssize_t
coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len);
#ifdef WITH_LWIP
ssize_t
coap_socket_send_pdu( coap_socket_t *sock, struct coap_session_t *session,
struct coap_pdu_t *pdu );
#endif
const char *coap_socket_strerror( void );
/**
* 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 sock Socket to send data with
* @param session Addressing information for unconnected sockets, or NULL
* @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( coap_socket_t *sock, const struct coap_session_t *session, const uint8_t *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 sock Socket to read data from
* @param packet Received packet metadata and payload. src and dst should be preset.
*
* @return The number of bytes received on success, or a value less than
* zero on error.
*/
ssize_t coap_network_read( coap_socket_t *sock, struct coap_packet_t *packet );
#ifndef coap_mcast_interface
# define coap_mcast_interface(Local) 0
#endif
/**
* 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(struct 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(struct coap_packet_t *packet);
#endif
#if defined(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 struct coap_endpoint_t *local_interface;
coap_address_t src; /**< the packet's source address */
coap_address_t dst; /**< the packet's destination address */
int ifindex; /**< the interface index */
// uint16_t srcport;
};
#else
struct coap_packet_t {
coap_address_t src; /**< the packet's source address */
coap_address_t dst; /**< the packet's destination address */
int ifindex; /**< the interface index */
size_t length; /**< length of payload */
unsigned char payload[COAP_RXBUFFER_SIZE]; /**< payload */
};
#endif
typedef struct coap_packet_t coap_packet_t;
typedef enum {
COAP_NACK_TOO_MANY_RETRIES,
COAP_NACK_NOT_DELIVERABLE,
COAP_NACK_RST,
COAP_NACK_TLS_FAILED
} coap_nack_reason_t;
#endif /* COAP_IO_H_ */

View File

@ -0,0 +1,50 @@
/*
* coap_mutex.h -- mutex utilities
*
* Copyright (C) 2019 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* This file is part of the CoAP library libcoap. Please see README for terms
* of use.
*/
/**
* @file coap_mutex.h
* @brief COAP mutex mechanism wrapper
*/
#ifndef COAP_MUTEX_H_
#define COAP_MUTEX_H_
#if defined(RIOT_VERSION)
#include <mutex.h>
typedef mutex_t coap_mutex_t;
#define COAP_MUTEX_INITIALIZER MUTEX_INIT
#define coap_mutex_lock(a) mutex_lock(a)
#define coap_mutex_trylock(a) mutex_trylock(a)
#define coap_mutex_unlock(a) mutex_unlock(a)
#elif defined(WITH_CONTIKI)
/* CONTIKI does not support mutex */
typedef int coap_mutex_t;
#define COAP_MUTEX_INITIALIZER 0
#define coap_mutex_lock(a) *(a) = 1
#define coap_mutex_trylock(a) *(a) = 1
#define coap_mutex_unlock(a) *(a) = 0
#else /* ! RIOT_VERSION && ! WITH_CONTIKI */
#include <pthread.h>
typedef pthread_mutex_t coap_mutex_t;
#define COAP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define coap_mutex_lock(a) pthread_mutex_lock(a)
#define coap_mutex_trylock(a) pthread_mutex_trylock(a)
#define coap_mutex_unlock(a) pthread_mutex_unlock(a)
#endif /* ! RIOT_VERSION && ! WITH_CONTIKI */
#endif /* COAP_MUTEX_H_ */

View File

@ -0,0 +1,492 @@
/* coap_session.h -- Session management for libcoap
*
* Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com>
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#ifndef COAP_SESSION_H_
#define COAP_SESSION_H_
#include "coap_io.h"
#include "coap_time.h"
#include "pdu.h"
struct coap_endpoint_t;
struct coap_context_t;
struct coap_queue_t;
/**
* Abstraction of a fixed point number that can be used where necessary instead
* of a float. 1,000 fractional bits equals one integer
*/
typedef struct coap_fixed_point_t {
uint16_t integer_part; /**< Integer part of fixed point variable */
uint16_t fractional_part; /**< Fractional part of fixed point variable
1/1000 (3 points) precision */
} coap_fixed_point_t;
#define COAP_DEFAULT_SESSION_TIMEOUT 300
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND)
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100
#define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS)
#define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS)
typedef uint8_t coap_session_type_t;
/**
* coap_session_type_t values
*/
#define COAP_SESSION_TYPE_CLIENT 1 /**< client-side */
#define COAP_SESSION_TYPE_SERVER 2 /**< server-side */
#define COAP_SESSION_TYPE_HELLO 3 /**< server-side ephemeral session for responding to a client hello */
typedef uint8_t coap_session_state_t;
/**
* coap_session_state_t values
*/
#define COAP_SESSION_STATE_NONE 0
#define COAP_SESSION_STATE_CONNECTING 1
#define COAP_SESSION_STATE_HANDSHAKE 2
#define COAP_SESSION_STATE_CSM 3
#define COAP_SESSION_STATE_ESTABLISHED 4
typedef struct coap_session_t {
struct coap_session_t *next;
coap_proto_t proto; /**< protocol used */
coap_session_type_t type; /**< client or server side socket */
coap_session_state_t state; /**< current state of relationaship with peer */
unsigned ref; /**< reference count from queues */
unsigned tls_overhead; /**< overhead of TLS layer */
unsigned mtu; /**< path or CSM mtu */
coap_address_t local_if; /**< optional local interface address */
coap_address_t remote_addr; /**< remote address and port */
coap_address_t local_addr; /**< local address and port */
int ifindex; /**< interface index */
coap_socket_t sock; /**< socket object for the session, if any */
struct coap_endpoint_t *endpoint; /**< session's endpoint */
struct coap_context_t *context; /**< session's context */
void *tls; /**< security parameters */
uint16_t tx_mid; /**< the last message id that was used in this session */
uint8_t con_active; /**< Active CON request sent */
struct coap_queue_t *delayqueue; /**< list of delayed messages waiting to be sent */
size_t partial_write; /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */
uint8_t read_header[8]; /**< storage space for header of incoming message header */
size_t partial_read; /**< if > 0 indicates number of bytes already read for an incoming message */
coap_pdu_t *partial_pdu; /**< incomplete incoming pdu */
coap_tick_t last_rx_tx;
coap_tick_t last_tx_rst;
coap_tick_t last_ping;
coap_tick_t last_pong;
coap_tick_t csm_tx;
uint8_t *psk_identity;
size_t psk_identity_len;
uint8_t *psk_key;
size_t psk_key_len;
void *app; /**< application-specific data */
unsigned int max_retransmit; /**< maximum re-transmit count (default 4) */
coap_fixed_point_t ack_timeout; /**< timeout waiting for ack (default 2 secs) */
coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default 1.5) */
unsigned int dtls_timeout_count; /**< dtls setup retry counter */
int dtls_event; /**< Tracking any (D)TLS events on this sesison */
} coap_session_t;
/**
* Increment reference counter on a session.
*
* @param session The CoAP session.
* @return same as session
*/
coap_session_t *coap_session_reference(coap_session_t *session);
/**
* Decrement reference counter on a session.
* Note that the session may be deleted as a result and should not be used
* after this call.
*
* @param session The CoAP session.
*/
void coap_session_release(coap_session_t *session);
/**
* Stores @p data with the given session. This function overwrites any value
* that has previously been stored with @p session.
*/
void coap_session_set_app_data(coap_session_t *session, void *data);
/**
* Returns any application-specific data that has been stored with @p
* session using the function coap_session_set_app_data(). This function will
* return @c NULL if no data has been stored.
*/
void *coap_session_get_app_data(const coap_session_t *session);
/**
* Notify session that it has failed.
*
* @param session The CoAP session.
* @param reason The reason why the session was disconnected.
*/
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason);
/**
* Notify session transport has just connected and CSM exchange can now start.
*
* @param session The CoAP session.
*/
void coap_session_send_csm(coap_session_t *session);
/**
* Notify session that it has just connected or reconnected.
*
* @param session The CoAP session.
*/
void coap_session_connected(coap_session_t *session);
/**
* Set the session MTU. This is the maximum message size that can be sent,
* excluding IP and UDP overhead.
*
* @param session The CoAP session.
* @param mtu maximum message size
*/
void coap_session_set_mtu(coap_session_t *session, unsigned mtu);
/**
* Get maximum acceptable PDU size
*
* @param session The CoAP session.
* @return maximum PDU size, not including header (but including token).
*/
size_t coap_session_max_pdu_size(const coap_session_t *session);
/**
* Creates a new client session to the designated server.
* @param ctx The CoAP context.
* @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
* @param server The server's address. If the port number is zero, the default port for the protocol will be used.
* @param proto Protocol.
*
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
*/
coap_session_t *coap_new_client_session(
struct coap_context_t *ctx,
const coap_address_t *local_if,
const coap_address_t *server,
coap_proto_t proto
);
/**
* Creates a new client session to the designated server with PSK credentials
* @param ctx The CoAP context.
* @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
* @param server The server's address. If the port number is zero, the default port for the protocol will be used.
* @param proto Protocol.
* @param identity PSK client identity
* @param key PSK shared key
* @param key_len PSK shared key length
*
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
*/
coap_session_t *coap_new_client_session_psk(
struct coap_context_t *ctx,
const coap_address_t *local_if,
const coap_address_t *server,
coap_proto_t proto,
const char *identity,
const uint8_t *key,
unsigned key_len
);
struct coap_dtls_pki_t;
/**
* Creates a new client session to the designated server with PKI credentials
* @param ctx The CoAP context.
* @param local_if Address of local interface. It is recommended to use NULL to
* let the operating system choose a suitable local interface.
* If an address is specified, the port number should be zero,
* which means that a free port is automatically selected.
* @param server The server's address. If the port number is zero, the default
* port for the protocol will be used.
* @param proto CoAP Protocol.
* @param setup_data PKI parameters.
*
* @return A new CoAP session or NULL if failed. Call coap_session_release()
* to free.
*/
coap_session_t *coap_new_client_session_pki(
struct coap_context_t *ctx,
const coap_address_t *local_if,
const coap_address_t *server,
coap_proto_t proto,
struct coap_dtls_pki_t *setup_data
);
/**
* Creates a new server session for the specified endpoint.
* @param ctx The CoAP context.
* @param ep An endpoint where an incoming connection request is pending.
*
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
*/
coap_session_t *coap_new_server_session(
struct coap_context_t *ctx,
struct coap_endpoint_t *ep
);
/**
* Function interface for datagram data transmission. This function returns
* the number of bytes that have been transmitted, or a value less than zero
* on error.
*
* @param session Session to send data on.
* @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_session_send(coap_session_t *session,
const uint8_t *data, size_t datalen);
/**
* Function interface for stream data transmission. This function returns
* the number of bytes that have been transmitted, or a value less than zero
* on error. The number of bytes written may be less than datalen because of
* congestion control.
*
* @param session Session to send data on.
* @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_session_write(coap_session_t *session,
const uint8_t *data, size_t datalen);
/**
* Send a pdu according to the session's protocol. This function returns
* the number of bytes that have been transmitted, or a value less than zero
* on error.
*
* @param session Session to send pdu on.
* @param pdu The pdu to send.
*
* @return The number of bytes written on success, or a value
* less than zero on error.
*/
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu);
/**
* @ingroup logging
* Get session description.
*
* @param session The CoAP session.
* @return description string.
*/
const char *coap_session_str(const coap_session_t *session);
ssize_t
coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu,
struct coap_queue_t *node);
/**
* 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 {
struct coap_endpoint_t *next;
struct coap_context_t *context; /**< endpoint's context */
coap_proto_t proto; /**< protocol used on this interface */
uint16_t default_mtu; /**< default mtu for this interface */
coap_socket_t sock; /**< socket object for the interface, if any */
coap_address_t bind_addr; /**< local interface address */
coap_session_t *sessions; /**< list of active sessions */
} coap_endpoint_t;
/**
* Create a new endpoint for communicating with peers.
*
* @param context The coap context that will own the new endpoint
* @param listen_addr Address the endpoint will listen for incoming requests on or originate outgoing requests from. Use NULL to specify that no incoming request will be accepted and use a random endpoint.
* @param proto Protocol used on this endpoint
*/
coap_endpoint_t *coap_new_endpoint(struct coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto);
/**
* Set the endpoint's default MTU. This is the maximum message size that can be
* sent, excluding IP and UDP overhead.
*
* @param endpoint The CoAP endpoint.
* @param mtu maximum message size
*/
void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu);
void coap_free_endpoint(coap_endpoint_t *ep);
/**
* @ingroup logging
* Get endpoint description.
*
* @param endpoint The CoAP endpoint.
* @return description string.
*/
const char *coap_endpoint_str(const coap_endpoint_t *endpoint);
/**
* Lookup the server session for the packet received on an endpoint, or create
* a new one.
*
* @param endpoint Active endpoint the packet was received on.
* @param packet Received packet.
* @param now The current time in ticks.
* @return The CoAP session or @c NULL if error.
*/
coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint,
const struct coap_packet_t *packet, coap_tick_t now);
/**
* Create a new DTLS session for the @p session.
* Note: the @p session is released if no DTLS server session can be created.
*
* @ingroup dtls_internal
*
* @param session Session to add DTLS session to
* @param now The current time in ticks.
*
* @return CoAP session or @c NULL if error.
*/
coap_session_t *coap_session_new_dtls_session(coap_session_t *session,
coap_tick_t now);
coap_session_t *coap_session_get_by_peer(struct coap_context_t *ctx,
const struct coap_address_t *remote_addr, int ifindex);
void coap_session_free(coap_session_t *session);
void coap_session_mfree(coap_session_t *session);
/**
* @defgroup cc Rate Control
* The transmission parameters for CoAP rate control ("Congestion
* Control" in stream-oriented protocols) are defined in
* https://tools.ietf.org/html/rfc7252#section-4.8
* @{
*/
/**
* Number of seconds when to expect an ACK or a response to an
* outstanding CON message.
* RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2
*/
#define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0})
/**
* A factor that is used to randomize the wait time before a message
* is retransmitted to prevent synchronization effects.
* RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5
*/
#define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500})
/**
* Number of message retransmissions before message sending is stopped
* RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4
*/
#define COAP_DEFAULT_MAX_RETRANSMIT 4
/**
* The number of simultaneous outstanding interactions that a client
* maintains to a given server.
* RFC 7252, Section 4.8 Default value of NSTART is 1
*/
#define COAP_DEFAULT_NSTART 1
/** @} */
/**
* Set the CoAP maximum retransmit count before failure
*
* Number of message retransmissions before message sending is stopped
*
* @param session The CoAP session.
* @param value The value to set to. The default is 4 and should not normally
* get changed.
*/
void coap_session_set_max_retransmit(coap_session_t *session,
unsigned int value);
/**
* Set the CoAP initial ack response timeout before the next re-transmit
*
* Number of seconds when to expect an ACK or a response to an
* outstanding CON message.
*
* @param session The CoAP session.
* @param value The value to set to. The default is 2 and should not normally
* get changed.
*/
void coap_session_set_ack_timeout(coap_session_t *session,
coap_fixed_point_t value);
/**
* Set the CoAP ack randomize factor
*
* A factor that is used to randomize the wait time before a message
* is retransmitted to prevent synchronization effects.
*
* @param session The CoAP session.
* @param value The value to set to. The default is 1.5 and should not normally
* get changed.
*/
void coap_session_set_ack_random_factor(coap_session_t *session,
coap_fixed_point_t value);
/**
* Get the CoAP maximum retransmit before failure
*
* Number of message retransmissions before message sending is stopped
*
* @param session The CoAP session.
*
* @return Current maximum retransmit value
*/
unsigned int coap_session_get_max_transmit(coap_session_t *session);
/**
* Get the CoAP initial ack response timeout before the next re-transmit
*
* Number of seconds when to expect an ACK or a response to an
* outstanding CON message.
*
* @param session The CoAP session.
*
* @return Current ack response timeout value
*/
coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session);
/**
* Get the CoAP ack randomize factor
*
* A factor that is used to randomize the wait time before a message
* is retransmitted to prevent synchronization effects.
*
* @param session The CoAP session.
*
* @return Current ack randomize value
*/
coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session);
/**
* Send a ping message for the session.
* @param session The CoAP session.
*
* @return COAP_INVALID_TID if there is an error
*/
coap_tid_t coap_session_send_ping(coap_session_t *session);
#endif /* COAP_SESSION_H */

View File

@ -0,0 +1,162 @@
/*
* coap_time.h -- Clock Handling
*
* Copyright (C) 2010-2019 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.
* @{
*/
#if defined(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;
COAP_STATIC_INLINE void coap_ticks_impl(coap_tick_t *t) {
*t = sys_now();
}
COAP_STATIC_INLINE void coap_clock_init_impl(void) {
}
#define coap_clock_init coap_clock_init_impl
#define coap_ticks coap_ticks_impl
COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) {
return t / COAP_TICKS_PER_SECOND;
}
#elif defined(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
COAP_STATIC_INLINE void coap_clock_init(void) {
clock_init();
}
COAP_STATIC_INLINE void coap_ticks(coap_tick_t *t) {
*t = clock_time();
}
COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) {
return t / COAP_TICKS_PER_SECOND;
}
#else
#include <stdint.h>
/**
* This data type represents internal timer ticks with COAP_TICKS_PER_SECOND
* resolution.
*/
typedef uint64_t 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 int64_t coap_tick_diff_t;
/** Use ms resolution on POSIX systems */
#define COAP_TICKS_PER_SECOND ((coap_tick_t)(1000U))
/**
* 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);
/**
* Helper function that converts coap ticks to POSIX wallclock time in us.
*
* @param t Internal system ticks.
*
* @return The number of seconds that has passed since a specific reference
* point (seconds since epoch on POSIX).
*/
uint64_t coap_ticks_to_rt_us(coap_tick_t t);
/**
* Helper function that converts POSIX wallclock time in us to coap ticks.
*
* @param t POSIX time is us
*
* @return coap ticks
*/
coap_tick_t coap_ticks_from_rt_us(uint64_t t);
#endif
/**
* Returns @c 1 if and only if @p a is less than @p b where less is defined on a
* signed data type.
*/
COAP_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.
*/
COAP_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_ */

View File

@ -0,0 +1,96 @@
/*
* 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) || defined(_WIN32)
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdint.h>
#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
#ifndef HAVE_FLSLL
/* include this only if flsll() is not available */
extern int coap_flsll(long long i);
#else
#define coap_flsll(i) flsll(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. @p buf points to an input byte
* sequence of length @p length. Returns the decoded value.
*
* @param buf The input byte sequence to decode from
* @param length The length of the input byte sequence
*
* @return The decoded value
*/
unsigned int coap_decode_var_bytes(const uint8_t *buf, unsigned int length);
/**
* Encodes multiple-length byte sequences. @p buf points to an output buffer of
* sufficient length to store the encoded bytes. @p value is the value to
* encode.
* Returns the number of bytes used to encode @p value or 0 on error.
*
* @param buf The output buffer to decode into
* @param length The output buffer size to encode into (must be sufficient)
* @param value The value to encode into the buffer
*
* @return The number of bytes used to encode @p value or @c 0 on error.
*/
unsigned int coap_encode_var_safe(uint8_t *buf,
size_t length,
unsigned int value);
/**
* @deprecated Use coap_encode_var_safe() instead.
* Provided for backward compatibility. As @p value has a
* maximum value of 0xffffffff, and buf is usually defined as an array, it
* is unsafe to continue to use this variant if buf[] is less than buf[4].
*
* For example
* char buf[1],oops;
* ..
* coap_encode_var_bytes(buf, 0xfff);
* would cause oops to get overwritten. This error can only be found by code
* inspection.
* coap_encode_var_safe(buf, sizeof(buf), 0xfff);
* would catch this error at run-time and should be used instead.
*/
COAP_STATIC_INLINE COAP_DEPRECATED int
coap_encode_var_bytes(uint8_t *buf, unsigned int value
) {
return (int)coap_encode_var_safe(buf, sizeof(value), value);
}
#endif /* COAP_ENCODE_H_ */

View File

@ -0,0 +1,54 @@
/*
* 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 COAP_LIBCOAP_H_
#define COAP_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(_WIN32)
#pragma comment(lib,"Ws2_32.lib")
#include <ws2tcpip.h>
typedef SSIZE_T ssize_t;
typedef USHORT in_port_t;
#elif !defined (CONTIKI)
#include <netinet/in.h>
#include <sys/socket.h>
#endif /* CONTIKI */
#ifndef COAP_STATIC_INLINE
# if defined(__cplusplus)
# define COAP_STATIC_INLINE inline
# else
# if defined(_MSC_VER)
# define COAP_STATIC_INLINE static __inline
# else
# define COAP_STATIC_INLINE static inline
# endif
# endif
#endif
#ifndef COAP_DEPRECATED
# if defined(_MSC_VER)
# define COAP_DEPRECATED __declspec(deprecated)
# else
# define COAP_DEPRECATED __attribute__ ((deprecated))
# endif
#endif
void coap_startup(void);
void coap_cleanup(void);
#endif /* COAP_LIBCOAP_H_ */

View File

@ -0,0 +1,81 @@
/*
* 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_COAPSESSION
#define MEMP_NUM_COAPSESSION 2
#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
#ifndef MEMP_NUM_COAPOPTLIST
#define MEMP_NUM_COAPOPTLIST 1
#endif
#ifndef MEMP_LEN_COAPOPTLIST
#define MEMP_LEN_COAPOPTLIST 12
#endif
#ifndef MEMP_NUM_COAPSTRING
#define MEMP_NUM_COAPSTRING 10
#endif
#ifndef MEMP_LEN_COAPSTRING
#define MEMP_LEN_COAPSTRING 32
#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_SESSION, MEMP_NUM_COAPSESSION, sizeof(coap_session_t), "COAP_SESSION")
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")
LWIP_MEMPOOL(COAP_OPTLIST, MEMP_NUM_COAPOPTLIST, sizeof(coap_optlist_t)+MEMP_LEN_COAPOPTLIST, "COAP_OPTLIST")
LWIP_MEMPOOL(COAP_STRING, MEMP_NUM_COAPSTRING, sizeof(coap_string_t)+MEMP_LEN_COAPSTRING, "COAP_STRING")

View File

@ -0,0 +1,116 @@
/*
* 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,
#ifdef HAVE_LIBTINYDTLS
COAP_DTLS_SESSION,
#endif
COAP_SESSION,
COAP_OPTLIST,
} 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.
*/
COAP_STATIC_INLINE void *coap_malloc(size_t size) {
return coap_malloc_type(COAP_STRING, size);
}
/**
* Wrapper function to coap_free_type() for backwards compatibility.
*/
COAP_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) */
COAP_STATIC_INLINE void coap_memory_init(void) {}
/* It would be nice to check that size equals the size given at the memp
* declaration, but i currently don't see a standard way to check that without
* 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.
*/
COAP_STATIC_INLINE void *coap_malloc(size_t size) {
LWIP_ASSERT("coap_malloc must not be used in lwIP", 0);
}
COAP_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_ */

View File

@ -0,0 +1,746 @@
/*
* 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>
#ifndef _WIN32
#include <sys/time.h>
#endif
#include <time.h>
#ifdef WITH_LWIP
#include <lwip/ip_addr.h>
#endif
#include "coap_io.h"
#include "coap_dtls.h"
#include "coap_event.h"
#include "coap_time.h"
#include "option.h"
#include "pdu.h"
#include "prng.h"
#include "coap_session.h"
struct coap_queue_t;
/**
* Queue entry
*/
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_session_t *session; /**< the CoAP session */
coap_tid_t id; /**< CoAP transaction id */
coap_pdu_t *pdu; /**< the CoAP PDU to send */
} coap_queue_t;
/**
* Adds @p node to given @p queue, ordered by variable t in @p node.
*
* @param queue Queue to add to.
* @param node Node entry to add to Queue.
*
* @return @c 1 added to queue, @c 0 failure.
*/
int coap_insert_node(coap_queue_t **queue, coap_queue_t *node);
/**
* Destroys specified @p node.
*
* @param node Node entry to remove.
*
* @return @c 1 node deleted from queue, @c 0 failure.
*/
int coap_delete_node(coap_queue_t *node);
/**
* Removes all items from given @p queue and frees the allocated storage.
*
* @param queue The queue to delete.
*/
void coap_delete_all(coap_queue_t *queue);
/**
* Creates a new node suitable for adding to the CoAP sendqueue.
*
* @return New node entry, or @c NULL if failure.
*/
coap_queue_t *coap_new_node(void);
struct coap_resource_t;
struct coap_context_t;
#ifndef WITHOUT_ASYNC
struct coap_async_state_t;
#endif
/**
* Response handler that is used as call-back in coap_context_t.
*
* @param context CoAP session.
* @param session CoAP session.
* @param sent The PDU that was transmitted.
* @param received The PDU that was received.
* @param id CoAP transaction ID.
*/
typedef void (*coap_response_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *sent,
coap_pdu_t *received,
const coap_tid_t id);
/**
* Negative Acknowedge handler that is used as call-back in coap_context_t.
*
* @param context CoAP session.
* @param session CoAP session.
* @param sent The PDU that was transmitted.
* @param reason The reason for the NACK.
* @param id CoAP transaction ID.
*/
typedef void (*coap_nack_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *sent,
coap_nack_reason_t reason,
const coap_tid_t id);
/**
* Recieved Ping handler that is used as call-back in coap_context_t.
*
* @param context CoAP session.
* @param session CoAP session.
* @param received The PDU that was received.
* @param id CoAP transaction ID.
*/
typedef void (*coap_ping_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *received,
const coap_tid_t id);
/**
* Recieved Pong handler that is used as call-back in coap_context_t.
*
* @param context CoAP session.
* @param session CoAP session.
* @param received The PDU that was received.
* @param id CoAP transaction ID.
*/
typedef void (*coap_pong_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *received,
const coap_tid_t id);
/**
* 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 */
struct coap_resource_t *unknown_resource; /**< can be used for handling
unknown 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 endpoints used for listening */
coap_session_t *sessions; /**< client sessions */
#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 */
coap_response_handler_t response_handler;
coap_nack_handler_t nack_handler;
coap_ping_handler_t ping_handler;
coap_pong_handler_t pong_handler;
/**
* Callback function that is used to signal events to the
* application. This field is set by coap_set_event_handler().
*/
coap_event_handler_t handle_event;
ssize_t (*network_send)(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen);
ssize_t (*network_read)(coap_socket_t *sock, struct coap_packet_t *packet);
size_t(*get_client_psk)(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len);
size_t(*get_server_psk)(const coap_session_t *session, const uint8_t *identity, size_t identity_len, uint8_t *psk, size_t max_psk_len);
size_t(*get_server_hint)(const coap_session_t *session, uint8_t *hint, size_t max_hint_len);
void *dtls_context;
uint8_t *psk_hint;
size_t psk_hint_len;
uint8_t *psk_key;
size_t psk_key_len;
unsigned int session_timeout; /**< Number of seconds of inactivity after which an unused session will be closed. 0 means use default. */
unsigned int max_idle_sessions; /**< Maximum number of simultaneous unused sessions per endpoint. 0 means no maximum. */
unsigned int max_handshake_sessions; /**< Maximum number of simultaneous negotating sessions per endpoint. 0 means use default. */
unsigned int ping_timeout; /**< Minimum inactivity time before sending a ping message. 0 means disabled. */
unsigned int csm_timeout; /**< Timeout for waiting for a CSM from the remote side. 0 means disabled. */
void *app; /**< application-specific data */
} 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.
*/
COAP_STATIC_INLINE void
coap_register_response_handler(coap_context_t *context,
coap_response_handler_t handler) {
context->response_handler = handler;
}
/**
* Registers a new message handler that is called whenever a confirmable
* message (request or response) is dropped after all retries have been
* exhausted, or a rst message was received, or a network or TLS level
* event was received that indicates delivering the message is not possible.
*
* @param context The context to register the handler for.
* @param handler The nack handler to register.
*/
COAP_STATIC_INLINE void
coap_register_nack_handler(coap_context_t *context,
coap_nack_handler_t handler) {
context->nack_handler = handler;
}
/**
* Registers a new message handler that is called whenever a CoAP Ping
* message is received.
*
* @param context The context to register the handler for.
* @param handler The ping handler to register.
*/
COAP_STATIC_INLINE void
coap_register_ping_handler(coap_context_t *context,
coap_ping_handler_t handler) {
context->ping_handler = handler;
}
/**
* Registers a new message handler that is called whenever a CoAP Pong
* message is received.
*
* @param context The context to register the handler for.
* @param handler The pong handler to register.
*/
COAP_STATIC_INLINE void
coap_register_pong_handler(coap_context_t *context,
coap_pong_handler_t handler) {
context->pong_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.
*/
COAP_STATIC_INLINE void
coap_register_option(coap_context_t *ctx, uint16_t 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);
/**
* Set the context's default PSK hint and/or key for a server.
*
* @param context The current coap_context_t object.
* @param hint The default PSK server hint sent to a client. If @p NULL, PSK
* authentication is disabled. Empty string is a valid hint.
* @param key The default PSK key. If @p NULL, PSK authentication will fail.
* @param key_len The default PSK key's length. If @p 0, PSK authentication will
* fail.
*
* @return @c 1 if successful, else @c 0.
*/
int coap_context_set_psk( coap_context_t *context, const char *hint,
const uint8_t *key, size_t key_len );
/**
* Set the context's default PKI information for a server.
*
* @param context The current coap_context_t object.
* @param setup_data If @p NULL, PKI authentication will fail. Certificate
* information required.
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_context_set_pki(coap_context_t *context,
coap_dtls_pki_t *setup_data);
/**
* Set the context's default Root CA information for a client or server.
*
* @param context The current coap_context_t object.
* @param ca_file If not @p NULL, is the full path name of a PEM encoded
* file containing all the Root CAs to be used.
* @param ca_dir If not @p NULL, points to a directory containing PEM
* encoded files containing all the Root CAs to be used.
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_context_set_pki_root_cas(coap_context_t *context,
const char *ca_file,
const char *ca_dir);
/**
* Set the context keepalive timer for sessions.
* A keepalive message will be sent after if a session has been inactive,
* i.e. no packet sent or received, for the given number of seconds.
* For reliable protocols, a PING message will be sent. If a PONG has not
* been received before the next PING is due to be sent, the session will
* considered as disconnected.
*
* @param context The coap_context_t object.
* @param seconds Number of seconds for the inactivity timer, or zero
* to disable CoAP-level keepalive messages.
*
* @return 1 if successful, else 0
*/
void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds);
/**
* Returns a new message id and updates @p session->tx_mid accordingly. The
* message id is returned in network byte order to make it easier to read in
* tracing tools.
*
* @param session The current coap_session_t object.
*
* @return Incremented message id in network byte order.
*/
COAP_STATIC_INLINE uint16_t
coap_new_message_id(coap_session_t *session) {
return ++session->tx_mid;
}
/**
* 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.
*
* @param context The current coap_context_t object to free off.
*/
void coap_free_context(coap_context_t *context);
/**
* Stores @p data with the given CoAP context. This function
* overwrites any value that has previously been stored with @p
* context.
*
* @param context The CoAP context.
* @param data The data to store with wih the context. Note that this data
* must be valid during the lifetime of @p context.
*/
void coap_set_app_data(coap_context_t *context, void *data);
/**
* Returns any application-specific data that has been stored with @p
* context using the function coap_set_app_data(). This function will
* return @c NULL if no data has been stored.
*
* @param context The CoAP context.
*
* @return The data previously stored or @c NULL if not data stored.
*/
void *coap_get_app_data(const coap_context_t *context);
/**
* 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 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 session The CoAP session.
* @param request The original request to respond to.
* @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_session_t *session,
coap_pdu_t *request,
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 session The CoAP session.
* @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_session_t *session, 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 session The CoAP session.
* @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_session_t *session, 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 session The CoAP session.
* @param request The request to be reset.
*
* @return The transaction id if RST was sent or @c
* COAP_INVALID_TID on error.
*/
COAP_STATIC_INLINE coap_tid_t
coap_send_rst(coap_session_t *session, coap_pdu_t *request) {
return coap_send_message_type(session, request, COAP_MESSAGE_RST);
}
/**
* Sends a CoAP message to given peer. The memory that is
* allocated by pdu will be released by coap_send().
* The caller must not use the pdu after calling coap_send().
*
* @param session The CoAP session.
* @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_session_t *session, coap_pdu_t *pdu );
/**
* Handles retransmissions of confirmable messages
*
* @param context The CoAP context.
* @param node The node to retransmit.
*
* @return The message id of the sent message or @c
* COAP_INVALID_TID on error.
*/
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node);
/**
* For applications with their own message loop, send all pending retransmits and
* return the list of sockets with events to wait for and the next timeout
* The application should call coap_read, then coap_write again when any condition below is true:
* - data is available on any of the sockets with the COAP_SOCKET_WANT_READ
* - an incoming connection is pending in the listen queue and the COAP_SOCKET_WANT_ACCEPT flag is set
* - at least some data can be written without blocking on any of the sockets with the COAP_SOCKET_WANT_WRITE flag set
* - a connection event occured (success or failure) and the COAP_SOCKET_WANT_CONNECT flag is set
* - the timeout has expired
* Before calling coap_read or coap_write again, the application should position COAP_SOCKET_CAN_READ and COAP_SOCKET_CAN_WRITE flags as applicable.
*
* @param ctx The CoAP context
* @param sockets array of socket descriptors, filled on output
* @param max_sockets size of socket array.
* @param num_sockets pointer to the number of valid entries in the socket arrays on output
* @param now Current time.
*
* @return timeout as maxmimum number of milliseconds that the application should wait for network events or 0 if the application should wait forever.
*/
unsigned int
coap_write(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now
);
/**
* For applications with their own message loop, reads all data from the network.
*
* @param ctx The CoAP context
* @param now Current time
*/
void coap_read(coap_context_t *ctx, coap_tick_t now);
/**
* The main message processing loop.
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new messages before returning. If zero the call will block until at least one packet is sent or received.
*
* @return number of milliseconds spent or @c -1 if there was an error
*/
int coap_run_once( coap_context_t *ctx, unsigned int timeout_ms );
/**
* Parses and interprets a CoAP datagram with context @p ctx. This function
* returns @c 0 if the datagram was handled, or a value less than zero on
* error.
*
* @param ctx The current CoAP context.
* @param session The current CoAP session.
* @param data The received packet'd data.
* @param data_len The received packet'd data length.
*
* @return @c 0 if message was handled successfully, or less than zero on
* error.
*/
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *data, size_t data_len);
/**
* Invokes the event handler of @p context for the given @p event and
* @p data.
*
* @param context The CoAP context whose event handler is to be called.
* @param event The event to deliver.
* @param session The session related to @p event.
* @return The result from the associated event handler or 0 if none was
* registered.
*/
int coap_handle_event(coap_context_t *context,
coap_event_t event,
coap_session_t *session);
/**
* 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 session The session to look for.
* @param id The transaction 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_session_t *session,
coap_tid_t id,
coap_queue_t **node);
coap_tid_t
coap_wait_ack( coap_context_t *context, coap_session_t *session,
coap_queue_t *node);
/**
* Retrieves transaction from the queue.
*
* @param queue The transaction queue to be searched.
* @param session The session to find.
* @param id The transaction id to find.
*
* @return A pointer to the transaction object or @c NULL if not found.
*/
coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_session_t *session, coap_tid_t id);
/**
* Cancels all outstanding messages for session @p session that have the specified
* token.
*
* @param context The context in use.
* @param session Session 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,
coap_session_t *session,
const uint8_t *token,
size_t token_length);
/**
* Cancels all outstanding messages for session @p session.
*
* @param context The context in use.
* @param session Session of the messages to remove.
* @param reason The reasion for the session cancellation
*/
void
coap_cancel_session_messages(coap_context_t *context,
coap_session_t *session,
coap_nack_reason_t reason);
/**
* Dispatches the PDUs from the receive queue in given context.
*/
void coap_dispatch(coap_context_t *context, coap_session_t *session,
coap_pdu_t *pdu);
/**
* 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 either sent with coap_sent() or released by coap_delete_pdu().
*
* @param context The current coap context to use.
* @param session The CoAP session.
* @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_session_t *session,
coap_pdu_t *request);
/**
* Calculates the initial timeout based on the session CoAP transmission
* parameters 'ack_timeout', 'ack_random_factor', and COAP_TICKS_PER_SECOND.
* The calculation requires 'ack_timeout' and 'ack_random_factor' to be in
* Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r
* is interpreted as the fractional part of a Q0.MAX_BITS random value.
*
* @param session session timeout is associated with
* @param r random value as fractional part of a Q0.MAX_BITS fixed point
* value
* @return COAP_TICKS_PER_SECOND * 'ack_timeout' *
* (1 + ('ack_random_factor' - 1) * r)
*/
unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r);
/**
* Function interface for joining a multicast group for listening
*
* @param ctx The current context
* @param groupname The name of the group that is to be joined for listening
*
* @return 0 on success, -1 on error
*/
int
coap_join_mcast_group(coap_context_t *ctx, const char *groupname);
#endif /* COAP_NET_H_ */

View File

@ -0,0 +1,461 @@
/*
* 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 uint8_t coap_opt_t;
#define PCHAR(p) ((coap_opt_t *)(p))
/**
* Representation of CoAP options.
*/
typedef struct {
uint16_t delta;
size_t length;
const uint8_t *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);
/**
* @defgroup opt_filter Option Filters
* API functions for access 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.
*/
COAP_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, uint16_t 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, uint16_t 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(coap_opt_filter_t filter, uint16_t 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.
*/
COAP_STATIC_INLINE int
coap_option_setb(coap_opt_filter_t filter, uint16_t 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.
*/
COAP_STATIC_INLINE int
coap_option_clrb(coap_opt_filter_t filter, uint16_t 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.
*/
COAP_STATIC_INLINE int
coap_option_getb(coap_opt_filter_t filter, uint16_t 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 */
uint16_t 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(const 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,
uint16_t 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,
uint16_t delta,
size_t length);
/**
* Compute storage bytes needed for an option with given @p delta and
* @p length
*
* @param delta The option delta.
* @param length The option length.
*
* @return The number of bytes required to encode this option.
*/
size_t coap_opt_encode_size(uint16_t 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,
uint16_t delta,
const uint8_t *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.
*/
uint16_t coap_opt_delta(const coap_opt_t *opt);
/**
* 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.
*/
uint16_t coap_opt_length(const coap_opt_t *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.
*/
const uint8_t *coap_opt_value(const coap_opt_t *opt);
/** @} */
/**
* Representation of chained list of CoAP options to install.
*
* @code
* coap_optlist_t *optlist_chain = NULL;
* coap_pdu_t *pdu = coap_new_pdu(session);
*
* ... other set up code ...
* coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_OBSERVE,
* COAP_OBSERVE_ESTABLISH, NULL));
*
* coap_add_optlist_pdu(pdu, &optlist_chain);
* ... other code ...
* coap_delete_optlist(optlist_chain);
* @endcode
*/
typedef struct coap_optlist_t {
struct coap_optlist_t *next; /**< next entry in the optlist chain */
uint16_t number; /**< the option number (no delta coding) */
size_t length; /**< the option value length */
uint8_t *data; /**< the option data */
} coap_optlist_t;
/**
* Create a new optlist entry.
*
* @param number The option number (COAP_OPTION_*)
* @param length The option length
* @param data The option value data
*
* @return A pointer to the new optlist entry, or @c NULL if error
*/
coap_optlist_t *coap_new_optlist(uint16_t number,
size_t length,
const uint8_t *data);
/**
* The current optlist of @p optlist_chain is first sorted (as per RFC7272
* ordering requirements) and then added to the @p pdu.
*
* @param pdu The pdu to add the options to from the chain list
* @param optlist_chain The chained list of optlist to add to the pdu
*
* @return @c 1 if succesful or @c 0 if failure;
*/
int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t** optlist_chain);
/**
* Adds @p optlist to the given @p optlist_chain. The optlist_chain variable
* be set to NULL before the initial call to coap_insert_optlist().
* The optlist_chain will need to be deleted using coap_delete_optlist()
* when no longer required.
*
* @param optlist_chain The chain to add optlist to
* @param optlist The optlist to add to the queue
*
* @return @c 1 if successful, @c 0 otherwise.
*/
int coap_insert_optlist(coap_optlist_t **optlist_chain,
coap_optlist_t *optlist);
/**
* Removes all entries from the @p optlist_chain, freeing off their
* memory usage.
*
* @param optlist_chain The optlist chain to remove all the entries from
*/
void coap_delete_optlist(coap_optlist_t *optlist_chain);
#endif /* COAP_OPTION_H_ */

View File

@ -0,0 +1,543 @@
/*
* 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"
struct coap_session_t;
#ifdef WITH_LWIP
#include <lwip/pbuf.h>
#endif
#include <stdint.h>
#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP/TCP port */
#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP/TCP port for secure transmission */
#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */
#ifndef COAP_DEFAULT_MTU
#define COAP_DEFAULT_MTU 1152
#endif /* COAP_DEFAULT_MTU */
/* TCP Message format constants, do not modify */
#define COAP_MESSAGE_SIZE_OFFSET_TCP8 13
#define COAP_MESSAGE_SIZE_OFFSET_TCP16 269 /* 13 + 256 */
#define COAP_MESSAGE_SIZE_OFFSET_TCP32 65805 /* 269 + 65536 */
/* Derived message size limits */
#define COAP_MAX_MESSAGE_SIZE_TCP0 (COAP_MESSAGE_SIZE_OFFSET_TCP8-1) /* 12 */
#define COAP_MAX_MESSAGE_SIZE_TCP8 (COAP_MESSAGE_SIZE_OFFSET_TCP16-1) /* 268 */
#define COAP_MAX_MESSAGE_SIZE_TCP16 (COAP_MESSAGE_SIZE_OFFSET_TCP32-1) /* 65804 */
#define COAP_MAX_MESSAGE_SIZE_TCP32 (COAP_MESSAGE_SIZE_OFFSET_TCP32+0xFFFFFFFF)
#ifndef COAP_DEFAULT_MAX_PDU_RX_SIZE
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+4)
#else
/* 8 MiB max-message-size plus some space for options */
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8*1024*1024+256)
#endif
#endif /* COAP_DEFAULT_MAX_PDU_RX_SIZE */
#ifndef COAP_DEBUG_BUF_SIZE
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
#define COAP_DEBUG_BUF_SIZE 128
#else /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
/* 1024 derived from RFC7252 4.6. Message Size max payload */
#define COAP_DEBUG_BUF_SIZE (8 + 1024 * 2)
#endif /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
#endif /* COAP_DEBUG_BUF_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"
/* 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
#define COAP_REQUEST_FETCH 5 /* RFC 8132 */
#define COAP_REQUEST_PATCH 6 /* RFC 8132 */
#define COAP_REQUEST_IPATCH 7 /* RFC 8132 */
/*
* CoAP option types (be sure to update coap_option_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_SIZE2 28 /* E, uint, 0-4 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.
*/
const 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 */
#define COAP_SIGNALING_CODE(N) (((N)/100 << 5) | (N)%100)
#define COAP_SIGNALING_CSM COAP_SIGNALING_CODE(701)
#define COAP_SIGNALING_PING COAP_SIGNALING_CODE(702)
#define COAP_SIGNALING_PONG COAP_SIGNALING_CODE(703)
#define COAP_SIGNALING_RELEASE COAP_SIGNALING_CODE(704)
#define COAP_SIGNALING_ABORT COAP_SIGNALING_CODE(705)
/* Applies to COAP_SIGNALING_CSM */
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE 2
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER 4
/* Applies to COAP_SIGNALING_PING / COAP_SIGNALING_PONG */
#define COAP_SIGNALING_OPTION_CUSTODY 2
/* Applies to COAP_SIGNALING_RELEASE */
#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS 2
#define COAP_SIGNALING_OPTION_HOLD_OFF 4
/* Applies to COAP_SIGNALING_ABORT */
#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION 2
/* 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 */
/* Content formats from RFC 8152 */
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN 98 /* application/cose; cose-type="cose-sign" */
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN1 18 /* application/cose; cose-type="cose-sign1" */
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT 96 /* application/cose; cose-type="cose-encrypt" */
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0 16 /* application/cose; cose-type="cose-encrypt0" */
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC 97 /* application/cose; cose-type="cose-mac" */
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC0 17 /* application/cose; cose-type="cose-mac0" */
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY 101 /* application/cose-key */
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET 102 /* application/cose-key-set */
/* Content formats from RFC 8428 */
#define COAP_MEDIATYPE_APPLICATION_SENML_JSON 110 /* application/senml+json */
#define COAP_MEDIATYPE_APPLICATION_SENSML_JSON 111 /* application/sensml+json */
#define COAP_MEDIATYPE_APPLICATION_SENML_CBOR 112 /* application/senml+cbor */
#define COAP_MEDIATYPE_APPLICATION_SENSML_CBOR 113 /* application/sensml+cbor */
#define COAP_MEDIATYPE_APPLICATION_SENML_EXI 114 /* application/senml-exi */
#define COAP_MEDIATYPE_APPLICATION_SENSML_EXI 115 /* application/sensml-exi */
#define COAP_MEDIATYPE_APPLICATION_SENML_XML 310 /* application/senml+xml */
#define COAP_MEDIATYPE_APPLICATION_SENSML_XML 311 /* application/sensml+xml */
/* 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
#define COAP_PDU_DELAYED -3
#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 */
/**
* @deprecated Use coap_optlist_t instead.
*
* 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).
*/
COAP_DEPRECATED typedef struct {
uint16_t 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))
/**
* structure for CoAP PDUs
* token, if any, follows the fixed size header, then options until
* payload marker (0xff), then the payload if stored inline.
* Memory layout is:
* <---header--->|<---token---><---options--->0xff<---payload--->
* header is addressed with a negative offset to token, its maximum size is
* max_hdr_size.
* options starts at token + token_length
* payload starts at data, its length is used_size - (data - token)
*/
typedef struct coap_pdu_t {
uint8_t type; /**< message type */
uint8_t code; /**< request method (value 1--10) or response code (value 40-255) */
uint8_t max_hdr_size; /**< space reserved for protocol-specific header */
uint8_t hdr_size; /**< actaul size used for protocol-specific header */
uint8_t token_length; /**< length of Token */
uint16_t tid; /**< transaction id, if any, in regular host byte order */
uint16_t max_delta; /**< highest option number */
size_t alloc_size; /**< allocated storage for token, options and payload */
size_t used_size; /**< used bytes of storage for token, options and payload */
size_t max_size; /**< maximum size for token, options and payload, or zero for variable size pdu */
uint8_t *token; /**< first byte of token, if any, or options */
uint8_t *data; /**< first byte of payload, if any */
#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;
#define COAP_PDU_IS_EMPTY(pdu) ((pdu)->code == 0)
#define COAP_PDU_IS_REQUEST(pdu) (!COAP_PDU_IS_EMPTY(pdu) && (pdu)->code < 32)
#define COAP_PDU_IS_RESPONSE(pdu) ((pdu)->code >= 64 && (pdu)->code < 224)
#define COAP_PDU_IS_SIGNALING(pdu) ((pdu)->code >= 224)
#define COAP_PDU_MAX_UDP_HEADER_SIZE 4
#define COAP_PDU_MAX_TCP_HEADER_SIZE 6
#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
typedef uint8_t coap_proto_t;
/**
* coap_proto_t values
*/
#define COAP_PROTO_NONE 0
#define COAP_PROTO_UDP 1
#define COAP_PROTO_DTLS 2
#define COAP_PROTO_TCP 3
#define COAP_PROTO_TLS 4
/**
* Creates a new CoAP PDU with at least enough storage space for the given
* @p size maximum message size. 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() if coap_send() is not
* called.
*
* @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 tid The transcation id to set or 0 if unknown / not applicable.
* @param size The maximum allowed number of byte for the message.
* @return A pointer to the new PDU object or @c NULL on error.
*/
coap_pdu_t *
coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size);
/**
* Dynamically grows the size of @p pdu to @p new_size. The new size
* must not exceed the PDU's configure maximum size. On success, this
* function returns 1, otherwise 0.
*
* @param pdu The PDU to resize.
* @param new_size The new size in bytes.
* @return 1 if the operation succeeded, 0 otherwise.
*/
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size);
/**
* Clears any contents from @p pdu and resets @c used_size,
* 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.
*/
coap_pdu_t *coap_new_pdu(const struct coap_session_t *session);
/**
* Dispose of an CoAP PDU and frees associated storage.
* Not that in general you should not call this function directly.
* When a PDU is sent with coap_send(), coap_delete_pdu() will be
* called automatically for you.
*/
void coap_delete_pdu(coap_pdu_t *);
/**
* Interprets @p data to determine the number of bytes in the header.
* This function returns @c 0 on error or a number greater than zero on success.
*
* @param proto Session's protocol
* @param data The first byte of raw data to parse as CoAP PDU.
*
* @return A value greater than zero on success or @c 0 on error.
*/
size_t coap_pdu_parse_header_size(coap_proto_t proto,
const uint8_t *data);
/**
* Parses @p data to extract the message size.
* @p length must be at least coap_pdu_parse_header_size(proto, data).
* This function returns @c 0 on error or a number greater than zero on success.
*
* @param proto Session's protocol
* @param data The raw data to parse as CoAP PDU.
* @param length The actual size of @p data.
*
* @return A value greater than zero on success or @c 0 on error.
*/
size_t coap_pdu_parse_size(coap_proto_t proto,
const uint8_t *data,
size_t length);
/**
* Decode the protocol specific header for the specified PDU.
* @param pdu A newly received PDU.
* @param proto The target wire protocol.
* @return 1 for success or 0 on error.
*/
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto);
/**
* Verify consistency in the given CoAP PDU structure and locate the data.
* This function returns @c 0 on error or a number greater than zero on
* success.
* This function only parses the token and options, up to the payload start
* marker.
*
* @param pdu The PDU structure to.
*
* @return 1 on success or @c 0 on error.
*/
int coap_pdu_parse_opt(coap_pdu_t *pdu);
/**
* Parses @p data into the CoAP PDU structure given in @p result.
* The target pdu must be large enough to
* This function returns @c 0 on error or a number greater than zero on success.
*
* @param proto Session's protocol
* @param data The raw data to parse as CoAP PDU.
* @param length The actual size of @p data.
* @param pdu The PDU structure to fill. Note that the structure must
* provide space to hold at least the token and options
* part of the message.
*
* @return 1 on success or @c 0 on error.
*/
int coap_pdu_parse(coap_proto_t proto,
const uint8_t *data,
size_t length,
coap_pdu_t *pdu);
/**
* 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 function
* 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 uint8_t *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,
uint16_t type,
size_t len,
const uint8_t *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.
*/
uint8_t *coap_add_option_later(coap_pdu_t *pdu,
uint16_t type,
size_t 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,
size_t len,
const uint8_t *data);
/**
* Adds given data to the pdu that is passed as first parameter but does not
* copyt it. Note that the PDU's data is destroyed by coap_add_option().
* coap_add_data() must be have been called once for this PDU, otherwise the
* result is undefined.
* The actual data must be copied at the returned location.
*/
uint8_t *coap_add_data_after(coap_pdu_t *pdu, size_t len);
/**
* 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(const coap_pdu_t *pdu,
size_t *len,
uint8_t **data);
/**
* Compose the protocol specific header for the specified PDU.
* @param pdu A newly composed PDU.
* @param proto The target wire protocol.
* @return Number of header bytes prepended before pdu->token or 0 on error.
*/
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto);
#endif /* COAP_PDU_H_ */

View File

@ -0,0 +1,127 @@
/*
* 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
* API functions for gerating pseudo random numbers
* @{
*/
#if defined(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.
*/
COAP_STATIC_INLINE int
contiki_prng_impl(unsigned char *buf, size_t len) {
uint16_t 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((uint16_t)(Value))
#elif defined(WITH_LWIP) && defined(LWIP_RAND)
COAP_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)
#elif defined(_WIN32)
#define prng_init(Value)
errno_t __cdecl rand_s( _Out_ unsigned int* _RandomValue );
/**
* 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.
*/
COAP_STATIC_INLINE int
coap_prng_impl( unsigned char *buf, size_t len ) {
while ( len != 0 ) {
uint32_t r = 0;
size_t i;
if ( rand_s( &r ) != 0 )
return 0;
for ( i = 0; i < len && i < 4; i++ ) {
*buf++ = (uint8_t)r;
r >>= 8;
}
len -= i;
}
return 1;
}
#else
#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.
*/
COAP_STATIC_INLINE int
coap_prng_impl( unsigned char *buf, size_t len ) {
while ( len-- )
*buf++ = rand() & 0xFF;
return 1;
}
#endif
#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_ */

View File

@ -0,0 +1,524 @@
/*
* 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 */
#include "uthash.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 *,
coap_session_t *,
coap_pdu_t *,
coap_binary_t * /* token */,
coap_string_t * /* query string */,
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;
coap_str_const_t *name;
coap_str_const_t *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 */
unsigned int is_unknown:1; /**< resource created for unknown handler */
/**
* Used to store handlers for the seven coap methods @c GET, @c POST, @c PUT,
* @c DELETE, @c FETCH, @c PATCH and @c IPATCH.
* 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[7];
UT_hash_handle hh;
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 Path for this resource. This field will point into static
* or allocated memory which must remain there for the duration of the
* resource.
*/
coap_str_const_t *uri_path; /**< the key used for hash lookup for this resource */
int flags;
/**
* The next value for the Observe option. This field must be increased each
* time the resource changes. Only the lower 24 bits are sent.
*/
unsigned int observe;
/**
* This pointer is under user control. It can be used to store context for
* the coap handler.
*/
void *user_data;
} coap_resource_t;
/**
* Creates a new resource object and initializes the link field to the string
* @p uri_path. This function returns the new coap_resource_t object.
*
* If the string is going to be freed off by coap_delete_resource() when
* COAP_RESOURCE_FLAGS_RELEASE_URI is set in @p flags, then either the 's'
* variable of coap_str_const_t has to point to constant text, or point to data
* within the allocated coap_str_const_t parameter.
*
* @param uri_path The string URI path of the new resource.
* @param flags Flags for memory management (in particular release of
* memory). Possible values:@n
*
* COAP_RESOURCE_FLAGS_RELEASE_URI
* If this flag is set, the URI passed to
* coap_resource_init() is free'd by
* coap_delete_resource()@n
*
* COAP_RESOURCE_FLAGS_NOTIFY_CON
* If this flag is set, coap-observe notifications
* will be sent confirmable by default.@n
*
* COAP_RESOURCE_FLAGS_NOTIFY_NON (default)
* If this flag is set, coap-observe notifications
* will be sent non-confirmable by default.@n
*
* If flags is set to 0 then the
* COAP_RESOURCE_FLAGS_NOTIFY_NON is considered.
*
* @return A pointer to the new object or @c NULL on error.
*/
coap_resource_t *coap_resource_init(coap_str_const_t *uri_path,
int flags);
/**
* Creates a new resource object for the unknown resource handler with support
* for PUT.
*
* In the same way that additional handlers can be added to the resource
* created by coap_resource_init() by using coap_register_handler(), POST,
* GET, DELETE etc. handlers can be added to this resource. It is the
* responsibility of the application to manage the unknown resources by either
* creating new resources with coap_resource_init() (which should have a
* DELETE handler specified for the resource removal) or by maintaining an
* active resource list.
*
* Note: There can only be one unknown resource handler per context - attaching
* a new one overrides the previous definition.
*
* Note: It is not possible to observe the unknown resource with a GET request
* - a separate resource needs to be reated by the PUT (or POST) handler,
* and make that resource observable.
*
* This function returns the new coap_resource_t object.
*
* @param put_handler The PUT handler to register with @p resource for
* unknown Uri-Path.
*
* @return A pointer to the new object or @c NULL on error.
*/
coap_resource_t *coap_resource_unknown_init(coap_method_handler_t put_handler);
/**
* Sets the notification message type of resource @p resource to given
* @p mode
* @param resource The resource to update.
* @param mode Must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON
* or @c COAP_RESOURCE_FLAGS_NOTIFY_CON.
*/
COAP_STATIC_INLINE void
coap_resource_set_mode(coap_resource_t *resource, int mode) {
resource->flags = (resource->flags &
~(COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON)) |
(mode & (COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON));
}
/**
* Sets the user_data. The user_data is exclusively used by the library-user
* and can be used as context in the handler functions.
*
* @param r Resource to attach the data to
* @param data Data to attach to the user_data field. This pointer is only used for
* storage, the data remains under user control
*/
COAP_STATIC_INLINE void
coap_resource_set_userdata(coap_resource_t *r, void *data) {
r->user_data = data;
}
/**
* Gets the user_data. The user_data is exclusively used by the library-user
* and can be used as context in the handler functions.
*
* @param r Resource to retrieve the user_darta from
*
* @return The user_data pointer
*/
COAP_STATIC_INLINE void *
coap_resource_get_userdata(coap_resource_t *r) {
return r->user_data;
}
/**
* Registers the given @p resource for @p context. The resource must have been
* created by coap_resource_init() or coap_resource_unknown_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 resource. The storage allocated for that
* resource is freed, and removed from the context.
*
* @param context The context where the resources are stored.
* @param resource 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_resource_t *resource);
/**
* 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
* attribute's coap_str_const_ fields will point to @p name and @p value the
* caller must ensure that these pointers are valid during the
* attribute's lifetime.
* If the @p name and/or @p value string is going to be freed off at attribute
* removal time by the setting of COAP_ATTR_FLAGS_RELEASE_NAME or
* COAP_ATTR_FLAGS_RELEASE_VALUE in @p flags, then either the 's'
* variable of coap_str_const_t has to point to constant text, or point to data
* within the allocated coap_str_const_t parameter.
*
* @param resource The resource to register the attribute with.
* @param name The attribute's name as a string.
* @param value The attribute's value as a string or @c NULL if none.
* @param flags Flags for memory management (in particular release of
* memory). Possible values:@n
*
* COAP_ATTR_FLAGS_RELEASE_NAME
* If this flag is set, the name passed to
* coap_add_attr_release() is free'd
* when the attribute is deleted@n
*
* COAP_ATTR_FLAGS_RELEASE_VALUE
* If this flag is set, the value passed to
* coap_add_attr_release() is free'd
* when the attribute is deleted@n
*
* @return A pointer to the new attribute or @c NULL on error.
*/
coap_attr_t *coap_add_attr(coap_resource_t *resource,
coap_str_const_t *name,
coap_str_const_t *value,
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 as a string.
* @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,
coap_str_const_t *name);
/**
* Deletes an attribute.
* Note: This is for internal use only, as it is not deleted from its chain.
*
* @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.
*/
void coap_register_handler(coap_resource_t *resource,
unsigned char method,
coap_method_handler_t handler);
/**
* Returns the resource identified by the unique string @p uri_path. If no
* resource was found, this function returns @c NULL.
*
* @param context The context to look for this resource.
* @param uri_path The unique string uri of the resource.
*
* @return A pointer to the resource or @c NULL if not found.
*/
coap_resource_t *coap_get_resource_from_uri_path(coap_context_t *context,
coap_str_const_t *uri_path);
/**
* @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 session The observer's session
* @param token The token that identifies this subscription.
* @param query The query string, if any. subscription will
take ownership of the string.
* @param has_block2 If Option Block2 defined.
* @param block2 Contents of Block2 if Block 2 defined.
* @return A pointer to the added/updated subscription
* information or @c NULL on error.
*/
coap_subscription_t *coap_add_observer(coap_resource_t *resource,
coap_session_t *session,
const coap_binary_t *token,
coap_string_t *query,
int has_block2,
coap_block_t block2);
/**
* Returns a subscription object for given @p peer.
*
* @param resource The observed resource.
* @param session The observer's session
* @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,
coap_session_t *session,
const coap_binary_t *token);
/**
* Marks an observer as alive.
*
* @param context The CoAP context to use.
* @param session The observer's session
* @param token The corresponding token that has been used for the
* subscription.
*/
void coap_touch_observer(coap_context_t *context,
coap_session_t *session,
const coap_binary_t *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 session The observer's session.
* @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,
coap_session_t *session,
const coap_binary_t *token);
/**
* Removes any subscription for @p session and releases the allocated storage.
*
* @param context The CoAP context to use.
* @param session The observer's session.
*/
void coap_delete_observers(coap_context_t *context, coap_session_t *session);
/**
* Checks for all known resources, if they are dirty and notifies subscribed
* observers.
*/
void coap_check_notify(coap_context_t *context);
#define RESOURCES_ADD(r, obj) \
HASH_ADD(hh, (r), uri_path->s[0], (obj)->uri_path->length, (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)->s, (k)->length, (res)); \
}
/** @} */
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 *,
coap_session_t *,
const coap_binary_t *);
/**
* Set whether a @p resource is observable. If the resource is observable
* and the client has set the COAP_OPTION_OBSERVE in a request packet, then
* whenever the state of the resource changes (a call to
* coap_resource_trigger_observe()), an Observer response will get sent.
*
* @param resource The CoAP resource to use.
* @param mode @c 1 if Observable is to be set, @c 0 otherwise.
*
*/
COAP_STATIC_INLINE void
coap_resource_set_get_observable(coap_resource_t *resource, int mode) {
resource->observable = mode ? 1 : 0;
}
/**
* Initiate the sending of an Observe packet for all observers of @p resource,
* optionally matching @p query if not NULL
*
* @param resource The CoAP resource to use.
* @param query The Query to match against or NULL
*
* @return @c 1 if the Observe has been triggered, @c 0 otherwise.
*/
int
coap_resource_notify_observers(coap_resource_t *resource,
const coap_string_t *query);
/**
* Get the UriPath from a @p resource.
*
* @param resource The CoAP resource to check.
*
* @return The UriPath if it exists or @c NULL otherwise.
*/
COAP_STATIC_INLINE coap_str_const_t*
coap_resource_get_uri_path(coap_resource_t *resource) {
if (resource)
return resource->uri_path;
return NULL;
}
/**
* @deprecated use coap_resource_notify_observers() instead.
*/
COAP_DEPRECATED int
coap_resource_set_dirty(coap_resource_t *r,
const coap_string_t *query);
#endif /* COAP_RESOURCE_H_ */

View File

@ -0,0 +1,121 @@
/*
* 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>
/**
* @defgroup string String handling support
* API functions for handling strings
* @{
*/
/**
* Coap string data definition
*/
typedef struct coap_string_t {
size_t length; /**< length of string */
uint8_t *s; /**< string data */
} coap_string_t;
/**
* Coap string data definition with const data
*/
typedef struct coap_str_const_t {
size_t length; /**< length of string */
const uint8_t *s; /**< string data */
} coap_str_const_t;
#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); }
/**
* Coap binary data definition
*/
typedef struct coap_binary_t {
size_t length; /**< length of binary data */
uint8_t *s; /**< binary data */
} coap_binary_t;
/**
* Returns a new string object with at least size+1 bytes storage allocated.
* The string must be released using coap_delete_string().
*
* @param size The size to allocate for the binary string data.
*
* @return A pointer to the new object or @c NULL on error.
*/
coap_string_t *coap_new_string(size_t size);
/**
* Deletes the given string and releases any memory allocated.
*
* @param string The string to free off.
*/
void coap_delete_string(coap_string_t *string);
/**
* Returns a new const string object with at least size+1 bytes storage
* allocated, and the provided data copied into the string object.
* The string must be released using coap_delete_str_const().
*
* @param data The data to put in the new string object.
* @param size The size to allocate for the binary string data.
*
* @return A pointer to the new object or @c NULL on error.
*/
coap_str_const_t *coap_new_str_const(const uint8_t *data, size_t size);
/**
* Deletes the given const string and releases any memory allocated.
*
* @param string The string to free off.
*/
void coap_delete_str_const(coap_str_const_t *string);
/**
* Take the specified byte array (text) and create a coap_str_const_t *
*
* WARNING: The byte array must be in the local scope and not a
* parameter in the function call as sizeof() will return the size of the
* pointer, not the size of the byte array, leading to unxepected results.
*
* @param string The const byte array to convert to a coap_str_const_t *
*/
#ifdef __cplusplus
namespace libcoap {
struct CoAPStrConst : coap_str_const_t {
operator coap_str_const_t *() { return this; }
};
}
#define coap_make_str_const(CStr) \
libcoap::CoAPStrConst{sizeof(CStr)-1, reinterpret_cast<const uint8_t *>(CStr)}
#else /* __cplusplus */
#define coap_make_str_const(string) \
(&(coap_str_const_t){sizeof(string)-1,(const uint8_t *)(string)})
#endif /* __cplusplus */
/**
* Compares the two strings for equality
*
* @param string1 The first string.
* @param string2 The second string.
*
* @return @c 1 if the strings are equal
* @c 0 otherwise.
*/
#define coap_string_equal(string1,string2) \
((string1)->length == (string2)->length && ((string1)->length == 0 || \
memcmp((string1)->s, (string2)->s, (string1)->length) == 0))
/** @} */
#endif /* COAP_STR_H_ */

View File

@ -0,0 +1,77 @@
/*
* subscribe.h -- subscription handling for CoAP
* see RFC7641
*
* 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"
#include "block.h"
/**
* @defgroup observe Resource observation
* API functions for interfacing with the observe handling (RFC7641)
* @{
*/
/**
* 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_session_t *session; /**< subscriber session */
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) */
unsigned int has_block2:1; /**< GET request had Block2 definition */
uint16_t tid; /**< transaction id, if any, in regular host byte order */
coap_block_t block2; /**< GET request Block2 definition */
size_t token_length; /**< actual length of token */
unsigned char token[8]; /**< token used for subscription */
coap_string_t *query; /**< query string used for subscription, if any */
} coap_subscription_t;
void coap_subscription_init(coap_subscription_t *);
/** @} */
#endif /* COAP_SUBSCRIBE_H_ */

View File

@ -0,0 +1,147 @@
/*
* 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 <stdint.h>
#include "str.h"
struct coap_pdu_t;
/**
* The scheme specifiers. Secure schemes have an odd numeric value,
* others are even.
*/
enum coap_uri_scheme_t {
COAP_URI_SCHEME_COAP=0,
COAP_URI_SCHEME_COAPS=1,
COAP_URI_SCHEME_COAP_TCP=2,
COAP_URI_SCHEME_COAPS_TCP=3
};
/** This mask can be used to check if a parsed URI scheme is secure. */
#define COAP_URI_SCHEME_SECURE_MASK 0x01
/**
* 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 {
coap_str_const_t host; /**< host part of the URI */
uint16_t port; /**< The port in host byte order */
coap_str_const_t path; /**< Beginning of the first path segment.
Use coap_split_path() to create Uri-Path options */
coap_str_const_t query; /**< The query part if present */
/** The parsed scheme specifier. */
enum coap_uri_scheme_t scheme;
} coap_uri_t;
static inline int
coap_uri_scheme_is_secure(const coap_uri_t *uri) {
return uri && ((uri->scheme & COAP_URI_SCHEME_SECURE_MASK) != 0);
}
/**
* 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 uint8_t *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);
/**
* @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 uint8_t *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 uint8_t *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 uint8_t *s,
size_t length,
unsigned char *buf,
size_t *buflen);
/**
* Extract query string from request PDU according to escape rules in 6.5.8.
* @param request Request PDU.
* @return Reconstructed and escaped query string part.
*/
coap_string_t *coap_get_query(const struct coap_pdu_t *request);
/**
* Extract uri_path string from request PDU
* @param request Request PDU.
* @return Reconstructed and escaped uri path string part.
*/
coap_string_t *coap_get_uri_path(const struct coap_pdu_t *request);
/** @} */
#endif /* COAP_URI_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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_
#ifdef __cplusplus
extern "C" {
#endif
#include "libcoap.h"
#include "address.h"
#include "async.h"
#include "bits.h"
#include "block.h"
#include "coap_dtls.h"
#include "coap_event.h"
#include "coap_io.h"
#include "coap_time.h"
#include "coap_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"
#ifdef __cplusplus
}
#endif
#endif /* _COAP_H_ */

View File

@ -0,0 +1,631 @@
/*
* coap_dtls.h -- (Datagram) Transport Layer Support for libcoap
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
*
* This file is part of the CoAP library libcoap. Please see README for terms
* of use.
*/
#ifndef COAP_DTLS_H_
#define COAP_DTLS_H_
#include "coap_time.h"
#include "str.h"
struct coap_context_t;
struct coap_session_t;
struct coap_dtls_pki_t;
/**
* @defgroup dtls DTLS Support
* API functions for interfacing with DTLS libraries.
* @{
*/
/**
* Check whether DTLS is available.
*
* @return @c 1 if support for DTLS is enabled, or @c 0 otherwise.
*/
int coap_dtls_is_supported(void);
/**
* Check whether TLS is available.
*
* @return @c 1 if support for TLS is enabled, or @c 0 otherwise.
*/
int coap_tls_is_supported(void);
typedef enum coap_tls_library_t {
COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */
COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */
COAP_TLS_LIBRARY_OPENSSL, /**< Using OpenSSL library */
COAP_TLS_LIBRARY_GNUTLS, /**< Using GnuTLS library */
COAP_TLS_LIBRARY_MBEDTLS, /**< Using MbedTLS library */
} coap_tls_library_t;
/**
* The structure used for returning the underlying (D)TLS library
* information.
*/
typedef struct coap_tls_version_t {
uint64_t version; /**< (D)TLS runtime Library Version */
coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */
uint64_t built_version; /**< (D)TLS Built against Library Version */
} coap_tls_version_t;
/**
* Determine the type and version of the underlying (D)TLS library.
*
* @return The version and type of library libcoap was compiled against.
*/
coap_tls_version_t *coap_get_tls_library_version(void);
/**
* Additional Security setup handler that can be set up by
* coap_context_set_pki().
* Invoked when libcoap has done the validation checks at the TLS level,
* but the application needs to do some additional checks/changes/updates.
*
* @param tls_session The security session definition - e.g. SSL * for OpenSSL.
* NULL if server call-back.
* This will be dependent on the underlying TLS library -
* see coap_get_tls_library_version()
* @param setup_data A structure containing setup data originally passed into
* coap_context_set_pki() or coap_new_client_session_pki().
*
* @return @c 1 if successful, else @c 0.
*/
typedef int (*coap_dtls_security_setup_t)(void* tls_session,
struct coap_dtls_pki_t *setup_data);
/**
* CN Validation call-back that can be set up by coap_context_set_pki().
* Invoked when libcoap has done the validation checks at the TLS level,
* but the application needs to check that the CN is allowed.
* CN is the SubjectAltName in the cert, if not present, then the leftmost
* Common Name (CN) component of the subject name.
*
* @param cn The determined CN from the certificate
* @param asn1_public_cert The ASN.1 DER encoded X.509 certificate
* @param asn1_length The ASN.1 length
* @param coap_session The CoAP session associated with the certificate update
* @param depth Depth in cert chain. If 0, then client cert, else a CA
* @param validated TLS layer can find no issues if 1
* @param arg The same as was passed into coap_context_set_pki()
* in setup_data->cn_call_back_arg
*
* @return @c 1 if accepted, else @c 0 if to be rejected.
*/
typedef int (*coap_dtls_cn_callback_t)(const char *cn,
const uint8_t *asn1_public_cert,
size_t asn1_length,
struct coap_session_t *coap_session,
unsigned depth,
int validated,
void *arg);
/**
* The enum used for determining the provided PKI ASN.1 (DER) Private Key
* formats.
*/
typedef enum coap_asn1_privatekey_type_t {
COAP_ASN1_PKEY_NONE, /**< NONE */
COAP_ASN1_PKEY_RSA, /**< RSA type */
COAP_ASN1_PKEY_RSA2, /**< RSA2 type */
COAP_ASN1_PKEY_DSA, /**< DSA type */
COAP_ASN1_PKEY_DSA1, /**< DSA1 type */
COAP_ASN1_PKEY_DSA2, /**< DSA2 type */
COAP_ASN1_PKEY_DSA3, /**< DSA3 type */
COAP_ASN1_PKEY_DSA4, /**< DSA4 type */
COAP_ASN1_PKEY_DH, /**< DH type */
COAP_ASN1_PKEY_DHX, /**< DHX type */
COAP_ASN1_PKEY_EC, /**< EC type */
COAP_ASN1_PKEY_HMAC, /**< HMAC type */
COAP_ASN1_PKEY_CMAC, /**< CMAC type */
COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */
COAP_ASN1_PKEY_HKDF /**< HKDF type */
} coap_asn1_privatekey_type_t;
/**
* The enum used for determining the PKI key formats.
*/
typedef enum coap_pki_key_t {
COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM file */
COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) */
COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */
} coap_pki_key_t;
/**
* The structure that holds the PKI PEM definitions.
*/
typedef struct coap_pki_key_pem_t {
const char *ca_file; /**< File location of Common CA in PEM format */
const char *public_cert; /**< File location of Public Cert in PEM format */
const char *private_key; /**< File location of Private Key in PEM format */
} coap_pki_key_pem_t;
/**
* The structure that holds the PKI PEM buffer definitions.
*/
typedef struct coap_pki_key_pem_buf_t {
const uint8_t *ca_cert; /**< PEM buffer Common CA Cert */
const uint8_t *public_cert; /**< PEM buffer Public Cert */
const uint8_t *private_key; /**< PEM buffer Private Key */
size_t ca_cert_len; /**< PEM buffer CA Cert length */
size_t public_cert_len; /**< PEM buffer Public Cert length */
size_t private_key_len; /**< PEM buffer Private Key length */
} coap_pki_key_pem_buf_t;
/**
* The structure that holds the PKI ASN.1 (DER) definitions.
*/
typedef struct coap_pki_key_asn1_t {
const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */
const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */
const uint8_t *private_key; /**< ASN1 (DER) Private Key */
size_t ca_cert_len; /**< ASN1 CA Cert length */
size_t public_cert_len; /**< ASN1 Public Cert length */
size_t private_key_len; /**< ASN1 Private Key length */
coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */
} coap_pki_key_asn1_t;
/**
* The structure that holds the PKI key information.
*/
typedef struct coap_dtls_key_t {
coap_pki_key_t key_type; /**< key format type */
union {
coap_pki_key_pem_t pem; /**< for PEM file keys */
coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */
coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) file keys */
} key;
} coap_dtls_key_t;
/**
* Server Name Indication (SNI) Validation call-back that can be set up by
* coap_context_set_pki().
* Invoked if the SNI is not previously seen and prior to sending a certificate
* set back to the client so that the appropriate certificate set can be used
* based on the requesting SNI.
*
* @param sni The requested SNI
* @param arg The same as was passed into coap_context_set_pki()
* in setup_data->sni_call_back_arg
*
* @return New set of certificates to use, or @c NULL if SNI is to be rejected.
*/
typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni,
void* arg);
#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */
/**
* The structure used for defining the PKI setup data to be used.
*/
typedef struct coap_dtls_pki_t {
uint8_t version; /** Set to 1 to support this version of the struct */
/* Options to enable different TLS functionality in libcoap */
uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */
uint8_t require_peer_cert; /**< 1 if peer cert is required */
uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */
uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */
uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */
uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */
uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */
uint8_t allow_no_crl; /**< 1 ignore if CRL not there */
uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */
uint8_t allow_bad_md_hash; /**< 1 if expired certs are allowed */
uint8_t allow_short_rsa_length; /**< 1 if expired certs are allowed */
uint8_t reserved[4]; /**< Reserved - must be set to 0 for
future compatibility */
/* Size of 4 chosen to align to next
* parameter, so if newly defined option
* it can use one of the reserverd slot so
* no need to change
* COAP_DTLS_PKI_SETUP_VERSION and just
* decrement the reserved[] count.
*/
/** CN check call-back function.
* If not NULL, is called when the TLS connection has passed the configured
* TLS options above for the application to verify if the CN is valid.
*/
coap_dtls_cn_callback_t validate_cn_call_back;
void *cn_call_back_arg; /**< Passed in to the CN call-back function */
/** SNI check call-back function.
* If not @p NULL, called if the SNI is not previously seen and prior to
* sending a certificate set back to the client so that the appropriate
* certificate set can be used based on the requesting SNI.
*/
coap_dtls_sni_callback_t validate_sni_call_back;
void *sni_call_back_arg; /**< Passed in to the sni call-back function */
/** Additional Security call-back handler that is invoked when libcoap has
* done the standerd, defined validation checks at the TLS level,
* If not @p NULL, called from within the TLS Client Hello connection
* setup.
*/
coap_dtls_security_setup_t additional_tls_setup_call_back;
char* client_sni; /**< If not NULL, SNI to use in client TLS setup.
Owned by the client app and must remain valid
during the call to coap_new_client_session_pki() */
coap_dtls_key_t pki_key; /**< PKI key definition */
} coap_dtls_pki_t;
/** @} */
/**
* @defgroup dtls_internal DTLS Support (Internal)
* Internal API functions for interfacing with DTLS libraries.
* @{
*/
/**
* Creates a new DTLS context for the given @p coap_context. This function
* returns a pointer to a new DTLS context object or @c NULL on error.
*
* Internal function.
*
* @param coap_context The CoAP context where the DTLS object shall be used.
*
* @return A DTLS context object or @c NULL on error.
*/
void *
coap_dtls_new_context(struct coap_context_t *coap_context);
typedef enum coap_dtls_role_t {
COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */
COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */
} coap_dtls_role_t;
/**
* Set the DTLS context's default PSK information.
* This does the PSK specifics following coap_dtls_new_context().
* If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set.
* If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
* TLS library's context (from which sessions are derived).
* If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
* TLS library's session.
*
* Internal function.
*
* @param coap_context The CoAP context.
* @param identity_hint The default PSK server identity hint sent to a client.
* Required parameter. If @p NULL, will be set to "".
* Empty string is a valid hint.
* This parameter is ignored if COAP_DTLS_ROLE_CLIENT
* @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_psk(struct coap_context_t *coap_context,
const char *identity_hint,
coap_dtls_role_t role);
/**
* Set the DTLS context's default server PKI information.
* This does the PKI specifics following coap_dtls_new_context().
* If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
* TLS library's context (from which sessions are derived).
* If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
* TLS library's session.
*
* Internal function.
*
* @param coap_context The CoAP context.
* @param setup_data Setup information defining how PKI is to be setup.
* Required parameter. If @p NULL, PKI will not be
* set up.
* @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_pki(struct coap_context_t *coap_context,
coap_dtls_pki_t *setup_data,
coap_dtls_role_t role);
/**
* Set the dtls context's default Root CA information for a client or server.
*
* Internal function.
*
* @param coap_context The current coap_context_t object.
* @param ca_file If not @p NULL, is the full path name of a PEM encoded
* file containing all the Root CAs to be used.
* @param ca_dir If not @p NULL, points to a directory containing PEM
* encoded files containing all the Root CAs to be used.
*
* @return @c 1 if successful, else @c 0.
*/
int
coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context,
const char *ca_file,
const char *ca_dir);
/**
* Check whether one of the coap_dtls_context_set_{psk|pki}() functions have
* been called.
*
* Internal function.
*
* @param coap_context The current coap_context_t object.
*
* @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0.
*/
int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context);
/**
* Releases the storage allocated for @p dtls_context.
*
* Internal function.
*
* @param dtls_context The DTLS context as returned by coap_dtls_new_context().
*/
void coap_dtls_free_context(void *dtls_context);
/**
* Create a new client-side session. This should send a HELLO to the server.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_dtls_new_client_session(struct coap_session_t *coap_session);
/**
* Create a new DTLS server-side session.
* Called after coap_dtls_hello() has returned @c 1, signalling that a validated
* HELLO was received from a client.
* This should send a HELLO to the server.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the DTLS session.
*/
void *coap_dtls_new_server_session(struct coap_session_t *coap_session);
/**
* Terminates the DTLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_free_session(struct coap_session_t *coap_session);
/**
* Notify of a change in the CoAP session's MTU, for example after
* a PMTU update.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_session_update_mtu(struct coap_session_t *coap_session);
/**
* Send data to a DTLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this would be blocking, @c -1 if there is an error or the
* number of cleartext bytes sent.
*/
int coap_dtls_send(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Check if timeout is handled per CoAP session or per CoAP context.
*
* Internal function.
*
* @return @c 1 of timeout and retransmit is per context, @c 0 if it is
* per session.
*/
int coap_dtls_is_context_timeout(void);
/**
* Do all pending retransmits and get next timeout
*
* Internal function.
*
* @param dtls_context The DTLS context.
*
* @return @c 0 if no event is pending or date of the next retransmit.
*/
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context);
/**
* Get next timeout for this session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param now The current time in ticks.
*
* @return @c 0 If no event is pending or ticks time of the next retransmit.
*/
coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session,
coap_tick_t now);
/**
* Handle a DTLS timeout expiration.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_handle_timeout(struct coap_session_t *coap_session);
/**
* Handling incoming data from a DTLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return Result of coap_handle_dgram on the decrypted CoAP PDU
* or @c -1 for error.
*/
int coap_dtls_receive(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Handling client HELLO messages from a new candiate peer.
* Note that session->tls is empty.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return @c 0 if a cookie verification message has been sent, @c 1 if the
* HELLO contains a valid cookie and a server session should be created,
* @c -1 if the message is invalid.
*/
int coap_dtls_hello(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Get DTLS overhead over cleartext PDUs.
*
* Internal function.
*
* @param coap_session The CoAP session.
*
* @return Maximum number of bytes added by DTLS layer.
*/
unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session);
/**
* Create a new TLS client-side session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param connected Updated with whether the connection is connected yet or not.
* @c 0 is not connected, @c 1 is connected.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected);
/**
* Create a TLS new server-side session.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param connected Updated with whether the connection is connected yet or not.
* @c 0 is not connected, @c 1 is connected.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected);
/**
* Terminates the TLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* Internal function.
*
* @param coap_session The CoAP session.
*/
void coap_tls_free_session( struct coap_session_t *coap_session );
/**
* Send data to a TLS peer, with implicit flush.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes sent.
*/
ssize_t coap_tls_write(struct coap_session_t *coap_session,
const uint8_t *data,
size_t data_len
);
/**
* Read some data from a TLS peer.
*
* Internal function.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Maximum number of bytes to read.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes read.
*/
ssize_t coap_tls_read(struct coap_session_t *coap_session,
uint8_t *data,
size_t data_len
);
/**
* Initialize the underlying (D)TLS Library layer.
*
* Internal function.
*
*/
void coap_dtls_startup(void);
/** @} */
/**
* @ingroup logging
* Sets the (D)TLS logging level to the specified @p level.
* Note: coap_log_level() will influence output if at a specified level.
*
* @param level The logging level to use - LOG_*
*/
void coap_dtls_set_log_level(int level);
/**
* @ingroup logging
* Get the current (D)TLS logging.
*
* @return The current log level (one of LOG_*).
*/
int coap_dtls_get_log_level(void);
#endif /* COAP_DTLS_H */

View File

@ -0,0 +1,42 @@
/*
* 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_
/* Always enabled in ESP-IDF */
#ifndef WITH_POSIX
#define WITH_POSIX
#endif
#include "coap_config_posix.h"
#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_ */

View File

@ -0,0 +1,61 @@
/*
* 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>
#include <net/if.h>
#define HAVE_SYS_SOCKET_H
#define HAVE_MALLOC
#define HAVE_ARPA_INET_H
#define HAVE_TIME_H
#define HAVE_NETDB_H
#define HAVE_NETINET_IN_H
#define HAVE_STRUCT_CMSGHDR
#define ipi_spec_dst ipi_addr
struct in6_pktinfo {
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
#define IN6_IS_ADDR_V4MAPPED(a) \
((((__const uint32_t *) (a))[0] == 0) \
&& (((__const uint32_t *) (a))[1] == 0) \
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
/* As not defined, just need to define is as something innocuous */
#define IPV6_PKTINFO IPV6_CHECKSUM
#define PACKAGE_NAME "libcoap-posix"
#define PACKAGE_VERSION "?"
#ifdef CONFIG_MBEDTLS_TLS_ENABLED
#define HAVE_MBEDTLS
#endif /* CONFIG_MBEDTLS_TLS_ENABLED */
#define COAP_CONSTRAINED_STACK 1
#define ESPIDF_VERSION
#define _POSIX_TIMERS 1
#define gai_strerror(x) "gai_strerror() not supported"
#endif /* WITH_POSIX */
#endif /* COAP_CONFIG_POSIX_H_ */