coap_context_t中第二个成员变量
struct coap_resource_t *resources;
/** 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;
#ifndef WITH_CONTIKI
struct coap_resource_t *resources; /**< hash table or list of known resources */
#endif /* WITH_CONTIKI */
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 */
/**
* Used to store handlers for the four coap methods @c GET, @c POST,
* @c PUT, and @c DELETE. 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[4];
coap_key_t key; /**< the actual key bytes for this resource */
#ifndef WITH_CONTIKI
#ifdef COAP_RESOURCES_NOHASH
struct coap_resource_t *next;
#else
UT_hash_handle hh;
#endif
#endif /* WITH_CONTIKI */
#ifndef WITH_CONTIKI
coap_attr_t *link_attr; /**< attributes to be included with the link format */
#else /* WITH_CONTIKI */
LIST_STRUCT(link_attr); /**< attributes to be included with the link format */
#endif /* WITH_CONTIKI */
LIST_STRUCT(subscribers); /**< list of observers for this resource */
/**
* Request URI for this resource. This field will point into the
* static memory. */
str uri;
int flags;
} 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 */
这四个位与不懂,先不看
/**
* Used to store handlers for the four coap methods @c GET, @c POST,
* @c PUT, and @c DELETE. 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[4];
这个注释写的很清楚,针对GET POST PUT DELETE的四个handler,每个resource都可以有自己的4个handler
coap_key_t key; /**< the actual key bytes for this resource */
看下这个类型
typedef unsigned char coap_key_t[4];
是个含有4个unsigned char的数组,这个里面保存的是hash key,后续查找resource的时候是根据key来查询。来看下什么时候生成这个hash key
r = coap_resource_init((unsigned char *)"time", 4, 0);
coap_resource_t *
coap_resource_init(const unsigned char *uri, size_t len, int flags) {
coap_resource_t *r;
#ifdef WITH_POSIX
r = (coap_resource_t *)coap_malloc(sizeof(coap_resource_t));
#endif
#ifdef WITH_LWIP
r = (coap_resource_t *)memp_malloc(MEMP_COAP_RESOURCE);
#endif
#ifdef WITH_CONTIKI
r = (coap_resource_t *)memb_alloc(&resource_storage);
#endif
if (r) {
memset(r, 0, sizeof(coap_resource_t));
#ifdef WITH_CONTIKI
LIST_STRUCT_INIT(r, link_attr);
#endif /* WITH_CONTIKI */
LIST_STRUCT_INIT(r, subscribers);
r->uri.s = (unsigned char *)uri;
r->uri.length = len;
coap_hash_path(r->uri.s, r->uri.length, r->key);
r->flags = flags;
} else {
debug("coap_resource_init: no memory left\n");
}
return r;
}
int
coap_hash_path(const unsigned char *path, size_t len, coap_key_t key) {
coap_parse_iterator_t pi;
if (!path)
return 0;
memset(key, 0, sizeof(coap_key_t));
coap_parse_iterator_init((unsigned char *)path, len,
'/', (unsigned char *)"?#", 2, &pi);
coap_split_path_impl(&pi, hash_segment, key);
return 1;
}
/**
* Splits the given string into segments. You should call one of the
* macros coap_split_path() or coap_split_query() instead.
*
* @param parse_iter The iterator used for tokenizing.
* @param h A handler that is called with every token.
* @param data Opaque data that is passed to @p h when called.
*
* @return The number of characters that have been parsed from @p s.
*/
size_t
coap_split_path_impl(coap_parse_iterator_t *parse_iter,
segment_handler_t h, void *data) {
unsigned char *seg;
size_t length;
assert(parse_iter);
assert(h);
length = parse_iter->n;
while ( (seg = coap_parse_next(parse_iter)) ) {
/* any valid path segment is handled here: */
h(seg, parse_iter->segment_length, data);
}
return length - (parse_iter->n - parse_iter->segment_length);
}
/* hash URI path segments */
/* The function signature of coap_hash() is different from
* segment_handler_t hence we use this wrapper as safe typecast. */
static inline void
hash_segment(unsigned char *s, size_t len, void *data) {
coap_hash(s, len, data);
}
/**
* 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))
/* Caution: When changing this, update COAP_DEFAULT_WKC_HASHKEY
* accordingly (see int coap_hash_path());
*/
void
coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h) {
size_t j;
while (len--) {
j = sizeof(coap_key_t)-1;
while (j) {
h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j];
--j;
}
h[0] = (h[0] << 7) + h[0] + *s++;
}
}
coap_hash_impl这个函数就是实现hask key的生成
具体hash key的算法后面再单独开一个主题说一下。
UT_hash_handle hh;
这个就是构造hash的数据结构。
#ifndef WITH_CONTIKI
coap_attr_t *link_attr; /**< attributes to be included with the link format */
#else /* WITH_CONTIKI */
LIST_STRUCT(link_attr); /**< attributes to be included with the link format */
#endif /* WITH_CONTIKI */
WITH_CONTIKI没有定义,所以这里直接是一个指针变量,看下这个结构体
typedef struct coap_attr_t {
struct coap_attr_t *next;
str name;
str value;
int flags;
} coap_attr_t;
里面有自身的指针,一看就是会用链表
看下它是怎么初始化的
coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0);
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) {
coap_attr_t *attr;
if (!resource || !name)
return NULL;
#ifdef WITH_POSIX
attr = (coap_attr_t *)coap_malloc(sizeof(coap_attr_t));
#endif
#ifdef WITH_LWIP
attr = (coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR);
#endif
#ifdef WITH_CONTIKI
attr = (coap_attr_t *)memb_alloc(&attribute_storage);
#endif
if (attr) {
attr->name.length = nlen;
attr->value.length = val ? vlen : 0;
attr->name.s = (unsigned char *)name;
attr->value.s = (unsigned char *)val;
attr->flags = flags;
/* add attribute to resource list */
#ifndef WITH_CONTIKI
LL_PREPEND(resource->link_attr, attr);
#else /* WITH_CONTIKI */
list_add(resource->link_attr, attr);
#endif /* WITH_CONTIKI */
} else {
debug("coap_add_attr: no memory left\n");
}
return attr;
}
/******************************************************************************
* singly linked list macros (non-circular) *
*****************************************************************************/
#define LL_PREPEND(head,add) \
do { \
(add)->next = head; \
head = add; \
} while (0)
LL_PREPEND(resource->link_attr, attr);
可以看出都会”链入“resource的link_attr,目前还不理解这里的coap_attr_t有什么作用。Qustion????????
/**
* Request URI for this resource. This field will point into the
* static memory. */
str uri;
int flags;
typedef struct {
size_t length; /* length of string */
unsigned char *s; /* string data */
} str;
uri就是resource的标示,unsigned char * 型
flags目前这里没有用到。
好了,这个结构体介绍完了。