Corrected bug in all confirmed handlers: if a segmented message was received, the handler tried to decode it instead of immediately sending an abort. This caused lockup with WriteProperty.

This commit is contained in:
skarg
2007-08-18 00:06:48 +00:00
parent 31d78501c0
commit cc4c46b84d
8 changed files with 462 additions and 445 deletions
+14 -9
View File
@@ -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);
+14 -9
View File
@@ -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);
+20 -13
View File
@@ -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);
+20 -12
View File
@@ -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);
+45 -41
View File
@@ -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);
+112 -126
View File
@@ -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(
-2
View File
@@ -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) {
+237 -233
View File
@@ -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;