diff --git a/bacnet-stack/demo/handler/h_arf.c b/bacnet-stack/demo/handler/h_arf.c index 72ac22a6..f9c7491c 100644 --- a/bacnet-stack/demo/handler/h_arf.c +++ b/bacnet-stack/demo/handler/h_arf.c @@ -109,12 +109,21 @@ void handler_atomic_read_file(uint8_t * service_request, #if PRINT_ENABLED fprintf(stderr, "Received Atomic-Read-File Request!\n"); #endif - len = arf_decode_service_request(service_request, service_len, &data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, "ARF: Segmented Message. Sending Abort!\n"); +#endif + goto ARF_ABORT; + } + len = arf_decode_service_request(service_request, service_len, &data); /* bad decoding - send an abort */ if (len < 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], @@ -122,14 +131,9 @@ void handler_atomic_read_file(uint8_t * service_request, #if PRINT_ENABLED fprintf(stderr, "Bad Encoding. Sending Abort!\n"); #endif - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); -#if PRINT_ENABLED - fprintf(stderr, "Segmented Message. Sending Abort!\n"); -#endif - } else if (data.object_type == OBJECT_FILE) { + goto ARF_ABORT; + } + if (data.object_type == OBJECT_FILE) { if (!bacfile_valid_instance(data.object_instance)) { error = true; } else if (data.access == FILE_STREAM_ACCESS) { @@ -179,6 +183,7 @@ void handler_atomic_read_file(uint8_t * service_request, service_data->invoke_id, SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code); } +ARF_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/demo/handler/h_awf.c b/bacnet-stack/demo/handler/h_awf.c index 2124b3d4..c8144a3d 100644 --- a/bacnet-stack/demo/handler/h_awf.c +++ b/bacnet-stack/demo/handler/h_awf.c @@ -87,12 +87,21 @@ void handler_atomic_write_file(uint8_t * service_request, #if PRINT_ENABLED fprintf(stderr, "Received AtomicWriteFile Request!\n"); #endif - len = awf_decode_service_request(service_request, service_len, &data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, "Segmented Message. Sending Abort!\n"); +#endif + goto AWF_ABORT; + } + len = awf_decode_service_request(service_request, service_len, &data); /* bad decoding - send an abort */ if (len < 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], @@ -100,14 +109,9 @@ void handler_atomic_write_file(uint8_t * service_request, #if PRINT_ENABLED fprintf(stderr, "Bad Encoding. Sending Abort!\n"); #endif - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); -#if PRINT_ENABLED - fprintf(stderr, "Segmented Message. Sending Abort!\n"); -#endif - } else if (data.object_type == OBJECT_FILE) { + goto AWF_ABORT; + } + if (data.object_type == OBJECT_FILE) { if (!bacfile_valid_instance(data.object_instance)) { error = true; } else if (data.access == FILE_STREAM_ACCESS) { @@ -144,6 +148,7 @@ void handler_atomic_write_file(uint8_t * service_request, service_data->invoke_id, SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code); } +AWF_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/demo/handler/h_dcc.c b/bacnet-stack/demo/handler/h_dcc.c index c671aa86..504a67de 100644 --- a/bacnet-stack/demo/handler/h_dcc.c +++ b/bacnet-stack/demo/handler/h_dcc.c @@ -53,16 +53,28 @@ void handler_device_communication_control(uint8_t * service_request, BACNET_NPDU_DATA npdu_data; BACNET_ADDRESS my_address; - /* decode the service request only */ - len = dcc_decode_service_request(service_request, - service_len, &timeDuration, &state, &password); - /* encode the NPDU portion of the packet */ + /* encode the NPDU portion of the reply packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl!\n"); +#endif + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, "DeviceCommunicationControl: " + "Sending Abort - segmented message.\n"); +#endif + goto DCC_ABORT; + } + /* decode the service request only */ + len = dcc_decode_service_request(service_request, + service_len, &timeDuration, &state, &password); +#if PRINT_ENABLED if (len > 0) fprintf(stderr, "DeviceCommunicationControl: " "timeout=%u state=%u password=%s\n", @@ -77,15 +89,9 @@ void handler_device_communication_control(uint8_t * service_request, fprintf(stderr, "DeviceCommunicationControl: " "Sending Abort - could not decode.\n"); #endif - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); -#if PRINT_ENABLED - fprintf(stderr, "DeviceCommunicationControl: " - "Sending Abort - segmented message.\n"); -#endif - } else if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { + goto DCC_ABORT; + } + if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED @@ -115,6 +121,7 @@ void handler_device_communication_control(uint8_t * service_request, #endif } } +DCC_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/demo/handler/h_rd.c b/bacnet-stack/demo/handler/h_rd.c index 3b169adc..2f352dfe 100644 --- a/bacnet-stack/demo/handler/h_rd.c +++ b/bacnet-stack/demo/handler/h_rd.c @@ -53,9 +53,6 @@ void handler_reinitialize_device(uint8_t * service_request, int bytes_sent = 0; BACNET_ADDRESS my_address; - /* decode the service request only */ - len = rd_decode_service_request(service_request, - service_len, &state, &their_password); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); @@ -63,6 +60,21 @@ void handler_reinitialize_device(uint8_t * service_request, &my_address, &npdu_data); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice!\n"); +#endif + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, + "ReinitializeDevice: Sending Abort - segmented message.\n"); +#endif + goto RD_ABORT; + } + /* decode the service request only */ + len = rd_decode_service_request(service_request, + service_len, &state, &their_password); +#if PRINT_ENABLED if (len > 0) fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n", (unsigned) state, characterstring_value(&their_password)); @@ -77,15 +89,10 @@ void handler_reinitialize_device(uint8_t * service_request, fprintf(stderr, "ReinitializeDevice: Sending Abort - could not decode.\n"); #endif - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); -#if PRINT_ENABLED - fprintf(stderr, - "ReinitializeDevice: Sending Abort - segmented message.\n"); -#endif - } else if (state >= MAX_BACNET_REINITIALIZED_STATE) { + goto RD_ABORT; + } + /* check the data from the request */ + if (state >= MAX_BACNET_REINITIALIZED_STATE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED @@ -117,6 +124,7 @@ void handler_reinitialize_device(uint8_t * service_request, #endif } } +RD_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/demo/handler/h_rp.c b/bacnet-stack/demo/handler/h_rp.c index 108e01bd..5d9c7033 100644 --- a/bacnet-stack/demo/handler/h_rp.c +++ b/bacnet-stack/demo/handler/h_rp.c @@ -199,75 +199,79 @@ void handler_read_property(uint8_t * service_request, BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; BACNET_ADDRESS my_address; - len = rp_decode_service_request(service_request, service_len, &data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); + if (service_data->segmented_message) { + /* we don't support segmentation - send an abort */ + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, "RP: Segmented message. Sending Abort!\n"); +#endif + goto RP_ABORT; + } + + len = rp_decode_service_request(service_request, service_len, &data); #if PRINT_ENABLED if (len <= 0) - fprintf(stderr, "Unable to decode Read-Property Request!\n"); + fprintf(stderr, "RP: Unable to decode Request!\n"); #endif if (len < 0) { /* bad decoding - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED - fprintf(stderr, "Sending Abort!\n"); + fprintf(stderr, "RP: Bad Encoding. Sending Abort!\n"); #endif - } else if (service_data->segmented_message) { - /* we don't support segmentation - send an abort */ - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); + goto RP_ABORT; + } + + /* assume that there is an error */ + error = true; + len = Encode_Property_APDU( + &Temp_Buf[0], + data.object_type, + data.object_instance, + data.object_property, + data.array_index, + &error_class, &error_code); + if (len >= 0) { + /* encode the APDU portion of the packet */ + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; + /* FIXME: probably need a length limitation sent with encode */ + len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, &data); #if PRINT_ENABLED - fprintf(stderr, "Sending Abort!\n"); + fprintf(stderr, + "RP: Sending Ack!\n"); #endif - } else { - /* most cases will be error */ - error = true; - len = Encode_Property_APDU( - &Temp_Buf[0], - data.object_type, - data.object_instance, - data.object_property, - data.array_index, - &error_class, &error_code); - if (len >= 0) { - /* encode the APDU portion of the packet */ - data.application_data = &Temp_Buf[0]; - data.application_data_len = len; - /* FIXME: probably need a length limitation sent with encode */ - len = - rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, &data); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Read Property Ack!\n"); -#endif - error = false; - } + error = false; } if (error) { - switch (len) { + if (len == -2) { /* BACnet APDU too small to fit data, so proper response is Abort */ - case -2: len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); - break; - case -1: - default: +#if PRINT_ENABLED + fprintf(stderr, "RP: Reply too big to fit into APDU!\n"); +#endif + } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code); - break; - } #if PRINT_ENABLED - fprintf(stderr, "Sending Read Property Error!\n"); + fprintf(stderr, "RP: Sending Error!\n"); #endif + } } +RP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/demo/handler/h_rpm.c b/bacnet-stack/demo/handler/h_rpm.c index 68f780a8..701eef9d 100644 --- a/bacnet-stack/demo/handler/h_rpm.c +++ b/bacnet-stack/demo/handler/h_rpm.c @@ -318,41 +318,86 @@ void handler_read_property_multiple( npdu_len = npdu_encode_pdu( &Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); -#if PRINT_ENABLED - if (service_len <= 0) - printf("RPM: Unable to decode request!\r\n"); -#endif - /* bad decoding - send an abort */ - if (service_len == 0) - { - apdu_len = abort_encode_apdu( - &Handler_Transmit_Buffer[npdu_len], - service_data->invoke_id, - ABORT_REASON_OTHER, true); -#if PRINT_ENABLED - printf("RPM: Sending Abort!\r\n"); -#endif - } else if (service_data->segmented_message) { + if (service_data->segmented_message) { apdu_len = abort_encode_apdu( &Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED - printf("RPM: Sending Abort!\r\n"); + printf("RPM: Segmented message. Sending Abort!\r\n"); #endif - } else { - /* decode apdu request & encode apdu reply - encode complex ack, invoke id, service choice */ - apdu_len = rpm_ack_encode_apdu_init( - &Handler_Transmit_Buffer[npdu_len], - service_data->invoke_id); + goto RPM_ABORT; + } + /* decode apdu request & encode apdu reply + encode complex ack, invoke id, service choice */ + apdu_len = rpm_ack_encode_apdu_init( + &Handler_Transmit_Buffer[npdu_len], + service_data->invoke_id); + do + { + len = rpm_decode_object_id( + &service_request[decode_len], + service_len - decode_len, + &object_type, &object_instance); + /* 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) { + 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; + } + break; + } + len = rpm_ack_encode_apdu_object_begin( + &Temp_Buf[0], + object_type, object_instance); + 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; + } + /* do each property of this object of the RPM request */ do { - len = rpm_decode_object_id( + len = rpm_decode_object_property( &service_request[decode_len], service_len - decode_len, - &object_type, &object_instance); - /* end of object? */ + &object_property, + &array_index); + /* end of property list? */ if (len > 0) { decode_len += len; } else { @@ -383,108 +428,30 @@ void handler_read_property_multiple( ABORT_REASON_OTHER, true); goto RPM_ABORT; } + /* stop decoding properties */ break; } - len = rpm_ack_encode_apdu_object_begin( - &Temp_Buf[0], - object_type, object_instance); - 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; - } - /* do each property of this object of the RPM request */ - do + /* handle the special properties */ + if ((object_property == PROP_ALL) || + (object_property == PROP_REQUIRED) || + (object_property == PROP_OPTIONAL)) { - len = rpm_decode_object_property( - &service_request[decode_len], - service_len - decode_len, - &object_property, - &array_index); - /* 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) || - (object_property == PROP_REQUIRED) || - (object_property == PROP_OPTIONAL)) - { - struct special_property_list_t property_list; - unsigned property_count = 0; - unsigned index = 0; - BACNET_PROPERTY_ID special_object_property; + struct special_property_list_t property_list; + unsigned property_count = 0; + unsigned index = 0; + BACNET_PROPERTY_ID special_object_property; - special_object_property = object_property; - RPM_Property_List(object_type, &property_list); - property_count = RPM_Object_Property_Count( + special_object_property = object_property; + RPM_Property_List(object_type, &property_list); + property_count = RPM_Object_Property_Count( + &property_list, + special_object_property); + for (index = 0; index < property_count; index++) + { + object_property = RPM_Object_Property( &property_list, - special_object_property); - for (index = 0; index < property_count; index++) - { - object_property = RPM_Object_Property( - &property_list, - special_object_property, - index); - len = RPM_Encode_Property( - &Handler_Transmit_Buffer[0], - npdu_len + apdu_len, - sizeof(Handler_Transmit_Buffer), - object_type, - object_instance, - object_property, - array_index); - if (len > 0) { - apdu_len += len; - } else { - apdu_len = abort_encode_apdu( - &Handler_Transmit_Buffer[npdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); - goto RPM_ABORT; - } - } - } else { - /* handle an individual property */ + special_object_property, + index); len = RPM_Encode_Property( &Handler_Transmit_Buffer[0], npdu_len + apdu_len, @@ -503,12 +470,31 @@ void handler_read_property_multiple( goto RPM_ABORT; } } - } while(1); - if (decode_len >= service_len) { - break; + } else { + /* handle an individual property */ + len = RPM_Encode_Property( + &Handler_Transmit_Buffer[0], + npdu_len + apdu_len, + sizeof(Handler_Transmit_Buffer), + object_type, + object_instance, + object_property, + array_index); + if (len > 0) { + apdu_len += len; + } else { + apdu_len = abort_encode_apdu( + &Handler_Transmit_Buffer[npdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); + goto RPM_ABORT; + } } } while(1); - } + if (decode_len >= service_len) { + break; + } + } while(1); RPM_ABORT: pdu_len = apdu_len + npdu_len; bytes_sent = datalink_send_pdu( diff --git a/bacnet-stack/demo/handler/h_whois.c b/bacnet-stack/demo/handler/h_whois.c index 477cc529..28ff41d7 100644 --- a/bacnet-stack/demo/handler/h_whois.c +++ b/bacnet-stack/demo/handler/h_whois.c @@ -47,8 +47,6 @@ void handler_who_is(uint8_t * service_request, (void) src; len = whois_decode_service_request(service_request, service_len, &low_limit, &high_limit); - /* in our simple system, we just set a flag and let the main loop - send the I-Am request. */ if (len == 0) iam_send(&Handler_Transmit_Buffer[0]); else if (len != -1) { diff --git a/bacnet-stack/demo/handler/h_wp.c b/bacnet-stack/demo/handler/h_wp.c index 2be77f93..63c0f7dd 100644 --- a/bacnet-stack/demo/handler/h_wp.c +++ b/bacnet-stack/demo/handler/h_wp.c @@ -63,270 +63,274 @@ void handler_write_property(uint8_t * service_request, int bytes_sent = 0; BACNET_ADDRESS my_address; - /* decode the service request only */ - len = wp_decode_service_request(service_request, - service_len, &wp_data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); #if PRINT_ENABLED - fprintf(stderr, "Received Write-Property Request!\n"); + fprintf(stderr, "WP: Received Request!\n"); +#endif + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); +#if PRINT_ENABLED + fprintf(stderr, "WP: Segmented message. Sending Abort!\n"); +#endif + goto WP_ABORT; + } /* decode the service request only */ + len = wp_decode_service_request(service_request, + service_len, &wp_data); +#if PRINT_ENABLED if (len > 0) - fprintf(stderr, "type=%u instance=%u property=%u index=%d\n", + fprintf(stderr, "WP: type=%u instance=%u property=%u index=%d\n", wp_data.object_type, wp_data.object_instance, wp_data.object_property, wp_data.array_index); else - fprintf(stderr, "Unable to decode Write-Property Request!\n"); + fprintf(stderr, "WP: Unable to decode Request!\n"); #endif /* bad decoding or something we didn't understand - send an abort */ if (len <= 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED - fprintf(stderr, "Sending Abort!\n"); + fprintf(stderr, "WP: Bad Encoding. Sending Abort!\n"); #endif - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); + goto WP_ABORT; + } + switch (wp_data.object_type) { + case OBJECT_DEVICE: + if (Device_Write_Property(&wp_data, &error_class, &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); #if PRINT_ENABLED - fprintf(stderr, "Sending Abort!\n"); + fprintf(stderr, + "WP: Sending Simple Ack for Device!\n"); #endif - } else { - switch (wp_data.object_type) { - case OBJECT_DEVICE: - if (Device_Write_Property(&wp_data, &error_class, &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for Device!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Error for Device!\n"); -#endif - } - break; - case OBJECT_ANALOG_INPUT: - case OBJECT_BINARY_INPUT: - error_class = ERROR_CLASS_PROPERTY; - error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, - error_class, error_code); + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); #if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error!\n"); + fprintf(stderr, + "WP: Sending Error for Device!\n"); #endif - break; - case OBJECT_BINARY_OUTPUT: - if (Binary_Output_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for BO!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for BO!\n"); -#endif - } - break; - case OBJECT_BINARY_VALUE: - if (Binary_Value_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for BV!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for BV!\n"); -#endif - } - break; - case OBJECT_ANALOG_OUTPUT: - if (Analog_Output_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for AO!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for AO!\n"); -#endif - } - break; - case OBJECT_ANALOG_VALUE: - if (Analog_Value_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for AV!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for AV!\n"); -#endif - } - break; - case OBJECT_LIFE_SAFETY_POINT: - if (Life_Safety_Point_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for LSP!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for LSP!\n"); -#endif - } - break; - case OBJECT_LOAD_CONTROL: - if (Load_Control_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for Load Control!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Access Error for Load Control!\n"); -#endif - } - break; - case OBJECT_MULTI_STATE_OUTPUT: - if (Multistate_Output_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for MSO!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for MSO!\n"); -#endif - } - break; -#if BACFILE - case OBJECT_FILE: - if (bacfile_write_property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); -#if PRINT_ENABLED - fprintf(stderr, - "Sending Write Property Simple Ack for File!\n"); -#endif - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Write Access Error for File!\n"); -#endif - } - break; -#endif /* BACFILE */ - default: - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, - error_class, error_code); -#if PRINT_ENABLED - fprintf(stderr, "Sending Unknown Object Error!\n"); -#endif - break; } + break; + case OBJECT_ANALOG_INPUT: + case OBJECT_BINARY_INPUT: + error_class = ERROR_CLASS_PROPERTY; + error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, + error_class, error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error!\n"); +#endif + break; + case OBJECT_BINARY_OUTPUT: + if (Binary_Output_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for BO!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for BO!\n"); +#endif + } + break; + case OBJECT_BINARY_VALUE: + if (Binary_Value_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for BV!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for BV!\n"); +#endif + } + break; + case OBJECT_ANALOG_OUTPUT: + if (Analog_Output_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for AO!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for AO!\n"); +#endif + } + break; + case OBJECT_ANALOG_VALUE: + if (Analog_Value_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for AV!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for AV!\n"); +#endif + } + break; + case OBJECT_LIFE_SAFETY_POINT: + if (Life_Safety_Point_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for LSP!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for LSP!\n"); +#endif + } + break; + case OBJECT_LOAD_CONTROL: + if (Load_Control_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for Load Control!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Write Access Error for Load Control!\n"); +#endif + } + break; + case OBJECT_MULTI_STATE_OUTPUT: + if (Multistate_Output_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Write Property Simple Ack for MSO!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for MSO!\n"); +#endif + } + break; +#if BACFILE + case OBJECT_FILE: + if (bacfile_write_property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); +#if PRINT_ENABLED + fprintf(stderr, + "WP: Sending Simple Ack for File!\n"); +#endif + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Write Access Error for File!\n"); +#endif + } + break; +#endif /* BACFILE */ + default: + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, + error_class, error_code); +#if PRINT_ENABLED + fprintf(stderr, "WP: Sending Unknown Object Error!\n"); +#endif + break; } +WP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) - fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); + fprintf(stderr, "WP: Failed to send PDU (%s)!\n", strerror(errno)); #endif return;