From 987e28d5151675a35a642b15afcff3211c37abba Mon Sep 17 00:00:00 2001 From: skarg Date: Tue, 15 Jun 2010 14:58:27 +0000 Subject: [PATCH] Modified the ReadProperty, ReadPropertyMultiple, and WriteProperty demo applications to check source address and invoke ID on the returning acknowledge to prevent printing responses not intended for this client. --- bacnet-stack/demo/handler/h_rp_a.c | 4 +- bacnet-stack/demo/handler/h_rpm_a.c | 11 ++- bacnet-stack/demo/readprop/main.c | 86 +++++++++++++------ bacnet-stack/demo/readpropm/main.c | 129 ++++++++++++++++++++++------ bacnet-stack/demo/writeprop/main.c | 59 +++++++------ bacnet-stack/include/handlers.h | 6 ++ 6 files changed, 205 insertions(+), 90 deletions(-) diff --git a/bacnet-stack/demo/handler/h_rp_a.c b/bacnet-stack/demo/handler/h_rp_a.c index bb2563f9..e684a6c3 100644 --- a/bacnet-stack/demo/handler/h_rp_a.c +++ b/bacnet-stack/demo/handler/h_rp_a.c @@ -47,7 +47,7 @@ /** For debugging... * @param [in] data portion of the ACK */ -static void PrintReadPropertyData( +void rp_ack_print_data( BACNET_READ_PROPERTY_DATA * data) { BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */ @@ -123,7 +123,7 @@ void handler_read_property_ack( fprintf(stderr, "Received Read-Property Ack!\n"); #endif if (len > 0) - PrintReadPropertyData(&data); + rp_ack_print_data(&data); } /** Decode the received RP data into a linked list of the results, with the diff --git a/bacnet-stack/demo/handler/h_rpm_a.c b/bacnet-stack/demo/handler/h_rpm_a.c index 4e357709..e634dca3 100644 --- a/bacnet-stack/demo/handler/h_rpm_a.c +++ b/bacnet-stack/demo/handler/h_rpm_a.c @@ -200,7 +200,7 @@ int rpm_ack_decode_service_request( } /* for debugging... */ -static void PrintReadPropertyMultipleData( +void rpm_ack_print_data( BACNET_READ_ACCESS_DATA * rpm_data) { BACNET_PROPERTY_REFERENCE *listOfProperties; @@ -275,17 +275,16 @@ static void PrintReadPropertyMultipleData( } } - /** Handler for a ReadPropertyMultiple ACK. * @ingroup DSRPM * For each read property, print out the ACK'd data for debugging, * and free the request data items from linked property list. - * + * * @param service_request [in] The contents of the service request. * @param service_len [in] The length of the service_request. * @param src [in] BACNET_ADDRESS of the source of the message - * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information - * decoded from the APDU header of this message. + * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information + * decoded from the APDU header of this message. */ void handler_read_property_multiple_ack( uint8_t * service_request, @@ -315,7 +314,7 @@ void handler_read_property_multiple_ack( #endif if (len > 0) { while (rpm_data) { - PrintReadPropertyMultipleData(rpm_data); + rpm_ack_print_data(rpm_data); rpm_property = rpm_data->listOfProperties; while (rpm_property) { value = rpm_property->value; diff --git a/bacnet-stack/demo/readprop/main.c b/bacnet-stack/demo/readprop/main.c index c15451f4..ac86bd04 100644 --- a/bacnet-stack/demo/readprop/main.c +++ b/bacnet-stack/demo/readprop/main.c @@ -56,13 +56,14 @@ /* buffer used for receive */ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; -/* global variables used in this file */ +/* converted command line arguments */ static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE; static uint32_t Target_Object_Instance = BACNET_MAX_INSTANCE; static BACNET_OBJECT_TYPE Target_Object_Type = OBJECT_ANALOG_INPUT; static BACNET_PROPERTY_ID Target_Object_Property = PROP_ACKED_TRANSITIONS; static int32_t Target_Object_Index = BACNET_ARRAY_ALL; - +/* the invoke id is needed to filter incoming messages */ +static uint8_t Request_Invoke_ID = 0; static BACNET_ADDRESS Target_Address; static bool Error_Detected = false; @@ -72,13 +73,13 @@ static void MyErrorHandler( BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Error: %s: %s\r\n", - bactext_error_class_name((int) error_class), - bactext_error_code_name((int) error_code)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Error: %s: %s\r\n", + bactext_error_class_name((int) error_class), + bactext_error_code_name((int) error_code)); + Error_Detected = true; + } } void MyAbortHandler( @@ -87,13 +88,13 @@ void MyAbortHandler( uint8_t abort_reason, bool server) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; (void) server; - printf("BACnet Abort: %s\r\n", - bactext_abort_reason_name((int) abort_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Abort: %s\r\n", + bactext_abort_reason_name((int) abort_reason)); + Error_Detected = true; + } } void MyRejectHandler( @@ -101,12 +102,42 @@ void MyRejectHandler( uint8_t invoke_id, uint8_t reject_reason) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Reject: %s\r\n", - bactext_reject_reason_name((int) reject_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Reject: %s\r\n", + bactext_reject_reason_name((int) reject_reason)); + Error_Detected = true; + } +} + +/** Handler for a ReadProperty ACK. + * @ingroup DSRP + * Doesn't actually do anything, except, for debugging, to + * print out the ACK data of a matching request. + * + * @param service_request [in] The contents of the service request. + * @param service_len [in] The length of the service_request. + * @param src [in] BACNET_ADDRESS of the source of the message + * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information + * decoded from the APDU header of this message. + */ +void My_Read_Property_Ack_Handler( + uint8_t * service_request, + uint16_t service_len, + BACNET_ADDRESS * src, + BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data) +{ + int len = 0; + BACNET_READ_PROPERTY_DATA data; + + if (address_match(&Target_Address, src) && + (service_data->invoke_id == Request_Invoke_ID)) { + len = rp_ack_decode_service_request( + service_request, service_len, &data); + if (len > 0) { + rp_ack_print_data(&data); + } + } } static void Init_Service_Handlers( @@ -127,7 +158,7 @@ static void Init_Service_Handlers( handler_read_property); /* handle the data coming back from confirmed requests */ apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY, - handler_read_property_ack); + My_Read_Property_Ack_Handler); /* handle any errors coming back */ apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler); apdu_set_abort_handler(MyAbortHandler); @@ -148,7 +179,6 @@ int main( time_t last_seconds = 0; time_t current_seconds = 0; time_t timeout_seconds = 0; - uint8_t invoke_id = 0; bool found = false; if (argc < 5) { @@ -252,16 +282,16 @@ int main( &Target_Address); } if (found) { - if (invoke_id == 0) { - invoke_id = + if (Request_Invoke_ID == 0) { + Request_Invoke_ID = Send_Read_Property_Request(Target_Device_Object_Instance, Target_Object_Type, Target_Object_Instance, Target_Object_Property, Target_Object_Index); - } else if (tsm_invoke_id_free(invoke_id)) + } else if (tsm_invoke_id_free(Request_Invoke_ID)) break; - else if (tsm_invoke_id_failed(invoke_id)) { + else if (tsm_invoke_id_failed(Request_Invoke_ID)) { fprintf(stderr, "\rError: TSM Timeout!\r\n"); - tsm_free_invoke_id(invoke_id); + tsm_free_invoke_id(Request_Invoke_ID); Error_Detected = true; /* try again or abort? */ break; diff --git a/bacnet-stack/demo/readpropm/main.c b/bacnet-stack/demo/readpropm/main.c index 45cb126e..f0d0f8b9 100644 --- a/bacnet-stack/demo/readpropm/main.c +++ b/bacnet-stack/demo/readpropm/main.c @@ -60,8 +60,10 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; /* global variables used in this file */ static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE; static BACNET_READ_ACCESS_DATA *Read_Access_Data; - +/* needed to filter incoming messages */ +static uint8_t Request_Invoke_ID = 0; static BACNET_ADDRESS Target_Address; +/* needed for return value of main application */ static bool Error_Detected = false; static void MyErrorHandler( @@ -70,13 +72,13 @@ static void MyErrorHandler( BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Error: %s: %s\r\n", - bactext_error_class_name((int) error_class), - bactext_error_code_name((int) error_code)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Error: %s: %s\r\n", + bactext_error_class_name((int) error_class), + bactext_error_code_name((int) error_code)); + Error_Detected = true; + } } void MyAbortHandler( @@ -85,13 +87,13 @@ void MyAbortHandler( uint8_t abort_reason, bool server) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; (void) server; - printf("BACnet Abort: %s\r\n", - bactext_abort_reason_name((int) abort_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Abort: %s\r\n", + bactext_abort_reason_name((int) abort_reason)); + Error_Detected = true; + } } void MyRejectHandler( @@ -100,11 +102,87 @@ void MyRejectHandler( uint8_t reject_reason) { /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Reject: %s\r\n", - bactext_reject_reason_name((int) reject_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Reject: %s\r\n", + bactext_reject_reason_name((int) reject_reason)); + Error_Detected = true; + } +} + +/** Handler for a ReadPropertyMultiple ACK. + * @ingroup DSRPM + * For each read property, print out the ACK'd data, + * and free the request data items from linked property list. + * + * @param service_request [in] The contents of the service request. + * @param service_len [in] The length of the service_request. + * @param src [in] BACNET_ADDRESS of the source of the message + * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information + * decoded from the APDU header of this message. + */ +void My_Read_Property_Multiple_Ack_Handler( + uint8_t * service_request, + uint16_t service_len, + BACNET_ADDRESS * src, + BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data) +{ + int len = 0; + BACNET_READ_ACCESS_DATA *rpm_data; + BACNET_READ_ACCESS_DATA *old_rpm_data; + BACNET_PROPERTY_REFERENCE *rpm_property; + BACNET_PROPERTY_REFERENCE *old_rpm_property; + BACNET_APPLICATION_DATA_VALUE *value; + BACNET_APPLICATION_DATA_VALUE *old_value; + + if (address_match(&Target_Address, src) && + (service_data->invoke_id == Request_Invoke_ID)) { + rpm_data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA)); + if (rpm_data) { + len = + rpm_ack_decode_service_request(service_request, service_len, + rpm_data); + } + if (len > 0) { + while (rpm_data) { + rpm_ack_print_data(rpm_data); + rpm_property = rpm_data->listOfProperties; + while (rpm_property) { + value = rpm_property->value; + while (value) { + old_value = value; + value = value->next; + free(old_value); + } + old_rpm_property = rpm_property; + rpm_property = rpm_property->next; + free(old_rpm_property); + } + old_rpm_data = rpm_data; + rpm_data = rpm_data->next; + free(old_rpm_data); + } + } else { + fprintf(stderr, "RPM Ack Malformed! Freeing memory...\n"); + while (rpm_data) { + rpm_property = rpm_data->listOfProperties; + while (rpm_property) { + value = rpm_property->value; + while (value) { + old_value = value; + value = value->next; + free(old_value); + } + old_rpm_property = rpm_property; + rpm_property = rpm_property->next; + free(old_rpm_property); + } + old_rpm_data = rpm_data; + rpm_data = rpm_data->next; + free(old_rpm_data); + } + } + } } static void Init_Service_Handlers( @@ -125,7 +203,7 @@ static void Init_Service_Handlers( handler_read_property); /* handle the data coming back from confirmed requests */ apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE, - handler_read_property_multiple_ack); + My_Read_Property_Multiple_Ack_Handler); /* handle any errors coming back */ apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler); apdu_set_abort_handler(MyAbortHandler); @@ -170,7 +248,6 @@ int main( time_t last_seconds = 0; time_t current_seconds = 0; time_t timeout_seconds = 0; - uint8_t invoke_id = 0; bool found = false; uint8_t buffer[MAX_PDU] = { 0 @@ -328,16 +405,16 @@ int main( &Target_Address); } if (found) { - if (invoke_id == 0) { - invoke_id = + if (Request_Invoke_ID == 0) { + Request_Invoke_ID = Send_Read_Property_Multiple_Request(&buffer[0], sizeof(buffer), Target_Device_Object_Instance, Read_Access_Data); - } else if (tsm_invoke_id_free(invoke_id)) + } else if (tsm_invoke_id_free(Request_Invoke_ID)) break; - else if (tsm_invoke_id_failed(invoke_id)) { + else if (tsm_invoke_id_failed(Request_Invoke_ID)) { fprintf(stderr, "\rError: TSM Timeout!\r\n"); - tsm_free_invoke_id(invoke_id); + tsm_free_invoke_id(Request_Invoke_ID); Error_Detected = true; /* try again or abort? */ break; diff --git a/bacnet-stack/demo/writeprop/main.c b/bacnet-stack/demo/writeprop/main.c index 49d6aee0..c1f7efdf 100644 --- a/bacnet-stack/demo/writeprop/main.c +++ b/bacnet-stack/demo/writeprop/main.c @@ -72,7 +72,10 @@ static BACNET_APPLICATION_DATA_VALUE /* 0 if not set, 1..16 if set */ static uint8_t Target_Object_Property_Priority = 0; +/* needed to filter incoming messages */ +static uint8_t Request_Invoke_ID = 0; static BACNET_ADDRESS Target_Address; +/* needed for return value of main application */ static bool Error_Detected = false; static void MyErrorHandler( @@ -81,13 +84,13 @@ static void MyErrorHandler( BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Error: %s: %s\r\n", - bactext_error_class_name((int) error_class), - bactext_error_code_name((int) error_code)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Error: %s: %s\r\n", + bactext_error_class_name((int) error_class), + bactext_error_code_name((int) error_code)); + Error_Detected = true; + } } void MyAbortHandler( @@ -96,13 +99,13 @@ void MyAbortHandler( uint8_t abort_reason, bool server) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; (void) server; - printf("BACnet Abort: %s\r\n", - bactext_abort_reason_name((int) abort_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Abort: %s\r\n", + bactext_abort_reason_name((int) abort_reason)); + Error_Detected = true; + } } void MyRejectHandler( @@ -110,21 +113,22 @@ void MyRejectHandler( uint8_t invoke_id, uint8_t reject_reason) { - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Reject: %s\r\n", - bactext_reject_reason_name((int) reject_reason)); - Error_Detected = true; + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("BACnet Reject: %s\r\n", + bactext_reject_reason_name((int) reject_reason)); + Error_Detected = true; + } } void MyWritePropertySimpleAckHandler( BACNET_ADDRESS * src, uint8_t invoke_id) { - (void) src; - (void) invoke_id; - printf("\r\nWriteProperty Acknowledged!\r\n"); + if (address_match(&Target_Address, src) && + (invoke_id == Request_Invoke_ID)) { + printf("\r\nWriteProperty Acknowledged!\r\n"); + } } static void Init_Service_Handlers( @@ -166,7 +170,6 @@ int main( time_t last_seconds = 0; time_t current_seconds = 0; time_t timeout_seconds = 0; - uint8_t invoke_id = 0; bool found = false; char *value_string = NULL; bool status = false; @@ -351,18 +354,18 @@ int main( &Target_Address); } if (found) { - if (invoke_id == 0) { - invoke_id = + if (Request_Invoke_ID == 0) { + Request_Invoke_ID = Send_Write_Property_Request(Target_Device_Object_Instance, Target_Object_Type, Target_Object_Instance, Target_Object_Property, &Target_Object_Property_Value[0], Target_Object_Property_Priority, Target_Object_Property_Index); - } else if (tsm_invoke_id_free(invoke_id)) + } else if (tsm_invoke_id_free(Request_Invoke_ID)) break; - else if (tsm_invoke_id_failed(invoke_id)) { + else if (tsm_invoke_id_failed(Request_Invoke_ID)) { fprintf(stderr, "\rError: TSM Timeout!\r\n"); - tsm_free_invoke_id(invoke_id); + tsm_free_invoke_id(Request_Invoke_ID); Error_Detected = true; /* try again or abort? */ break; diff --git a/bacnet-stack/include/handlers.h b/bacnet-stack/include/handlers.h index 3d875f31..580052ee 100644 --- a/bacnet-stack/include/handlers.h +++ b/bacnet-stack/include/handlers.h @@ -172,6 +172,12 @@ extern "C" { uint8_t * apdu, int apdu_len, BACNET_READ_ACCESS_DATA * read_access_data); + /* print the RP Ack data to stdout */ + void rp_ack_print_data( + BACNET_READ_PROPERTY_DATA * data); + /* print the RPM Ack data to stdout */ + void rpm_ack_print_data( + BACNET_READ_ACCESS_DATA * rpm_data); /* Encodes the property APDU and returns the length, or sets the error, and returns -1 */