diff --git a/bacnet-stack/handlers.c b/bacnet-stack/handlers.c index 67945558..b3022250 100644 --- a/bacnet-stack/handlers.c +++ b/bacnet-stack/handlers.c @@ -149,6 +149,7 @@ bool Send_Read_Property_Request( bool status = false; int pdu_len = 0; int bytes_sent = 0; + BACNET_READ_PROPERTY_DATA data; status = address_get_by_device(device_id, &max_apdu, &dest); if (status) @@ -162,13 +163,15 @@ bool Send_Read_Property_Request( MESSAGE_PRIORITY_NORMAL); invoke_id = tsm_next_free_invokeID(); + // load the data for the encoding + data.object_type = object_type; + data.object_instance = object_instance; + data.object_property = object_property; + data.array_index = array_index; pdu_len += rp_encode_apdu( &Tx_Buf[pdu_len], invoke_id, - object_type, - object_instance, - object_property, - array_index); + &data); if ((unsigned)pdu_len < max_apdu) { tsm_set_confirmed_unsegmented_transaction( @@ -252,13 +255,10 @@ void ReadPropertyHandler( BACNET_ADDRESS *src, BACNET_CONFIRMED_SERVICE_DATA *service_data) { - BACNET_READ_PROPERTY_DATA rp_data; + BACNET_READ_PROPERTY_DATA data; int len = 0; int pdu_len = 0; - BACNET_OBJECT_TYPE object_type; uint32_t object_instance; - BACNET_PROPERTY_ID object_property; - int32_t array_index; BACNET_ADDRESS my_address; bool send = false; bool error = false; @@ -269,17 +269,14 @@ void ReadPropertyHandler( len = rp_decode_service_request( service_request, service_len, - &object_type, - &object_instance, - &object_property, - &array_index); + &data); fprintf(stderr,"Received Read-Property Request!\n"); if (len > 0) fprintf(stderr,"type=%u instance=%u property=%u index=%d\n", - object_type, - object_instance, - object_property, - array_index); + data.object_type, + data.object_instance, + data.object_property, + data.array_index); else fprintf(stderr,"Unable to decode Read-Property Request!\n"); // prepare a reply @@ -312,32 +309,28 @@ void ReadPropertyHandler( } else { - switch (object_type) + switch (data.object_type) { case OBJECT_DEVICE: // FIXME: probably need a length limitation sent with encode - if (object_instance == Device_Object_Instance_Number()) + if (data.object_instance == Device_Object_Instance_Number()) { len = Device_Encode_Property_APDU( &Temp_Buf[0], - object_property, - array_index, + data.object_property, + data.array_index, &error_class, &error_code); if (len > 0) { // encode the APDU portion of the packet - rp_data.object_type = object_type; - rp_data.object_instance = object_instance; - rp_data.object_property = object_property; - rp_data.array_index = array_index; - rp_data.application_data = &Temp_Buf[0]; - rp_data.application_data_len = len; + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; // FIXME: probably need a length limitation sent with encode pdu_len += rp_ack_encode_apdu( &Tx_Buf[pdu_len], service_data->invoke_id, - &rp_data); + &data); fprintf(stderr,"Sending Read Property Ack!\n"); send = true; } @@ -348,29 +341,25 @@ void ReadPropertyHandler( error = true; break; case OBJECT_ANALOG_INPUT: - if (Analog_Input_Valid_Instance(object_instance)) + if (Analog_Input_Valid_Instance(data.object_instance)) { len = Analog_Input_Encode_Property_APDU( &Temp_Buf[0], - object_instance, - object_property, - array_index, + data.object_instance, + data.object_property, + data.array_index, &error_class, &error_code); if (len > 0) { // encode the APDU portion of the packet - rp_data.object_type = object_type; - rp_data.object_instance = object_instance; - rp_data.object_property = object_property; - rp_data.array_index = array_index; - rp_data.application_data = &Temp_Buf[0]; - rp_data.application_data_len = len; + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; // FIXME: probably need a length limitation sent with encode pdu_len += rp_ack_encode_apdu( &Tx_Buf[pdu_len], service_data->invoke_id, - &rp_data); + &data); fprintf(stderr,"Sending Read Property Ack!\n"); send = true; } @@ -381,29 +370,25 @@ void ReadPropertyHandler( error = true; break; case OBJECT_ANALOG_OUTPUT: - if (Analog_Output_Valid_Instance(object_instance)) + if (Analog_Output_Valid_Instance(data.object_instance)) { len = Analog_Output_Encode_Property_APDU( &Temp_Buf[0], - object_instance, - object_property, - array_index, + data.object_instance, + data.object_property, + data.array_index, &error_class, &error_code); if (len > 0) { // encode the APDU portion of the packet - rp_data.object_type = object_type; - rp_data.object_instance = object_instance; - rp_data.object_property = object_property; - rp_data.array_index = array_index; - rp_data.application_data = &Temp_Buf[0]; - rp_data.application_data_len = len; + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; // FIXME: probably need a length limitation sent with encode pdu_len += rp_ack_encode_apdu( &Tx_Buf[pdu_len], service_data->invoke_id, - &rp_data); + &data); fprintf(stderr,"Sending Read Property Ack!\n"); send = true; } @@ -418,25 +403,21 @@ void ReadPropertyHandler( { len = bacfile_encode_property_apdu( &Temp_Buf[0], - object_instance, - object_property, - array_index, + data.object_instance, + data.object_property, + data.array_index, &error_class, &error_code); if (len > 0) { // encode the APDU portion of the packet - rp_data.object_type = object_type; - rp_data.object_instance = object_instance; - rp_data.object_property = object_property; - rp_data.array_index = array_index; - rp_data.application_data = &Temp_Buf[0]; - rp_data.application_data_len = len; + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; // FIXME: probably need a length limitation sent with encode pdu_len += rp_ack_encode_apdu( &Tx_Buf[pdu_len], service_data->invoke_id, - &rp_data); + &data); fprintf(stderr,"Sending Read Property Ack!\n"); send = true; } @@ -615,6 +596,7 @@ void AtomicReadFileHandler( int len = 0; int pdu_len = 0; BACNET_ADDRESS my_address; + bool send = false; bool error = false; int bytes_sent = 0; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; @@ -645,6 +627,7 @@ void AtomicReadFileHandler( service_data->invoke_id, ABORT_REASON_OTHER); fprintf(stderr,"Sending Abort!\n"); + send = true; } else if (service_data->segmented_message) { @@ -653,6 +636,7 @@ void AtomicReadFileHandler( service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); fprintf(stderr,"Sending Abort!\n"); + send = true; } else { @@ -660,9 +644,6 @@ void AtomicReadFileHandler( { data.fileData = (uint8_t *)&buffer[0]; data.fileDataLength = sizeof(buffer); - // FIXME: this may not be a valid way to check this, as the - // file length may be smaller than the request - // or smaller than the size of the buffer. if (data.type.stream.requestedOctetCount < data.fileDataLength) { if (bacfile_read_data(&data)) @@ -671,9 +652,13 @@ void AtomicReadFileHandler( &Tx_Buf[pdu_len], service_data->invoke_id, &data); + send = true; } else + { + send = true; error = true; + } } else { @@ -681,17 +666,15 @@ void AtomicReadFileHandler( &Tx_Buf[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED); - fprintf(stderr, - "Sending Abort! %u octets requested." - " Only able to send %u octets.\n", - data.type.stream.requestedOctetCount, - data.fileDataLength); + fprintf(stderr,"Sending Abort!\n"); + send = true; } } else { error_class = ERROR_CLASS_SERVICES; error_code = ERROR_CODE_INVALID_FILE_ACCESS_METHOD; + send = true; error = true; } } @@ -704,13 +687,17 @@ void AtomicReadFileHandler( error_class, error_code); fprintf(stderr,"Sending Error!\n"); + send = true; + } + if (send) + { + bytes_sent = datalink_send_pdu( + src, // destination address + &Tx_Buf[0], + pdu_len); // number of bytes of data + if (bytes_sent <= 0) + fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno)); } - bytes_sent = datalink_send_pdu( - src, // destination address - &Tx_Buf[0], - pdu_len); // number of bytes of data - if (bytes_sent <= 0) - fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno)); return; } @@ -718,7 +705,8 @@ void AtomicReadFileHandler( // We performed an AtomicReadFile Request, // and here is the data from the server // Note: it does not have to be the same file=instance -// that someone can read from us. +// that someone can read from us. It is common to +// use the description as the file name. void AtomicReadFileAckHandler( uint8_t *service_request, uint16_t service_len, diff --git a/bacnet-stack/rp.c b/bacnet-stack/rp.c index 3fd69dfe..a58b96ba 100644 --- a/bacnet-stack/rp.c +++ b/bacnet-stack/rp.c @@ -35,17 +35,13 @@ #include "bacenum.h" #include "bacdcode.h" #include "bacdef.h" -#include "device.h" #include "rp.h" // encode service int rp_encode_apdu( uint8_t *apdu, uint8_t invoke_id, - BACNET_OBJECT_TYPE object_type, - uint32_t object_instance, - BACNET_PROPERTY_ID object_property, - int32_t array_index) + BACNET_READ_PROPERTY_DATA *data) { int len = 0; // length of each encoding int apdu_len = 0; // total length of the apdu, return value @@ -53,21 +49,21 @@ int rp_encode_apdu( if (apdu) { apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; - apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); + apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[2] = invoke_id; apdu[3] = SERVICE_CONFIRMED_READ_PROPERTY; // service choice apdu_len = 4; len = encode_context_object_id(&apdu[apdu_len], 0, - object_type, object_instance); + data->object_type, data->object_instance); apdu_len += len; len = encode_context_enumerated(&apdu[apdu_len], 1, - object_property); + data->object_property); apdu_len += len; /* optional array index */ - if (array_index != BACNET_ARRAY_ALL) + if (data->array_index != BACNET_ARRAY_ALL) { len = encode_context_unsigned(&apdu[apdu_len], 2, - array_index); + data->array_index); apdu_len += len; } } @@ -79,10 +75,7 @@ int rp_encode_apdu( int rp_decode_service_request( uint8_t *apdu, unsigned apdu_len, - BACNET_OBJECT_TYPE *object_type, - uint32_t *object_instance, - BACNET_PROPERTY_ID *object_property, - int32_t *array_index) + BACNET_READ_PROPERTY_DATA *data) { unsigned len = 0; uint8_t tag_number = 0; @@ -92,21 +85,20 @@ int rp_decode_service_request( unsigned array_value = 0; // for decoding // check for value pointers - if (apdu_len && object_type && object_instance && - object_property && array_index) + if (apdu_len && data) { // Tag 0: Object ID if (!decode_is_context_tag(&apdu[len++], 0)) return -1; - len += decode_object_id(&apdu[len], &type, object_instance); - *object_type = type; + len += decode_object_id(&apdu[len], &type, &data->object_instance); + data->object_type = type; // Tag 1: Property ID len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) return -1; len += decode_enumerated(&apdu[len], len_value_type, &property); - *object_property = property; + data->object_property = property; // Tag 2: Optional Array Index if (len < apdu_len) { @@ -116,13 +108,13 @@ int rp_decode_service_request( { len += decode_unsigned(&apdu[len], len_value_type, &array_value); - *array_index = array_value; + data->array_index = array_value; } else - *array_index = BACNET_ARRAY_ALL; + data->array_index = BACNET_ARRAY_ALL; } else - *array_index = BACNET_ARRAY_ALL; + data->array_index = BACNET_ARRAY_ALL; } return (int)len; @@ -132,10 +124,7 @@ int rp_decode_apdu( uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id, - BACNET_OBJECT_TYPE *object_type, - uint32_t *object_instance, - BACNET_PROPERTY_ID *object_property, - int32_t *array_index) + BACNET_READ_PROPERTY_DATA *data) { int len = 0; unsigned offset = 0; @@ -156,10 +145,7 @@ int rp_decode_apdu( len = rp_decode_service_request( &apdu[offset], apdu_len - offset, - object_type, - object_instance, - object_property, - array_index); + data); } return len; @@ -251,7 +237,7 @@ int rp_ack_decode_service_request( len++; // don't decode the application tag number or its data here data->application_data = &apdu[len]; - data->application_data_len = apdu_len - len; + data->application_data_len = apdu_len - len - 1 /*closing tag*/; } else return -1; @@ -354,22 +340,17 @@ void testReadProperty(Test * pTest) int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; - BACNET_OBJECT_TYPE object_type = OBJECT_CALENDAR; - BACNET_OBJECT_TYPE test_object_type = 0; - uint32_t object_instance = 1; - uint32_t test_object_instance = 0; - BACNET_PROPERTY_ID object_property = PROP_ARCHIVE; - BACNET_PROPERTY_ID test_object_property = 0; - int32_t array_index = 2; - int32_t test_array_index = 0; - + BACNET_READ_PROPERTY_DATA data; + BACNET_READ_PROPERTY_DATA test_data; + + data.object_type = OBJECT_DEVICE; + data.object_instance = 1; + data.object_property = PROP_OBJECT_IDENTIFIER; + data.array_index = BACNET_ARRAY_ALL; len = rp_encode_apdu( &apdu[0], invoke_id, - object_type, - object_instance, - object_property, - array_index); + &data); ct_test(pTest, len != 0); apdu_len = len; @@ -377,15 +358,12 @@ void testReadProperty(Test * pTest) &apdu[0], apdu_len, &test_invoke_id, - &test_object_type, - &test_object_instance, - &test_object_property, - &test_array_index); + &test_data); ct_test(pTest, len != -1); - ct_test(pTest, test_object_type == object_type); - ct_test(pTest, test_object_instance == object_instance); - ct_test(pTest, test_object_property == object_property); - ct_test(pTest, test_array_index == array_index); + ct_test(pTest, test_data.object_type == data.object_type); + ct_test(pTest, test_data.object_instance == data.object_instance); + ct_test(pTest, test_data.object_property == data.object_property); + ct_test(pTest, test_data.array_index == data.array_index); return; } diff --git a/bacnet-stack/rp.h b/bacnet-stack/rp.h index 582c42b1..2ba876d4 100644 --- a/bacnet-stack/rp.h +++ b/bacnet-stack/rp.h @@ -51,28 +51,19 @@ typedef struct BACnet_Read_Property_Data int rp_encode_apdu( uint8_t *apdu, uint8_t invoke_id, - BACNET_OBJECT_TYPE object_type, - uint32_t object_instance, - BACNET_PROPERTY_ID object_property, - int32_t array_index); + BACNET_READ_PROPERTY_DATA *data); // decode the service request only int rp_decode_service_request( uint8_t *apdu, unsigned apdu_len, - BACNET_OBJECT_TYPE *object_type, - uint32_t *object_instance, - BACNET_PROPERTY_ID *object_property, - int32_t *array_index); + BACNET_READ_PROPERTY_DATA *data); int rp_decode_apdu( uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id, - BACNET_OBJECT_TYPE *object_type, - uint32_t *object_instance, - BACNET_PROPERTY_ID *object_property, - int32_t *array_index); + BACNET_READ_PROPERTY_DATA *data); int rp_ack_encode_apdu( uint8_t *apdu, diff --git a/bacnet-stack/rp.mak b/bacnet-stack/rp.mak index 5f5960a9..9d2dcf8a 100644 --- a/bacnet-stack/rp.mak +++ b/bacnet-stack/rp.mak @@ -8,7 +8,6 @@ CFLAGS = -Wall -I. -Itest -DTEST -DTEST_READ_PROPERTY -g SRCS = bacdcode.c \ bigend.c \ - device.c \ rp.c \ test/ctest.c diff --git a/bacnet-stack/test.sh b/bacnet-stack/test.sh index c3ac28bb..92b13aec 100755 --- a/bacnet-stack/test.sh +++ b/bacnet-stack/test.sh @@ -19,6 +19,16 @@ make -f mstp.mak ./mstp >> test.log make -f mstp.mak clean +make -f iam.mak clean +make -f iam.mak +./iam >> test.log +make -f iam.mak clean + +make -f whois.mak clean +make -f whois.mak +./whois >> test.log +make -f whois.mak clean + make -f bacdcode.mak clean make -f bacdcode.mak ./bacdcode >> test.log