9 #include "coap_config.h" 24 #include <lwip/memp.h> 26 #define COAP_MALLOC_TYPE(Type) \ 27 ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) 28 #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) 42 #define COAP_MALLOC_TYPE(Type) \ 43 ((coap_##Type##_t *)memb_alloc(&(Type##_storage))) 44 #define COAP_FREE_TYPE(Type, Object) memb_free(&(Type##_storage), (Object)) 49 coap_resources_init() {
50 memb_init(&subscription_storage);
54 coap_malloc_subscription() {
55 return memb_alloc(&subscription_storage);
60 memb_free(&subscription_storage, subscription);
65 #define min(a,b) ((a) < (b) ? (a) : (b)) 75 #define PRINT_WITH_OFFSET(Buf,Offset,Char) \ 76 if ((Offset) == 0) { \ 77 (*(Buf)++) = (Char); \ 85 #define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \ 86 if ((Buf) < (Bufend)) { \ 87 PRINT_WITH_OFFSET(Buf,Offset,Char); \ 97 #define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \ 99 for (i = 0; i < (Length); i++) { \ 100 PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ 105 match(
const str *text,
const str *pattern,
int match_prefix,
int match_substring) {
111 if (match_substring) {
112 unsigned char *next_token = text->
s;
113 size_t remaining_length = text->
length;
114 while (remaining_length) {
116 unsigned char *token = next_token;
117 next_token = memchr(token,
' ', remaining_length);
120 token_length = next_token - token;
121 remaining_length -= (token_length + 1);
124 token_length = remaining_length;
125 remaining_length = 0;
128 if ((match_prefix || pattern->
length == token_length) &&
129 memcmp(token, pattern->
s, pattern->
length) == 0)
135 return (match_prefix || pattern->
length == text->
length) &&
136 memcmp(text->
s, pattern->
s, pattern->
length) == 0;
160 #if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) 164 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 WITHOUT_QUERY_FILTER 177 str resource_param = { 0, NULL }, query_pattern = { 0, NULL };
179 #define MATCH_URI 0x01 180 #define MATCH_PREFIX 0x02 181 #define MATCH_SUBSTRING 0x04 182 static const str _rt_attributes[] = {
183 {2, (
unsigned char *)
"rt"},
184 {2, (
unsigned char *)
"if"},
185 {3, (
unsigned char *)
"rel"},
189 #ifndef WITHOUT_QUERY_FILTER 194 && resource_param.
s[resource_param.
length] !=
'=')
198 const str *rt_attributes;
199 if (resource_param.
length == 4 &&
200 memcmp(resource_param.
s,
"href", 4) == 0)
203 for (rt_attributes = _rt_attributes; rt_attributes->
s; rt_attributes++) {
205 memcmp(resource_param.
s, rt_attributes->
s, rt_attributes->
length) == 0) {
216 query_pattern.length =
221 query_pattern.length--;
224 if (query_pattern.length &&
225 query_pattern.s[query_pattern.length-1] ==
'*') {
226 query_pattern.length--;
235 #ifndef WITHOUT_QUERY_FILTER 236 if (resource_param.
length) {
246 if (attr->
value.
s[0] ==
'"') {
248 unquoted_val.
s = attr->
value.
s + 1;
250 unquoted_val = attr->
value;
252 if (!(
match(&unquoted_val, &query_pattern,
260 if (!subsequent_resource) {
261 subsequent_resource = 1;
281 if (result + old_offset - offset < *buflen) {
300 r->
uri.
s = (
unsigned char *)uri;
307 debug(
"coap_resource_init: no memory left\n");
315 const unsigned char *name,
size_t nlen,
316 const unsigned char *val,
size_t vlen,
320 if (!resource || !name)
324 attr = (
coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR);
334 attr->
name.
s = (
unsigned char *)name;
335 attr->
value.
s = (
unsigned char *)val;
342 debug(
"coap_add_attr: no memory left\n");
350 const unsigned char *name,
size_t nlen) {
353 if (!resource || !name)
358 memcmp(attr->
name.
s, name, nlen) == 0)
375 memp_free(MEMP_COAP_RESOURCEATTR, attr);
420 memp_free(MEMP_COAP_RESOURCE, resource);
456 #ifdef COAP_RESOURCES_NOHASH 479 unsigned char *buf,
size_t *len,
size_t *offset) {
480 unsigned char *p = buf;
481 const unsigned char *bufend = buf + *len;
484 const size_t old_offset = *offset;
515 if (result + old_offset - *offset < *len) {
522 #ifndef WITHOUT_OBSERVE 568 if (token && token->
length) {
635 debug(
"coap_check_notify: pdu init failed, resource stays partially dirty\n");
642 debug(
"coap_check_notify: cannot add token, resource stays partially dirty\n");
675 debug(
"coap_check_notify: sending failed, resource stays partially dirty\n");
728 #ifndef INET6_ADDRSTRLEN 729 #define INET6_ADDRSTRLEN 40 734 debug(
"** removed observer %s\n", addr);
#define LL_FOREACH(head, el)
unsigned int observe
The next value to be used for Observe.
coap_tid_t coap_send_confirmed(coap_context_t *context, const coap_endpoint_t *local_interface, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a confirmed CoAP message to given destination.
#define RESOURCES_DELETE(r, obj)
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]
int 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.
int coap_delete_resource(coap_context_t *context, coap_key_t key)
Deletes a resource identified by key.
multi-purpose address abstraction
#define COAP_PRINT_OUTPUT_LENGTH(v)
int coap_tid_t
coap_tid_t is used to store CoAP transaction id, i.e.
#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
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.
static int coap_option_setb(coap_opt_filter_t filter, unsigned short type)
Sets the corresponding bit for type in filter.
coap_hdr_t * hdr
Address of the first byte of the CoAP message.
static int match(const str *text, const str *pattern, int match_prefix, int match_substring)
#define COAP_OBS_MAX_FAIL
Number of confirmable notifications that may fail (i.e.
Abstraction of virtual endpoint that can be attached to coap_context_t.
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)
#define COAP_INVALID_TID
Indicates an invalid transaction id.
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.
#define RESOURCES_ITER(r, tmp)
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...
coap_key_t key
the actual key bytes for this resource
unsigned int dirty
set to 1 if resource has changed
#define COAP_MALLOC_TYPE(Type)
coap_tid_t coap_send(coap_context_t *context, const coap_endpoint_t *local_interface, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a non-confirmed CoAP message to given destination.
#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.
#define RESOURCES_ADD(r, obj)
Generic resource handling.
#define COAP_MAX_PDU_SIZE
coap_subscription_t * coap_add_observer(coap_resource_t *resource, const coap_endpoint_t *local_interface, const coap_address_t *observer, const str *token)
Adds the specified peer as observer for resource.
#define coap_hash(String, Length, Result)
static void coap_notify_observers(coap_context_t *context, coap_resource_t *r)
coap_subscription_t * subscribers
list of observers for this resource
uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE]
Fixed-size vector we use for option filtering.
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
#define COAP_RESOURCE_FLAGS_NOTIFY_CON
Notifications will be sent confirmable by default.
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 partially dirty f...
#define RESOURCES_FIND(r, k, res)
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.
#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.
void coap_delete_all_resources(coap_context_t *context)
Deletes all resources from given context and frees their storage.
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.
static void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
#define LL_DELETE(head, del)
#define COAP_PRINT_STATUS_ERROR
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
#define COAP_FREE_TYPE(Type, Object)
coap_print_status_t coap_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.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
unsigned char token[8]
token used for subscription
void coap_delete_attr(coap_attr_t *attr)
Deletes an attribute.
coap_endpoint_t local_if
local communication interface
#define COAP_PRINT_STATUS_TRUNC
void coap_subscription_init(coap_subscription_t *s)
#define COAP_RESOURCE_FLAGS_RELEASE_URI
The URI passed to coap_resource_init() is free'd by coap_delete_resource().
coap_log_t coap_get_log_level(void)
Returns the current log level.
void(* coap_method_handler_t)(coap_context_t *, struct coap_resource_t *, const coap_endpoint_t *, coap_address_t *, coap_pdu_t *, str *, coap_pdu_t *)
Definition of message handler function (.
void coap_handle_failed_notify(coap_context_t *context, const coap_address_t *peer, const str *token)
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 void coap_free_resource(coap_resource_t *resource)
#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.