void testAtomicReadFileAckAccess( Test * pTest, BACNET_ATOMIC_READ_FILE_DATA * data) { BACNET_ATOMIC_READ_FILE_DATA test_data = { 0 }; uint8_t apdu[480] = { 0 }; int len = 0; int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; unsigned int i = 0; len = arf_ack_encode_apdu(&apdu[0], invoke_id, data); ct_test(pTest, len != 0); apdu_len = len; len = arf_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data); ct_test(pTest, len != -1); ct_test(pTest, test_data.endOfFile == data->endOfFile); ct_test(pTest, test_data.access == data->access); if (test_data.access == FILE_STREAM_ACCESS) { ct_test(pTest, test_data.type.stream.fileStartPosition == data->type.stream.fileStartPosition); ct_test(pTest, octetstring_length(&test_data.fileData[0]) == octetstring_length(&data->fileData[0])); ct_test(pTest, memcmp(octetstring_value(&test_data.fileData[0]), octetstring_value(&data->fileData[0]), octetstring_length(&test_data.fileData[0])) == 0); } else if (test_data.access == FILE_RECORD_ACCESS) { ct_test(pTest, test_data.type.record.fileStartRecord == data->type.record.fileStartRecord); ct_test(pTest, test_data.type.record.RecordCount == data->type.record.RecordCount); for (i = 0; i < data->type.record.RecordCount; i++) { ct_test(pTest, octetstring_length(&test_data.fileData[i]) == octetstring_length(&data->fileData[i])); ct_test(pTest, memcmp(octetstring_value(&test_data.fileData[i]), octetstring_value(&data->fileData[i]), octetstring_length(&test_data.fileData[i])) == 0); } } }
void handler_atomic_read_file( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_ATOMIC_READ_FILE_DATA data; int len = 0; int pdu_len = 0; bool error = false; int bytes_sent = 0; BACNET_NPDU_DATA npdu_data; BACNET_ADDRESS my_address; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; #if PRINT_ENABLED fprintf(stderr, "Received Atomic-Read-File Request!\n"); #endif /* 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], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED fprintf(stderr, "Bad Encoding. Sending Abort!\n"); #endif 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) { if (data.type.stream.requestedOctetCount < octetstring_capacity(&data.fileData[0])) { if (bacfile_read_stream_data(&data)) { #if PRINT_ENABLED fprintf(stderr, "ARF: Stream offset %d, %d octets.\n", data.type.stream.fileStartPosition, data.type.stream.requestedOctetCount); #endif len = arf_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, &data); } else { error = true; error_class = ERROR_CLASS_OBJECT; error_code = ERROR_CODE_FILE_ACCESS_DENIED; } } else { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED fprintf(stderr, "Too Big To Send (%d >= %d). Sending Abort!\n", data.type.stream.requestedOctetCount, octetstring_capacity(&data.fileData[0])); #endif } } else if (data.access == FILE_RECORD_ACCESS) { if (data.type.record.fileStartRecord >= BACNET_READ_FILE_RECORD_COUNT) { error_class = ERROR_CLASS_SERVICES; error_code = ERROR_CODE_INVALID_FILE_START_POSITION; error = true; } else if (bacfile_read_stream_data(&data)) { #if PRINT_ENABLED fprintf(stderr, "ARF: fileStartRecord %d, %u RecordCount.\n", data.type.record.fileStartRecord, data.type.record.RecordCount); #endif len = arf_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, &data); } else { error = true; error_class = ERROR_CLASS_OBJECT; error_code = ERROR_CODE_FILE_ACCESS_DENIED; } } else { error = true; error_class = ERROR_CLASS_SERVICES; error_code = ERROR_CODE_INVALID_FILE_ACCESS_METHOD; #if PRINT_ENABLED fprintf(stderr, "Record Access Requested. Sending Error!\n"); #endif } } else { error = true; error_class = ERROR_CLASS_SERVICES; error_code = ERROR_CODE_INCONSISTENT_OBJECT_TYPE; } if (error) { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], 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); #if PRINT_ENABLED if (bytes_sent <= 0) { fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); } #endif return; }