BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数
2016-03-10 10:17
621 查看
在有了第一篇分析之后,whois_decode_service_request这个函数理解起来就简单很多了。
首先,来看看len的值是怎样得到的。首先通过调用decode_tag_number_and_value(...),在这个函数里,先调用了decode_tag_number(...)。
这个函数主要用于判断这个编码的标记号编码是否存在扩展标记,如果是扩展标记,则返回2个字节长度,不是扩展标记则返回1个字节长度。在获得了标记的字节长度之后。回到decode_tag_number_and_value(...):
65535]之间,并且其后要附加两个字节,因此,需要调用decode_unsigned16(...)来分配两个字节的空间,要注意的是,在decode_unsigned16(...)中,还存在一个大端转小端的过程。同理,可以得知当存储的是D'255'的时候的情况。
在判断完是否有扩展值之后,需要判断这个编码是否为“构件”,“构件”元素是指编码的数据结构中包含有标记元素的,其中,标记元素包括"opening"和"closing"。如果是"opening"标记,那么长度/值/类型域将被设置为B‘110’,如果是"closing"标记,那么长度/值/类型域将被设置为B‘111’。最后,返回了的长度包括了tag和value的长度。回到who_is_decode_service_request(....)这个函数.
比较此时apdu的长度与传入的参数apdu_len,如果比apdu_len要小,则说明需要设置设备阈值的范围。在16.9.1.1.1小节提到" 如果 '设备实例低阈值范围' 参数存在,则 ' 设备实例高阈值范围 ' 也必须存在
"。因此,在whois_decode_service_request(....)的21~25是先判断设备实例低阈值,26~43则是判断设备实例高阈值。由于设备低阈值与设备高阈值是成对出现的缘故,因此,当没有设置这两个阈值的值的时候,将其值设置为-1并且返回0个字节。
<strong>1 、int whois_decode_service_request( 2 、 uint8_t * apdu, 3 、 unsigned apdu_len, 4 、 int32_t * pLow_limit, 5 、 int32_t * pHigh_limit) 6 、{ 7 、 int len = 0; 8 、 uint8_t tag_number = 0; 9 、 uint32_t len_value = 0; 10、 uint32_t decoded_value = 0; 11、 12、 /* optional limits - must be used as a pair */ 13、 if (apdu_len) { 14、 len += 15、 decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); 16、 if (tag_number != 0) { 17、 return BACNET_STATUS_ERROR; 18、 } 19、 if (apdu_len > len) { 20、 len += decode_unsigned(&apdu[len], len_value, &decoded_value); 21、 if (decoded_value <= BACNET_MAX_INSTANCE) { 22、 if (pLow_limit) { 23、 *pLow_limit = decoded_value; 24、 } 25、 } 26、 if (apdu_len > len) { 27、 len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); 28、 if (tag_number != 1) { 29、 return BACNET_STATUS_ERROR; 30、 } 31、 if (apdu_len > len) { 32、 len += decode_unsigned(&apdu[len], len_value, &decoded_value); 33、 if (decoded_value <= BACNET_MAX_INSTANCE) { 34、 if (pHigh_limit) { 35、 *pHigh_limit = decoded_value; 36、 } 37、 } 38、 } else { 39、 return BACNET_STATUS_ERROR; 40、 } 41、 } else { 42、 return BACNET_STATUS_ERROR; 43、 } 44、 } else { 45、 return BACNET_STATUS_ERROR; 46、 } 47、 } else { 48、 if (pLow_limit) { 49、 *pLow_limit = -1; 50、 } 51、 if (pHigh_limit) { 52、 *pHigh_limit = -1; 53、 } 54、 len = 0; 55、 } 56、 57、 return len; 58、}</strong>
首先,来看看len的值是怎样得到的。首先通过调用decode_tag_number_and_value(...),在这个函数里,先调用了decode_tag_number(...)。
<strong>int decode_tag_number( uint8_t * apdu, uint8_t * tag_number) { int len = 1; /* return value */ /* decode the tag number first */ if (IS_EXTENDED_TAG_NUMBER(apdu[0])) { /* extended tag */ if (tag_number) { *tag_number = apdu[1]; } len++; } else { if (tag_number) { *tag_number = (uint8_t) (apdu[0] >> 4); } } return len; }</strong>
这个函数主要用于判断这个编码的标记号编码是否存在扩展标记,如果是扩展标记,则返回2个字节长度,不是扩展标记则返回1个字节长度。在获得了标记的字节长度之后。回到decode_tag_number_and_value(...):
<strong>1、int decode_tag_number_and_value( 2、 uint8_t * apdu, 3、 uint8_t * tag_number, 4、 uint32_t * value) 5、{ 6、 int len = 1; 7、 uint16_t value16; 8、 uint32_t value32; 9、 10、 len = decode_tag_number(&apdu[0], tag_number); 11、 if (IS_EXTENDED_VALUE(apdu[0])) { 12、 /* tagged as uint32_t */ 13、 if (apdu[len] == 255) { 14、 len++; 15、 len += decode_unsigned32(&apdu[len], &value32); 16、 if (value) { 17、 *value = value32; 18、 } 19、 } 20、 /* tagged as uint16_t */ 21、 else if (apdu[len] == 254) { 22、 len++; 23、 len += decode_unsigned16(&apdu[len], &value16); 24、 if (value) { 25、 *value = value16; 26、 } 27、 } 28、 /* no tag - must be uint8_t */ 29、 else { 30、 if (value) { 31、 *value = apdu[len]; 32、 } 33、 len++; 34、 } 35、 } else if (IS_OPENING_TAG(apdu[0]) && value) { 36、 *value = 0; 37、 } else if (IS_CLOSING_TAG(apdu[0]) && value) { 38、 /* closing tag */ 39、 *value = 0; 40、 } else if (value) { 41、 /* small value */ 42、 *value = apdu[0] & 0x07; 43、 } 44、 45、 return len; 46、}</strong>在得到了标记号的长度之后,就通过调用 IS_EXTENDED_VALUE 这个宏得到的值来判断其扩展值有没有被使用。这个是用于原语数据的判断,IS_EXTENDED_VALUE(x) ((x & 0x07) == 5) 。 在 20.2.1.3.1 小节中,定义了对于长度在大于5的字节,其主字节的长度/值/类型域被设置为B'101'。然后判断下一个字节,如果是存在扩展值得话,那么接下来这个字节存储的是D'254'或D'255'。当存储的是D'254'时,则表示该数据长度在[254,
65535]之间,并且其后要附加两个字节,因此,需要调用decode_unsigned16(...)来分配两个字节的空间,要注意的是,在decode_unsigned16(...)中,还存在一个大端转小端的过程。同理,可以得知当存储的是D'255'的时候的情况。
在判断完是否有扩展值之后,需要判断这个编码是否为“构件”,“构件”元素是指编码的数据结构中包含有标记元素的,其中,标记元素包括"opening"和"closing"。如果是"opening"标记,那么长度/值/类型域将被设置为B‘110’,如果是"closing"标记,那么长度/值/类型域将被设置为B‘111’。最后,返回了的长度包括了tag和value的长度。回到who_is_decode_service_request(....)这个函数.
比较此时apdu的长度与传入的参数apdu_len,如果比apdu_len要小,则说明需要设置设备阈值的范围。在16.9.1.1.1小节提到" 如果 '设备实例低阈值范围' 参数存在,则 ' 设备实例高阈值范围 ' 也必须存在
"。因此,在whois_decode_service_request(....)的21~25是先判断设备实例低阈值,26~43则是判断设备实例高阈值。由于设备低阈值与设备高阈值是成对出现的缘故,因此,当没有设置这两个阈值的值的时候,将其值设置为-1并且返回0个字节。
相关文章推荐
- iOS之获取UITableViewCell中UITextField的关联方法
- ios开发UI篇-iOS应用数据存储方式(XML属性列表 -plist)e二
- UE小用法
- UITableView 去掉多余行数、Cell系统分割线顶头
- 关于request.getServletPort()获取访问地址的说明
- string拼接和StringBuilder性能对比
- Explicit Interface Implementation (C# Programming Guide)
- String,StringBuilder,StringBuffer的区别
- [LeetCode]62. Unique Paths
- Interfaces (C# Programming Guide)
- 修改UIcontrollerTableView某一行的高度
- KVC中setValuesForKeysWithDictionary:
- LeetCode Distinct Subsequences
- 背水一战 Windows 10 (2) - UI: 概述, 启动屏幕, 屏幕方向
- build st-crowd
- MathType requires a newer version of MT Extra等MathType问题的不兼容性解决方案
- UIWindow 实现遮盖导航条的蒙版
- Mysql 连接数据库超时设置autoReconnect=true
- @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
- jquer “$” 扩展(笔记)