Corrected ReadPropertyMultiple handler. Tested using VTS with demo/server running under linux.

This commit is contained in:
skarg
2007-07-19 18:27:03 +00:00
parent 032a78bb2a
commit 30c186d730
14 changed files with 157 additions and 86 deletions
+2 -2
View File
@@ -10,8 +10,8 @@
/* 50 is the minimum; adjust to your memory and physical layer constraints */ /* 50 is the minimum; adjust to your memory and physical layer constraints */
/* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476 */ /* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476 */
#ifndef MAX_APDU #ifndef MAX_APDU
#define MAX_APDU 50 /* #define MAX_APDU 50 */
/* #define MAX_APDU 480 */ #define MAX_APDU 480
/* #define MAX_APDU 1476 */ /* #define MAX_APDU 1476 */
#endif #endif
/* for confirmed messages, this is the number of transactions */ /* for confirmed messages, this is the number of transactions */
+68 -10
View File
@@ -75,6 +75,7 @@ static unsigned property_list_count(const int *pList)
if (pList) { if (pList) {
while (*pList != -1) { while (*pList != -1) {
property_count++; property_count++;
pList++;
} }
} }
@@ -183,8 +184,10 @@ static int RPM_Object_Property(
if (index < required) { if (index < required) {
property = pPropertyList->Required.pList[index]; property = pPropertyList->Required.pList[index];
} else if (index < (required + optional)) { } else if (index < (required + optional)) {
index -= required;
property = pPropertyList->Optional.pList[index]; property = pPropertyList->Optional.pList[index];
} else if (index < (required + optional + proprietary)) { } else if (index < (required + optional + proprietary)) {
index -= (required + optional);
property = pPropertyList->Proprietary.pList[index]; property = pPropertyList->Proprietary.pList[index];
} }
} else if (special_property == PROP_REQUIRED) { } else if (special_property == PROP_REQUIRED) {
@@ -458,13 +461,15 @@ void handler_read_property_multiple(
service_data->invoke_id); service_data->invoke_id);
do do
{ {
len = rpm_ack_decode_object_id( len = rpm_decode_object_id(
&service_request[decode_len], &service_request[decode_len],
service_len - decode_len, service_len - decode_len,
&object_type, &object_instance); &object_type, &object_instance);
/* error - end of object? */ /* end of object? */
if (len < 0) { if (len > 0) {
len = rpm_ack_decode_object_end( decode_len += len;
} else {
len = rpm_decode_object_end(
&service_request[decode_len], &service_request[decode_len],
service_len - decode_len); service_len - decode_len);
if (len == 1) { if (len == 1) {
@@ -481,6 +486,8 @@ void handler_read_property_multiple(
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
goto RPM_ABORT; goto RPM_ABORT;
} else {
apdu_len += copy_len;
} }
} else { } else {
apdu_len = abort_encode_apdu( apdu_len = abort_encode_apdu(
@@ -490,8 +497,6 @@ void handler_read_property_multiple(
goto RPM_ABORT; goto RPM_ABORT;
} }
break; break;
} else {
decode_len += len;
} }
len = rpm_ack_encode_apdu_object_begin( len = rpm_ack_encode_apdu_object_begin(
&Temp_Buf[0], &Temp_Buf[0],
@@ -507,6 +512,8 @@ void handler_read_property_multiple(
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
goto RPM_ABORT; goto RPM_ABORT;
} else {
apdu_len += copy_len;
} }
/* do each property of this object of the RPM request */ /* do each property of this object of the RPM request */
do do
@@ -516,11 +523,39 @@ void handler_read_property_multiple(
service_len - decode_len, service_len - decode_len,
&object_property, &object_property,
&array_index); &array_index);
/* error - end of property list? */ /* end of property list? */
if (len < 0) { if (len > 0) {
break;
} else {
decode_len += len; decode_len += len;
} else {
len = rpm_decode_object_end(
&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RPM_ABORT;
} else {
apdu_len += copy_len;
}
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER, true);
goto RPM_ABORT;
}
/* stop decoding properties */
break;
} }
/* handle the special properties */ /* handle the special properties */
if ((object_property == PROP_ALL) || if ((object_property == PROP_ALL) ||
@@ -554,6 +589,8 @@ void handler_read_property_multiple(
service_data->invoke_id, service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT; goto RPM_ABORT;
} else {
apdu_len += copy_len;
} }
application_data_len = Encode_Property_APDU( application_data_len = Encode_Property_APDU(
&Application_Buf[0], &Application_Buf[0],
@@ -583,10 +620,29 @@ void handler_read_property_multiple(
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
goto RPM_ABORT; goto RPM_ABORT;
} else {
apdu_len += copy_len;
} }
} }
} else { } else {
/* handle an individual property */ /* handle an individual property */
len = rpm_ack_encode_apdu_object_property(
&Temp_Buf[0],
object_property,
array_index);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
} else {
apdu_len += copy_len;
}
application_data_len = Encode_Property_APDU( application_data_len = Encode_Property_APDU(
&Application_Buf[0], &Application_Buf[0],
object_type, object_type,
@@ -615,6 +671,8 @@ void handler_read_property_multiple(
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
goto RPM_ABORT; goto RPM_ABORT;
} else {
apdu_len += copy_len;
} }
} }
} while(1); } while(1);
+3 -3
View File
@@ -68,11 +68,11 @@ void Analog_Input_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Analog_Input_Properties_Required; *pRequired = Analog_Input_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Analog_Input_Properties_Optional; *pOptional = Analog_Input_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Analog_Input_Properties_Proprietary; *pProprietary = Analog_Input_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -88,11 +88,11 @@ void Analog_Output_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Analog_Output_Properties_Required; *pRequired = Analog_Output_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Analog_Output_Properties_Optional; *pOptional = Analog_Output_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Analog_Output_Properties_Proprietary; *pProprietary = Analog_Output_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -87,11 +87,11 @@ void Analog_Value_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Analog_Value_Properties_Required; *pRequired = Analog_Value_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Analog_Value_Properties_Optional; *pOptional = Analog_Value_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Analog_Value_Properties_Proprietary; *pProprietary = Analog_Value_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -83,11 +83,11 @@ void BACfile_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = bacfile_Properties_Required; *pRequired = bacfile_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = bacfile_Properties_Optional; *pOptional = bacfile_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = bacfile_Properties_Proprietary; *pProprietary = bacfile_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -67,11 +67,11 @@ void Binary_Input_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Binary_Input_Properties_Required; *pRequired = Binary_Input_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Binary_Input_Properties_Optional; *pOptional = Binary_Input_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Binary_Input_Properties_Proprietary; *pProprietary = Binary_Input_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -79,11 +79,11 @@ void Binary_Output_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Binary_Output_Properties_Required; *pRequired = Binary_Output_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Binary_Output_Properties_Optional; *pOptional = Binary_Output_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Binary_Output_Properties_Proprietary; *pProprietary = Binary_Output_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -78,11 +78,11 @@ void Binary_Value_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Binary_Value_Properties_Required; *pRequired = Binary_Value_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Binary_Value_Properties_Optional; *pOptional = Binary_Value_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Binary_Value_Properties_Proprietary; *pProprietary = Binary_Value_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -97,11 +97,11 @@ void Device_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Device_Properties_Required; *pRequired = Device_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Device_Properties_Optional; *pOptional = Device_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Device_Properties_Proprietary; *pProprietary = Device_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -175,11 +175,11 @@ void Load_Control_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Load_Control_Properties_Required; *pRequired = Load_Control_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Load_Control_Properties_Optional; *pOptional = Load_Control_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Load_Control_Properties_Proprietary; *pProprietary = Load_Control_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -84,11 +84,11 @@ void Life_Safety_Point_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Life_Safety_Point_Properties_Required; *pRequired = Life_Safety_Point_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Life_Safety_Point_Properties_Optional; *pOptional = Life_Safety_Point_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Life_Safety_Point_Properties_Proprietary; *pProprietary = Life_Safety_Point_Properties_Proprietary;
return; return;
+3 -3
View File
@@ -84,11 +84,11 @@ void Multistate_Output_Property_Lists(
const int **pOptional, const int **pOptional,
const int **pProprietary) const int **pProprietary)
{ {
if (*pRequired) if (pRequired)
*pRequired = Multistate_Output_Properties_Required; *pRequired = Multistate_Output_Properties_Required;
if (*pOptional) if (pOptional)
*pOptional = Multistate_Output_Properties_Optional; *pOptional = Multistate_Output_Properties_Optional;
if (*pProprietary) if (pProprietary)
*pProprietary = Multistate_Output_Properties_Proprietary; *pProprietary = Multistate_Output_Properties_Proprietary;
return; return;
+54 -41
View File
@@ -156,6 +156,8 @@ int rpm_decode_object_property(uint8_t * apdu,
/* check for valid pointers */ /* check for valid pointers */
if (apdu && apdu_len && object_property && array_index) { if (apdu && apdu_len && object_property && array_index) {
/* Tag 0: propertyIdentifier */ /* Tag 0: propertyIdentifier */
if (!decode_is_context_specific(&apdu[len]))
return -1;
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number != 0) if (tag_number != 0)
@@ -164,7 +166,9 @@ int rpm_decode_object_property(uint8_t * apdu,
if (object_property) if (object_property)
*object_property = (BACNET_PROPERTY_ID)property; *object_property = (BACNET_PROPERTY_ID)property;
/* Tag 1: Optional propertyArrayIndex */ /* Tag 1: Optional propertyArrayIndex */
if (len < apdu_len) { if ((len < apdu_len) &&
decode_is_context_specific(&apdu[len]) &&
(!decode_is_closing_tag(&apdu[len]))) {
option_len = option_len =
decode_tag_number_and_value(&apdu[len], &tag_number, decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type); &len_value_type);
@@ -182,34 +186,6 @@ int rpm_decode_object_property(uint8_t * apdu,
return (int) len; return (int) len;
} }
int rpm_decode_apdu(uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t ** service_request, unsigned *service_request_len)
{
unsigned offset = 0;
if (!apdu)
return -1;
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE)
return -1;
offset = 4;
if (apdu_len > offset) {
if (service_request)
*service_request = &apdu[offset];
if (service_request_len)
*service_request_len = apdu_len - offset;
}
return offset;
}
int rpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id) int rpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
@@ -354,6 +330,8 @@ int rpm_ack_decode_object_property(uint8_t * apdu,
/* check for valid pointers */ /* check for valid pointers */
if (apdu && apdu_len && object_property && array_index) { if (apdu && apdu_len && object_property && array_index) {
/* Tag 2: propertyIdentifier */ /* Tag 2: propertyIdentifier */
if (!decode_is_context_specific(&apdu[len]))
return -1;
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number != 2) if (tag_number != 2)
@@ -362,20 +340,32 @@ int rpm_ack_decode_object_property(uint8_t * apdu,
if (object_property) if (object_property)
*object_property = (BACNET_PROPERTY_ID)property; *object_property = (BACNET_PROPERTY_ID)property;
/* Tag 3: Optional propertyArrayIndex */ /* Tag 3: Optional propertyArrayIndex */
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, if ((len < apdu_len) &&
&len_value_type); decode_is_context_specific(&apdu[len]) &&
if (tag_number == 3) { (!decode_is_closing_tag(&apdu[len]))) {
len += tag_len; tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
len += decode_unsigned(&apdu[len], len_value_type, &len_value_type);
&array_value); if (tag_number == 3) {
*array_index = array_value; len += tag_len;
} else len += decode_unsigned(&apdu[len], len_value_type,
&array_value);
*array_index = array_value;
} else {
*array_index = BACNET_ARRAY_ALL;
}
} else {
*array_index = BACNET_ARRAY_ALL; *array_index = BACNET_ARRAY_ALL;
}
} }
return (int) len; return (int) len;
} }
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the apdu */ int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the apdu */
uint8_t * invoke_id, uint8_t * invoke_id,
uint8_t ** service_request, unsigned *service_request_len) uint8_t ** service_request, unsigned *service_request_len)
@@ -401,10 +391,33 @@ int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the a
return offset; return offset;
} }
#ifdef TEST int rpm_decode_apdu(uint8_t * apdu,
#include <assert.h> unsigned apdu_len,
#include <string.h> uint8_t * invoke_id,
#include "ctest.h" uint8_t ** service_request, unsigned *service_request_len)
{
unsigned offset = 0;
if (!apdu)
return -1;
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE)
return -1;
offset = 4;
if (apdu_len > offset) {
if (service_request)
*service_request = &apdu[offset];
if (service_request_len)
*service_request_len = apdu_len - offset;
}
return offset;
}
void testReadPropertyMultiple(Test * pTest) void testReadPropertyMultiple(Test * pTest)
{ {