Add octet and character string buffer codecs to used with fixed size buffers that are not declared as BACNET_OCTET_STRING or BACNET_CHARACTER_STRING. (#1237)
This commit is contained in:
+605
-30
@@ -1394,6 +1394,31 @@ int encode_context_null(uint8_t *apdu, uint8_t tag_number)
|
||||
return encode_tag(apdu, tag_number, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the NULL value as application encoded
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed,
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_null_application_encode(uint8_t *apdu, uint32_t apdu_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_application_null(NULL);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_application_null(apdu);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the NULL value when application encoded
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
@@ -2224,6 +2249,283 @@ int encode_application_object_id(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value as application tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_OCTET_STRING, false, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String Value as context tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_context_octet_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(apdu, tag_number, true, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode an application tagged BACnet Octet String Value
|
||||
* From clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - value to encode
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_octet_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len =
|
||||
encode_application_octet_string_buffer(NULL, buffer, buffer_size);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_application_octet_string_buffer(apdu, buffer, buffer_size);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode an context tagged BACnet Octet String Value
|
||||
* From clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_octet_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_context_octet_string_buffer(
|
||||
NULL, tag_number, buffer, buffer_size);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_context_octet_string_buffer(
|
||||
apdu, tag_number, buffer, buffer_size);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the BACnet Octet String Value
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param len_value - number of bytes in the octet string value encoding,
|
||||
* may be zero
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes in the octet string value encoding (0..N)
|
||||
* or BACNET_STATUS_ERROR if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
size_t i;
|
||||
size_t copy_len;
|
||||
|
||||
if (len_value > apdu_size) {
|
||||
/* malformed */
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (apdu && buffer && buffer_size > 0) {
|
||||
/* copy only the available octets, up to the buffer size */
|
||||
copy_len = (len_value < buffer_size) ? (size_t)len_value : buffer_size;
|
||||
for (i = 0; i < copy_len; i++) {
|
||||
buffer[i] = apdu[i];
|
||||
}
|
||||
/* pad any remaining buffer space with zeros */
|
||||
for (i = copy_len; i < buffer_size; i++) {
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)len_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Octet String application encoding
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes decoded, zero if tag mismatch,
|
||||
* or #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.application &&
|
||||
(tag.number == BACNET_APPLICATION_TAG_OCTET_STRING)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_octet_string_buffer_decode(
|
||||
&apdu[len], apdu_size - apdu_len, tag.len_value_type, buffer,
|
||||
buffer_size);
|
||||
if (len >= 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Octet String application encoding
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param tag_value - context tag number expected
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes decoded, or zero if tag mismatch, or
|
||||
* #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.context && (tag.number == tag_value)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_octet_string_buffer_decode(
|
||||
&apdu[apdu_len], apdu_size - apdu_len, tag.len_value_type,
|
||||
buffer, buffer_size);
|
||||
if (len >= 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#if BACNET_USE_OCTETSTRING
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value
|
||||
@@ -2282,36 +2584,6 @@ int encode_application_octet_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value as application tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_OCTET_STRING, false, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String Value as context tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
@@ -2881,6 +3153,309 @@ int decode_context_character_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param value - the BACnetCharacterString buffer value to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed, or 0 if too large
|
||||
*/
|
||||
uint32_t encode_bacnet_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
uint32_t apdu_len = 1 /*encoding */;
|
||||
uint32_t i;
|
||||
|
||||
if (!value || !value->buffer) {
|
||||
return 0;
|
||||
}
|
||||
if (value->buffer_length > value->buffer_size) {
|
||||
return 0;
|
||||
}
|
||||
if (apdu) {
|
||||
apdu[0] = value->encoding;
|
||||
for (i = 0; i < value->buffer_length; i++) {
|
||||
apdu[1 + i] = value->buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += value->buffer_length;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as context tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param tag_number - context tag number to encode
|
||||
* @param char_string - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_context_character_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *char_string)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
uint32_t tag_len;
|
||||
|
||||
tag_len = encode_bacnet_character_string_buffer(NULL, char_string);
|
||||
if (tag_len == 0) {
|
||||
/* malformed, cannot be zero */
|
||||
return 0;
|
||||
}
|
||||
len = encode_tag(apdu, tag_number, true, tag_len);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
len = encode_bacnet_character_string_buffer(apdu, char_string);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as application tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param char_string - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_application_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *char_string)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
uint32_t tag_len;
|
||||
|
||||
tag_len = encode_bacnet_character_string_buffer(NULL, char_string);
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_CHARACTER_STRING, false, tag_len);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
len = encode_bacnet_character_string_buffer(apdu, char_string);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as application tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_character_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_application_character_string_buffer(NULL, value);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_application_character_string_buffer(apdu, value);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as context tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param value - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_character_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_context_character_string_buffer(NULL, tag_number, value);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_context_character_string_buffer(apdu, tag_number, value);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param len_value - number of bytes in the unsigned value encoding
|
||||
* @param value - the BACnetCharacterString buffer value to be encoded
|
||||
*
|
||||
* @return number of bytes decoded, or zero if malformed or APDU overflow.
|
||||
* String size overflow is detectable by the caller by comparing the
|
||||
* buffer size to the buffer length in the value.
|
||||
*/
|
||||
int bacnet_character_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
const char *string_value = NULL;
|
||||
uint32_t string_length = 0;
|
||||
int len = 0, i = 0;
|
||||
uint8_t encoding = 0;
|
||||
|
||||
if ((len_value > apdu_size) || (len_value == 0)) {
|
||||
/* malformed */
|
||||
return 0;
|
||||
}
|
||||
encoding = apdu[0];
|
||||
if (len_value > 1) {
|
||||
string_length = len_value - 1;
|
||||
}
|
||||
if (value) {
|
||||
value->encoding = encoding;
|
||||
value->buffer_length = string_length;
|
||||
if (value->buffer) {
|
||||
string_value = (const char *)&apdu[1];
|
||||
for (i = 0; i < value->buffer_size; i++) {
|
||||
if (i < string_length) {
|
||||
value->buffer[i] = string_value[i];
|
||||
} else {
|
||||
/* pad buffer */
|
||||
value->buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
len = (int)len_value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - the BACnetCharacterString buffer value to be decoded
|
||||
*
|
||||
* @return number of bytes decoded, zero if tag mismatch,
|
||||
* or #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_character_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.application &&
|
||||
(tag.number == BACNET_APPLICATION_TAG_CHARACTER_STRING)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_character_string_buffer_decode(
|
||||
&apdu[len], apdu_size - apdu_len, tag.len_value_type, value);
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param tag_value - context tag number expected
|
||||
* @param value - the BACnetCharacterString buffer value to be decoded
|
||||
*
|
||||
* @return number of bytes decoded, or zero if tag mismatch, or
|
||||
* #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_character_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.context && (tag.number == tag_value)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_character_string_buffer_decode(
|
||||
&apdu[apdu_len], apdu_size - apdu_len, tag.len_value_type,
|
||||
value);
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Unsigned value
|
||||
* from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||
|
||||
+98
-3
@@ -86,6 +86,19 @@ typedef struct BACnetTag {
|
||||
uint32_t len_value_type;
|
||||
} BACNET_TAG;
|
||||
|
||||
typedef struct BACnetCharacterStringBuffer {
|
||||
uint8_t encoding;
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
uint32_t buffer_length;
|
||||
} BACNET_CHARACTER_STRING_BUFFER;
|
||||
|
||||
typedef struct BACnetOctetStringBuffer {
|
||||
uint8_t *buffer;
|
||||
size_t buffer_size;
|
||||
uint32_t buffer_length;
|
||||
} BACNET_OCTET_STRING_BUFFER;
|
||||
|
||||
/* max size of a BACnet tag */
|
||||
#define BACNET_TAG_SIZE 7
|
||||
|
||||
@@ -183,6 +196,8 @@ int encode_application_null(uint8_t *apdu);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_null(uint8_t *apdu, uint8_t tag_number);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_application_encode(uint8_t *apdu, uint32_t apdu_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_application_decode(const uint8_t *apdu, uint32_t apdu_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_context_decode(
|
||||
@@ -384,15 +399,55 @@ bool bacnet_object_id_same(
|
||||
BACNET_OBJECT_TYPE object_type2,
|
||||
uint32_t instance2);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_octet_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_octet_string(uint8_t *apdu, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string(
|
||||
uint8_t *apdu, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_octet_string(
|
||||
uint8_t *apdu, uint8_t tag_number, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
@@ -431,6 +486,46 @@ uint32_t encode_bacnet_character_string_safe(
|
||||
const char *pString,
|
||||
uint32_t length);
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t encode_bacnet_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_character_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_bacnet_character_string(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
|
||||
Reference in New Issue
Block a user