BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数
来源:互联网 发布:威瑞森数据泄露报告 编辑:程序博客网 时间:2024/06/06 09:51
在有了第一篇分析之后,whois_decode_service_request这个函数理解起来就简单很多了。
<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个字节。
0 0
- BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数
- BACnet WHO-IS服务协议栈代码分析(1)------whois_encode_apdu(....)函数
- 分析bacnet协议栈源码 AtomicReadFile 服务
- 分析bacnet协议栈中的Device Communication Control服务
- BACnet协议栈分析之Makefile文件
- BACnet协议栈移植分析之一:rs485.c
- BACnet协议栈移植分析之二:rs485.mak
- BACnet协议栈移植分析之三:mstpsnap.c
- BACnet协议
- 结合VTS和BACnet协议栈源码分析Write Property读属性
- 【BACnet】3.bacnet-stack-0.8.0工程与BACnet标准协议之间的代码关系(对象及应用服务)
- 【BACnet】4.bacnet-stack-0.8.0工程与BACnet标准协议之间的代码关系(网络层)
- BACnet 协议栈浅析(Java 版)之 BACnet 协议简介
- 使用VTS分析bacnet协议的ReadProperty(一)
- 使用VTS分析bacnet协议的ReadProperty(二)
- BACnet协议开发
- BACnet协议栈学习、研究的一点tips
- 利用VTS与bacnet协议栈进行通信---ReadProperty
- 个人笔记 -- 勿入
- http与https的区别
- B-tree/B+tree/B*tree
- CocoaLumberjack 学习纪录(六)
- 博弈论基础习题集
- BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数
- 调试Release发布版程序的Crash错误
- git的多账户公钥配置简略
- android studio 模拟器安装应用失败(INSTALL_FAILED_NO_MATCHING_ABIS)
- Hadoop2.7.2分布式部署2(创建hadoop用户配置ssh免密码登录)
- KVO与通知的区别
- Java for Web学习笔记(十八):Session(2)Session的使用
- linux内核设计与实现学习摘要
- Unity3d 原生录音 Microphone