23 #include <lwip/memp.h> 
   25 #define COAP_MALLOC_TYPE(Type) \ 
   26   ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) 
   27 #define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object) 
   34 #define COAP_MALLOC_TYPE(Type) \ 
   35   ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) 
   36 #define COAP_FREE_TYPE(Type, Object) coap_free(Object) 
   43 MEMB(attribute_storage, 
coap_attr_t, COAP_MAX_ATTRIBUTES);
 
   47 coap_resources_init() {
 
   48   memb_init(&resource_storage);
 
   49   memb_init(&attribute_storage);
 
   50   memb_init(&subscription_storage);
 
   54 coap_malloc_subscription() {
 
   55   return memb_alloc(&subscription_storage);
 
   60   memb_free(&subscription_storage, subscription);
 
   64 #define min(a,b) ((a) < (b) ? (a) : (b)) 
   74 #define PRINT_WITH_OFFSET(Buf,Offset,Char)      \ 
   75   if ((Offset) == 0) {                  \ 
   76     (*(Buf)++) = (Char);                \ 
   84 #define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) {     \ 
   85     if ((Buf) < (Bufend)) {                     \ 
   86       PRINT_WITH_OFFSET(Buf,Offset,Char);               \ 
   96 #define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) {    \ 
   98     for (i = 0; i < (Length); i++) {                    \ 
   99       PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ 
  104 match(
const str *text, 
const str *pattern, 
int match_prefix, 
int match_substring) {
 
  105   assert(text); assert(pattern);
 
  110   if (match_substring) {
 
  111     unsigned char *next_token = text->
s;
 
  112     size_t remaining_length = text->
length;
 
  113     while (remaining_length) {
 
  115       unsigned char *token = next_token;
 
  116       next_token = memchr(token, 
' ', remaining_length);
 
  119         token_length = next_token - token;
 
  120         remaining_length -= (token_length + 1);
 
  123         token_length = remaining_length;
 
  124         remaining_length = 0;
 
  127       if ((match_prefix || pattern->
length == token_length) &&
 
  128             memcmp(token, pattern->
s, pattern->
length) == 0)
 
  134   return (match_prefix || pattern->
length == text->
length) &&
 
  135     memcmp(text->
s, pattern->
s, pattern->
length) == 0;
 
  159 #if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) 
  163         coap_opt_t *query_filter __attribute__ ((unused))) {
 
  170   unsigned char *p = buf;
 
  171   const unsigned char *bufend = buf + *buflen;
 
  172   size_t left, written = 0;
 
  174   const size_t old_offset = offset;
 
  175   int subsequent_resource = 0;
 
  176 #ifndef COAP_RESOURCES_NOHASH 
  179 #ifndef WITHOUT_QUERY_FILTER 
  180   str resource_param = { 0, NULL }, query_pattern = { 0, NULL };
 
  182 #define MATCH_URI       0x01 
  183 #define MATCH_PREFIX    0x02 
  184 #define MATCH_SUBSTRING 0x04 
  185   static const str _rt_attributes[] = {
 
  186     {2, (
unsigned char *)
"rt"},
 
  187     {2, (
unsigned char *)
"if"},
 
  188     {3, (
unsigned char *)
"rel"},
 
  196 #ifndef WITHOUT_QUERY_FILTER 
  201        && resource_param.
s[resource_param.
length] != 
'=')
 
  205       const str *rt_attributes;
 
  206       if (resource_param.
length == 4 && 
 
  207       memcmp(resource_param.
s, 
"href", 4) == 0)
 
  210       for (rt_attributes = _rt_attributes; rt_attributes->
s; rt_attributes++) {
 
  212             memcmp(resource_param.
s, rt_attributes->
s, rt_attributes->
length) == 0) {
 
  223       query_pattern.length = 
 
  228        query_pattern.length--;
 
  231       if (query_pattern.length && 
 
  232       query_pattern.s[query_pattern.length-1] == 
'*') {
 
  233     query_pattern.length--;
 
  242 #ifdef COAP_RESOURCES_NOHASH 
  249   for (i = 0; i < resource_storage.num; ++i, ++r) {
 
  250     if (!resource_storage.count[i])
 
  254 #ifndef WITHOUT_QUERY_FILTER 
  255     if (resource_param.
length) { 
 
  265         if (attr->
value.
s[0] == 
'"') {          
 
  267           unquoted_val.
s = attr->
value.
s + 1;
 
  269           unquoted_val = attr->
value;
 
  271     if (!(
match(&unquoted_val, &query_pattern, 
 
  279     if (!subsequent_resource) { 
 
  280       subsequent_resource = 1;
 
  300   if (result + old_offset - offset < *buflen) {
 
  327     r->
uri.
s = (
unsigned char *)uri;
 
  334     debug(
"coap_resource_init: no memory left\n");
 
  342           const unsigned char *name, 
size_t nlen,
 
  343           const unsigned char *val, 
size_t vlen,
 
  347   if (!resource || !name)
 
  354   attr = (
coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR);
 
  357   attr = (
coap_attr_t *)memb_alloc(&attribute_storage);
 
  364     attr->
name.
s = (
unsigned char *)name;
 
  365     attr->
value.
s = (
unsigned char *)val;
 
  376     debug(
"coap_add_attr: no memory left\n");
 
  384            const unsigned char *name, 
size_t nlen) {
 
  387   if (!resource || !name)
 
  397     memcmp(attr->
name.
s, name, nlen) == 0)
 
  416   memp_free(MEMP_COAP_RESOURCEATTR, attr);
 
  442 #ifdef COAP_RESOURCES_NOHASH 
  466 #if defined(WITH_POSIX) || defined(WITH_LWIP) 
  467 #ifdef COAP_RESOURCES_NOHASH 
  483   memp_free(MEMP_COAP_RESOURCE, resource);
 
  488     memb_free(&attribute_storage, attr);
 
  491   while ( (obs = 
list_pop(resource->subscribers)) ) {
 
  493     memb_free(&subscription_storage, obs);
 
  496   memb_free(&resource_storage, resource);
 
  506 #ifdef COAP_RESOURCES_NOHASH 
  526   for (i = 0; i < resource_storage.num; ++i) {
 
  527     if (resource_storage.count[i] && 
 
  539         unsigned char *buf, 
size_t *len, 
size_t *offset) {
 
  540   unsigned char *p = buf;
 
  541   const unsigned char *bufend = buf + *len;
 
  544   const size_t old_offset = *offset;
 
  580   if (result + old_offset - *offset < *len) {
 
  587 #ifndef WITHOUT_OBSERVE 
  608           const coap_address_t *observer,
 
  623   s = COAP_MALLOC_TYPE(subscription);
 
  629   memcpy(&s->
subscriber, observer, 
sizeof(coap_address_t));
 
  631   if (token && token->
length) {
 
  649 #ifdef COAP_RESOURCES_NOHASH 
  662   for (i = 0; i < resource_storage.num; ++i, ++r) {
 
  663     if (resource_storage.count[i]) {
 
  683     COAP_FREE_TYPE(subscription,s);
 
  714     debug(
"coap_check_notify: pdu init failed, resource stays partially dirty\n");
 
  721     debug(
"coap_check_notify: cannot add token, resource stays partially dirty\n");
 
  736       h(context, r, &obs->
subscriber, NULL, &token, response);
 
  750     debug(
"coap_check_notify: sending failed, resource stays partially dirty\n");
 
  768 #ifdef COAP_RESOURCES_NOHASH 
  780   for (i = 0; i < resource_storage.num; ++i, ++r) {
 
  781     if (resource_storage.count[i]) {
 
  801                  const coap_address_t *peer,
 
  805   for (obs = 
list_head(resource->subscribers); obs; 
 
  821 #ifndef INET6_ADDRSTRLEN 
  822 #define INET6_ADDRSTRLEN 40 
  827         debug(
"** removed observer %s\n", addr);
 
  833     COAP_FREE_TYPE(subscription, obs);
 
  842               const coap_address_t *peer, 
 
  848 #ifdef COAP_RESOURCES_NOHASH 
  860   for (i = 0; i < resource_storage.num; ++i, ++r) {
 
  861     if (resource_storage.count[i]) {
 
#define LL_FOREACH(head, el)
unsigned int observe
The next value to be used for Observe. 
coap_subscription_t * coap_add_observer(coap_resource_t *resource, const coap_address_t *observer, const str *token)
Adds the specified peer as observer for resource. 
void coap_check_notify(coap_context_t *context)
Checks for all known resources, if they are dirty and notifies subscribed observers. 
unsigned char coap_key_t[4]
#define LIST_STRUCT_INIT(struct_ptr, name)
int coap_delete_resource(coap_context_t *context, coap_key_t key)
Deletes a resource identified by key. 
coap_print_status_t print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, size_t offset, coap_opt_t *query_filter)
Prints the names of all known resources to buf. 
#define COAP_PRINT_OUTPUT_LENGTH(v)
coap_tid_t coap_send_confirmed(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a confirmed CoAP message to given destination. 
#define LL_PREPEND(head, add)
#define HASH_ITER(hh, head, el, tmp)
int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data)
Adds token of length len to pdu. 
coap_attr_t * link_attr
attributes to be included with the link format 
#define COAP_ATTR_FLAGS_RELEASE_NAME
unsigned int partiallydirty
set to 1 if some subscribers have not yet been notified of the last change 
#define coap_malloc(size)
static void coap_remove_failed_observers(coap_context_t *context, coap_resource_t *resource, const coap_address_t *peer, const str *token)
Checks the failure counter for (peer, token) and removes peer from the list of observers for the give...
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option. 
coap_log_t coap_get_log_level()
Returns the current log level. 
static int coap_option_setb(coap_opt_filter_t filter, unsigned short type)
Sets the corresponding bit for type in filter. 
static void * list_item_next(void *item)
#define COAP_OBS_MAX_FAIL
Number of confirmable notifications that may fail (i.e. 
void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key)
Calculates the hash key for the resource requested by the Uri-Options of request. ...
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
#define HASH_DELETE(hh, head, delptr)
coap_attr_t * coap_add_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen, const unsigned char *val, size_t vlen, int flags)
Registers a new attribute with the given resource. 
size_t token_length
actual length of token 
void coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst, const unsigned char *token, size_t token_length)
Cancels all outstanding messages for peer dst that have the specified token. 
str uri
Request URI for this resource. 
Header structure for CoAP PDUs. 
coap_opt_iterator_t * coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t filter)
Initializes the given option iterator oi to point to the beginning of the pdu's option list...
static void list_add(list_t the_list, void *item)
coap_key_t key
the actual key bytes for this resource 
unsigned int dirty
set to 1 if resource has changed 
static void list_remove(list_t the_list, void *item)
#define COAP_ATTR_FLAGS_RELEASE_VALUE
unsigned int observable
can be observed 
void coap_add_resource(coap_context_t *context, coap_resource_t *resource)
Registers the given resource for context. 
unsigned int non_cnt
up to 15 non-confirmable notifies allowed 
Iterator to run through PDU options. 
generic resource handling 
#define COAP_MAX_PDU_SIZE
unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3)+1]
Fixed-size bit-vector we use for option filtering. 
#define coap_hash(String, Length, Result)
static void coap_notify_observers(coap_context_t *context, coap_resource_t *r)
static void * list_pop(list_t the_list)
coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a non-confirmed CoAP message to given destination. 
int match(const str *text, const str *pattern, int match_prefix, int match_substring)
coap_subscription_t * coap_find_observer(coap_resource_t *resource, const coap_address_t *peer, const str *token)
Returns a subscription object for given peer. 
void coap_delete_pdu(coap_pdu_t *pdu)
coap_pdu_t * coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size)
Creates a new CoAP PDU of given size (must be large enough to hold the basic CoAP message header (coa...
unsigned int dirty
set if the notification temporarily could not be sent (in that case, the resource's partiallydirty fl...
static void coap_option_filter_clear(coap_opt_filter_t f)
Clears filter f. 
int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key)
Calculates a hash over the given path and stores the result in key. 
static void * list_head(list_t the_list)
#define LL_FOREACH_SAFE(head, el, tmp)
#define PRINT_COND_WITH_OFFSET(Buf, Bufend, Offset, Char, Result)
Adds Char to Buf if Offset is zero and Buf is less than Bufend. 
#define COAP_OPT_LENGTH(opt)
static unsigned short coap_new_message_id(coap_context_t *context)
Returns a new message id and updates context->message_id accordingly. 
coap_print_status_t coap_print_link(const coap_resource_t *resource, unsigned char *buf, size_t *len, size_t *offset)
Writes a description of this resource in link-format to given text buffer. 
coap_attr_t * coap_find_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen)
Returns resource's coap_attr_t object with given name if found, NULL otherwise. 
coap_resource_t * coap_resource_init(const unsigned char *uri, size_t len, int flags)
Creates a new resource object and initializes the link field to the string of length len...
#define COAP_OPTION_URI_PATH
void coap_touch_observer(coap_context_t *context, const coap_address_t *observer, const str *token)
Marks an observer as alive. 
#define LL_DELETE(head, del)
#define COAP_PRINT_STATUS_ERROR
#define HASH_ADD(hh, head, fieldname, keylen_in, add)
unsigned int coap_print_status_t
Status word to encode the result of conditional print or copy operations such as coap_print_link(). 
unsigned char coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
#define COPY_COND_WITH_OFFSET(Buf, Bufend, Offset, Str, Length, Result)
Copies at most Length characters of Str to Buf. 
unsigned int fail_cnt
up to 3 confirmable notifies can fail 
unsigned char token[8]
token used for subscription 
void coap_delete_attr(coap_attr_t *attr)
Deletes an attribute. 
void coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer, const str *token)
Removes any subscription for observer from resource and releases the allocated storage. 
void(* coap_method_handler_t)(coap_context_t *, struct coap_resource_t *, coap_address_t *, coap_pdu_t *, str *, coap_pdu_t *)
Definition of message handler function (. 
#define HASH_FIND(hh, head, keyptr, keylen, out)
#define COAP_PRINT_STATUS_TRUNC
void coap_subscription_init(coap_subscription_t *s)
#define COAP_RESOURCE_FLAGS_RELEASE_URI
void coap_handle_failed_notify(coap_context_t *context, const coap_address_t *peer, const str *token)
unsigned int non
send non-confirmable notifies if 1 
coap_address_t subscriber
address and port of subscriber 
#define COAP_OPT_VALUE(opt)
The CoAP stack's global state is stored in a coap_context_t object. 
static int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b. 
#define COAP_OBS_MAX_NON
Number of notifications that may be sent non-confirmable before a confirmable message is sent to dete...
coap_resource_t * coap_get_resource_from_key(coap_context_t *context, coap_key_t key)
Returns the resource identified by the unique string key. 
struct coap_resource_t * resources
hash table or list of known resources 
coap_method_handler_t handler[4]
Used to store handlers for the four coap methods GET, POST, PUT, and DELETE.