您的位置:首页 > 产品设计 > UI/UE

BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数

2016-03-10 10:17 621 查看
在有了第一篇分析之后,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个字节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: