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]) {