From 30c186d7304f7c55d240240ed00c7cc212e9e86c Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 19 Jul 2007 18:27:03 +0000 Subject: [PATCH] Corrected ReadPropertyMultiple handler. Tested using VTS with demo/server running under linux. --- bacnet-stack/config.h | 4 +- bacnet-stack/demo/handler/h_rpm.c | 78 ++++++++++++++++++++---- bacnet-stack/demo/object/ai.c | 6 +- bacnet-stack/demo/object/ao.c | 6 +- bacnet-stack/demo/object/av.c | 6 +- bacnet-stack/demo/object/bacfile.c | 6 +- bacnet-stack/demo/object/bi.c | 6 +- bacnet-stack/demo/object/bo.c | 6 +- bacnet-stack/demo/object/bv.c | 6 +- bacnet-stack/demo/object/device.c | 6 +- bacnet-stack/demo/object/lc.c | 6 +- bacnet-stack/demo/object/lsp.c | 6 +- bacnet-stack/demo/object/mso.c | 6 +- bacnet-stack/rpm.c | 95 +++++++++++++++++------------- 14 files changed, 157 insertions(+), 86 deletions(-) diff --git a/bacnet-stack/config.h b/bacnet-stack/config.h index 7e7dc172..6af77078 100644 --- a/bacnet-stack/config.h +++ b/bacnet-stack/config.h @@ -10,8 +10,8 @@ /* 50 is the minimum; adjust to your memory and physical layer constraints */ /* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476 */ #ifndef MAX_APDU - #define MAX_APDU 50 - /* #define MAX_APDU 480 */ + /* #define MAX_APDU 50 */ +#define MAX_APDU 480 /* #define MAX_APDU 1476 */ #endif /* for confirmed messages, this is the number of transactions */ diff --git a/bacnet-stack/demo/handler/h_rpm.c b/bacnet-stack/demo/handler/h_rpm.c index d91e7dcf..dab2e9f2 100644 --- a/bacnet-stack/demo/handler/h_rpm.c +++ b/bacnet-stack/demo/handler/h_rpm.c @@ -75,6 +75,7 @@ static unsigned property_list_count(const int *pList) if (pList) { while (*pList != -1) { property_count++; + pList++; } } @@ -183,8 +184,10 @@ static int RPM_Object_Property( if (index < required) { property = pPropertyList->Required.pList[index]; } else if (index < (required + optional)) { + index -= required; property = pPropertyList->Optional.pList[index]; } else if (index < (required + optional + proprietary)) { + index -= (required + optional); property = pPropertyList->Proprietary.pList[index]; } } else if (special_property == PROP_REQUIRED) { @@ -458,13 +461,15 @@ void handler_read_property_multiple( service_data->invoke_id); do { - len = rpm_ack_decode_object_id( + len = rpm_decode_object_id( &service_request[decode_len], service_len - decode_len, &object_type, &object_instance); - /* error - end of object? */ - if (len < 0) { - len = rpm_ack_decode_object_end( + /* end of object? */ + if (len > 0) { + decode_len += len; + } else { + len = rpm_decode_object_end( &service_request[decode_len], service_len - decode_len); if (len == 1) { @@ -481,6 +486,8 @@ void handler_read_property_multiple( ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto RPM_ABORT; + } else { + apdu_len += copy_len; } } else { apdu_len = abort_encode_apdu( @@ -490,8 +497,6 @@ void handler_read_property_multiple( goto RPM_ABORT; } break; - } else { - decode_len += len; } len = rpm_ack_encode_apdu_object_begin( &Temp_Buf[0], @@ -507,6 +512,8 @@ void handler_read_property_multiple( ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto RPM_ABORT; + } else { + apdu_len += copy_len; } /* do each property of this object of the RPM request */ do @@ -516,11 +523,39 @@ void handler_read_property_multiple( service_len - decode_len, &object_property, &array_index); - /* error - end of property list? */ - if (len < 0) { - break; - } else { + /* end of property list? */ + if (len > 0) { 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 */ if ((object_property == PROP_ALL) || @@ -554,6 +589,8 @@ void handler_read_property_multiple( 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_Buf[0], @@ -583,10 +620,29 @@ void handler_read_property_multiple( ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto RPM_ABORT; + } else { + apdu_len += copy_len; } } } else { /* 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_Buf[0], object_type, @@ -615,6 +671,8 @@ void handler_read_property_multiple( ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto RPM_ABORT; + } else { + apdu_len += copy_len; } } } while(1); diff --git a/bacnet-stack/demo/object/ai.c b/bacnet-stack/demo/object/ai.c index af8dffcd..45eba145 100644 --- a/bacnet-stack/demo/object/ai.c +++ b/bacnet-stack/demo/object/ai.c @@ -68,11 +68,11 @@ void Analog_Input_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Analog_Input_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Analog_Input_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Analog_Input_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/ao.c b/bacnet-stack/demo/object/ao.c index 421a1bfb..092fc1b3 100644 --- a/bacnet-stack/demo/object/ao.c +++ b/bacnet-stack/demo/object/ao.c @@ -88,11 +88,11 @@ void Analog_Output_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Analog_Output_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Analog_Output_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Analog_Output_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/av.c b/bacnet-stack/demo/object/av.c index 43bf2f05..0f17b6bd 100644 --- a/bacnet-stack/demo/object/av.c +++ b/bacnet-stack/demo/object/av.c @@ -87,11 +87,11 @@ void Analog_Value_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Analog_Value_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Analog_Value_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Analog_Value_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/bacfile.c b/bacnet-stack/demo/object/bacfile.c index ecdb3f20..948dd672 100644 --- a/bacnet-stack/demo/object/bacfile.c +++ b/bacnet-stack/demo/object/bacfile.c @@ -83,11 +83,11 @@ void BACfile_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = bacfile_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = bacfile_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = bacfile_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/bi.c b/bacnet-stack/demo/object/bi.c index c5799b97..c0df5882 100644 --- a/bacnet-stack/demo/object/bi.c +++ b/bacnet-stack/demo/object/bi.c @@ -67,11 +67,11 @@ void Binary_Input_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Binary_Input_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Binary_Input_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Binary_Input_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/bo.c b/bacnet-stack/demo/object/bo.c index dece631b..25a017e1 100644 --- a/bacnet-stack/demo/object/bo.c +++ b/bacnet-stack/demo/object/bo.c @@ -79,11 +79,11 @@ void Binary_Output_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Binary_Output_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Binary_Output_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Binary_Output_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/bv.c b/bacnet-stack/demo/object/bv.c index 13abeb16..120cb6fc 100644 --- a/bacnet-stack/demo/object/bv.c +++ b/bacnet-stack/demo/object/bv.c @@ -78,11 +78,11 @@ void Binary_Value_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Binary_Value_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Binary_Value_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Binary_Value_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 950759f6..d7ea6703 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -97,11 +97,11 @@ void Device_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Device_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Device_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Device_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/lc.c b/bacnet-stack/demo/object/lc.c index 25d82c2c..9f4af76b 100644 --- a/bacnet-stack/demo/object/lc.c +++ b/bacnet-stack/demo/object/lc.c @@ -175,11 +175,11 @@ void Load_Control_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Load_Control_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Load_Control_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Load_Control_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/lsp.c b/bacnet-stack/demo/object/lsp.c index c3b3c8be..b282e7d4 100644 --- a/bacnet-stack/demo/object/lsp.c +++ b/bacnet-stack/demo/object/lsp.c @@ -84,11 +84,11 @@ void Life_Safety_Point_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Life_Safety_Point_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Life_Safety_Point_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Life_Safety_Point_Properties_Proprietary; return; diff --git a/bacnet-stack/demo/object/mso.c b/bacnet-stack/demo/object/mso.c index 73fef351..633fc4ff 100644 --- a/bacnet-stack/demo/object/mso.c +++ b/bacnet-stack/demo/object/mso.c @@ -84,11 +84,11 @@ void Multistate_Output_Property_Lists( const int **pOptional, const int **pProprietary) { - if (*pRequired) + if (pRequired) *pRequired = Multistate_Output_Properties_Required; - if (*pOptional) + if (pOptional) *pOptional = Multistate_Output_Properties_Optional; - if (*pProprietary) + if (pProprietary) *pProprietary = Multistate_Output_Properties_Proprietary; return; diff --git a/bacnet-stack/rpm.c b/bacnet-stack/rpm.c index e4aa69fc..e7539e2e 100644 --- a/bacnet-stack/rpm.c +++ b/bacnet-stack/rpm.c @@ -156,6 +156,8 @@ int rpm_decode_object_property(uint8_t * apdu, /* check for valid pointers */ if (apdu && apdu_len && object_property && array_index) { /* Tag 0: propertyIdentifier */ + if (!decode_is_context_specific(&apdu[len])) + return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 0) @@ -164,7 +166,9 @@ int rpm_decode_object_property(uint8_t * apdu, if (object_property) *object_property = (BACNET_PROPERTY_ID)property; /* 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 = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); @@ -182,34 +186,6 @@ int rpm_decode_object_property(uint8_t * apdu, 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 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 */ if (apdu && apdu_len && object_property && array_index) { /* Tag 2: propertyIdentifier */ + if (!decode_is_context_specific(&apdu[len])) + return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 2) @@ -362,20 +340,32 @@ int rpm_ack_decode_object_property(uint8_t * apdu, if (object_property) *object_property = (BACNET_PROPERTY_ID)property; /* Tag 3: Optional propertyArrayIndex */ - tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, - &len_value_type); - if (tag_number == 3) { - len += tag_len; - len += decode_unsigned(&apdu[len], len_value_type, - &array_value); - *array_index = array_value; - } else + if ((len < apdu_len) && + decode_is_context_specific(&apdu[len]) && + (!decode_is_closing_tag(&apdu[len]))) { + tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, + &len_value_type); + if (tag_number == 3) { + len += tag_len; + 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; + } } return (int) len; } +#ifdef TEST +#include +#include +#include "ctest.h" + int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the apdu */ uint8_t * invoke_id, 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; } -#ifdef TEST -#include -#include -#include "ctest.h" +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; +} void testReadPropertyMultiple(Test * pTest) {