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 */
/* 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 */
+68 -10
View File
@@ -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);
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+54 -41
View File
@@ -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 <assert.h>
#include <string.h>
#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 <assert.h>
#include <string.h>
#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)
{