libcoap(二)

从协议的角度结合代码来看
看下coap_context_t object
在main函数中首先定义了这个结构体变量指针
coap_context_t *ctx;
看下其定义:

/** 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;
  。。。。。。。
/** 
 * Fixed-size bit-vector we use for option filtering. It is large
 * enough to hold the highest option number known at build time (20 in
 * the core spec).
 */
typedef unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3) + 1];
#define COAP_MAX_OPT             63 /**< the highest option number we know */

已知的最大的option number是63 ,这里把所有已知的option的标志位放在一个unsigned char的数组中,数组没有元素是一个Byte(8 bits).所以可以用8个大小的数组来保存这些标志位 。其中右移3位就是 2^3 = 8 . 加1防止除不尽多增加一个元素。

怎么去对这个filter赋值呢?搜下这个known_options,可以找到下面这个函数。

/** 
 * Registers the option type @p type with the given context object @p
 * ctx.
 * 
 * @param ctx  The context to use.
 * @param type The option type to register.
 */
inline static void 
coap_register_option(coap_context_t *ctx, unsigned char type) {
  coap_option_setb(ctx->known_options, type);
}

看下这个函数在哪里调用

  /* register the critical options that we know */
  coap_register_option(c, COAP_OPTION_IF_MATCH);
  coap_register_option(c, COAP_OPTION_URI_HOST);
  coap_register_option(c, COAP_OPTION_IF_NONE_MATCH);
  coap_register_option(c, COAP_OPTION_URI_PORT);
  coap_register_option(c, COAP_OPTION_URI_PATH);
  coap_register_option(c, COAP_OPTION_URI_QUERY);
  coap_register_option(c, COAP_OPTION_ACCEPT);
  coap_register_option(c, COAP_OPTION_PROXY_URI);
  coap_register_option(c, COAP_OPTION_PROXY_SCHEME);
  coap_register_option(c, COAP_OPTION_BLOCK2);
  coap_register_option(c, COAP_OPTION_BLOCK1);

看起来很简单,直接对需要的option注册就可以。

进去看下 coap_option_setb

/** 
 * Sets the corresponding bit for @p type in @p filter. This function
 * returns @c 1 if bit was set or @c -1 on error (i.e. when the given
 * type does not fit in the filter).
 * 
 * @param filter The filter object to change.
 * @param type   The type for which the bit should be set. 
 * 
 * @return @c 1 if bit was set, @c -1 otherwise.
 */
inline static int
coap_option_setb(coap_opt_filter_t filter, unsigned short type) {
  return bits_setb((uint8_t *)filter, sizeof(coap_opt_filter_t), type);
}
/** 
 * Sets the bit @p bit in bit-vector @p vec. This function returns @c
 * 1 if bit was set or @c -1 on error (i.e. when the given bit does
 * not fit in the vector).
 * 
 * @param vec  The bit-vector to change.
 * @param size The size of @p vec in bytes.
 * @param bit  The bit to set in @p vec.
 * 
 * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
 */
inline static int
bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
  if (size <= (bit >> 3))
    return -1;

  *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07));
  return 1;
}

上面这个函数就是在known_options中对应的元素中置对应的option位.
说的可能不太明白.
比如:

coap_register_option(c, COAP_OPTION_URI_PATH);
#define COAP_OPTION_URI_PATH     11 /* C, String, 0-255 B, (none) */

调用到bits_setb

inline static int
bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
  if (size <= (bit >> 3))
    return -1;

  *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07));
  return 1;
}

c 就是申请的结构体

#ifdef WITH_POSIX
  coap_context_t *c = coap_malloc( sizeof( coap_context_t ) );
  int reuse = 1;
#endif /* WITH_POSIX */
  if (size <= (bit >> 3))
    return -1;

做一下判断,如果option的值太大,就不能存放在know_options这个数组中了,不然代码直接往下走会有溢出。

  *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07));
  return 1;

bit >> 3 先把这个type分下组,option小于8则在第0个数组元素中,小于16则在第1个元素中,小于32则在第2个元素中。
每个数组元素是unsigned char型的总共有8 bits.
那可以想象这个type(参数bit)对8 取余得到是分在哪组(第几个元素),余数是几就会被分在这个元素的第几位

这样就注册完了,当然libcoap中只是注册几个option,如果你想用其他的可以自己加。

看这个变量的名字就知道是个filter,可以想象代码中是用获取到的option和这个filter中的元素做比较,如果在这个filter中找到了对应的option说明是已知的option,否则就直接返回错误码,然后再做其他处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值