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.