Ejemplo n.º 1
0
bool bacfile_read_ack_stream_data(
    uint32_t instance,
    BACNET_ATOMIC_READ_FILE_DATA * data)
{
    bool found = false;
    FILE *pFile = NULL;
    char *pFilename = NULL;

    pFilename = bacfile_name(instance);
    if (pFilename) {
        found = true;
        pFile = fopen(pFilename, "rb");
        if (pFile) {
            (void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
            if (fwrite(octetstring_value(&data->fileData),
                    octetstring_length(&data->fileData), 1, pFile) != 1) {
#if PRINT_ENABLED
                fprintf(stderr, "Failed to write to %s (%lu)!\n", pFilename,
                    (unsigned long) instance);
#endif
            }
            fclose(pFile);
        }
    }

    return found;
}
Ejemplo n.º 2
0
bool bacfile_read_data(
    BACNET_ATOMIC_READ_FILE_DATA * data)
{
    char *pFilename = NULL;
    bool found = false;
    FILE *pFile = NULL;
    size_t len = 0;

    pFilename = bacfile_name(data->object_instance);
    if (pFilename) {
        found = true;
        pFile = fopen(pFilename, "rb");
        if (pFile) {
            (void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
            len =
                fread(octetstring_value(&data->fileData), 1,
                data->type.stream.requestedOctetCount, pFile);
            if (len < data->type.stream.requestedOctetCount)
                data->endOfFile = true;
            else
                data->endOfFile = false;
            octetstring_truncate(&data->fileData, len);
            fclose(pFile);
        } else {
            octetstring_truncate(&data->fileData, 0);
            data->endOfFile = true;
        }
    } else {
        octetstring_truncate(&data->fileData, 0);
        data->endOfFile = true;
    }

    return found;
}
Ejemplo n.º 3
0
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);
        }
    }
}
Ejemplo n.º 4
0
void testAtomicWriteFileAccess(
    Test * pTest,
    BACNET_ATOMIC_WRITE_FILE_DATA * data)
{
    BACNET_ATOMIC_WRITE_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;

    len = awf_encode_apdu(&apdu[0], invoke_id, data);
    ct_test(pTest, len != 0);
    apdu_len = len;

    len = awf_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
    ct_test(pTest, len != -1);
    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.access == data->access);
    if (test_data.access == FILE_STREAM_ACCESS) {
        ct_test(pTest,
                test_data.type.stream.fileStartPosition ==
                data->type.stream.fileStartPosition);
    } 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.returnedRecordCount ==
                data->type.record.returnedRecordCount);
    }
    ct_test(pTest,
            octetstring_length(&test_data.fileData) ==
            octetstring_length(&data->fileData));
    ct_test(pTest, memcmp(octetstring_value(&test_data.fileData),
                          octetstring_value(&data->fileData),
                          octetstring_length(&test_data.fileData)) == 0);
}
Ejemplo n.º 5
0
static void AtomicReadFileAckHandler(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
    int len = 0;
    BACNET_ATOMIC_READ_FILE_DATA data;
    FILE *pFile = NULL; /* stream pointer */
    size_t octets_written = 0;

    (void) src; /* FIXME: validate the source address matches */
    len = arf_ack_decode_service_request(service_request, service_len, &data);
    if (len > 0) {
        /* validate the parameters before storing data */
        if ((data.access == FILE_STREAM_ACCESS) &&
            (service_data->invoke_id == Current_Invoke_ID)) {
            if (data.type.stream.fileStartPosition == 0)
                pFile = fopen(Local_File_Name, "wb");
            else
                pFile = fopen(Local_File_Name, "rb+");
            if (pFile) {
                /* is there anything to do with this? data.stream.requestedOctetCount */
                (void) fseek(pFile, data.type.stream.fileStartPosition,
                    SEEK_SET);
                octets_written = fwrite(octetstring_value(&data.fileData), 1,   /* unit to write in bytes - in our case, an octet is one byte */
                    octetstring_length(&data.fileData), pFile);
                if (octets_written != octetstring_length(&data.fileData)) {
                    fprintf(stderr, "Unable to write data to file \"%s\".\n",
                        Local_File_Name);
                } else if (octets_written == 0) {
                    fprintf(stderr, "Received 0 byte octet string!.\n");
                } else {
                    printf("\r%d bytes",
                        (data.type.stream.fileStartPosition + octets_written));
                }
                fflush(pFile);
                fclose(pFile);
            }
            if (data.endOfFile) {
                End_Of_File_Detected = true;
                printf("\r\n");
            }
        }
    }
}
Ejemplo n.º 6
0
static void AtomicReadFileAckHandler(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
    int len = 0;
    BACNET_ATOMIC_READ_FILE_DATA data;

    if (address_match(&Target_Address, src) &&
        (service_data->invoke_id == Request_Invoke_ID)) {
        len =
            arf_ack_decode_service_request(service_request, service_len,
            &data);
        if (len > 0) {
            /* validate the parameters before storing data */
            if ((data.access == FILE_STREAM_ACCESS) &&
                (service_data->invoke_id == Request_Invoke_ID)) {
                char msg[32];
                uint8_t *pFileData;
                int i;

                sprintf(msg, "EOF=%d,start=%d,", data.endOfFile,
                    data.type.stream.fileStartPosition);
                __LogAnswer(msg, 0);

                pFileData = octetstring_value(&data.fileData);
                for (i = 0; i < octetstring_length(&data.fileData); i++) {
                    sprintf(msg, "%02x ", *pFileData);
                    __LogAnswer(msg, 1);
                    pFileData++;
                }
            } else {
                LogError("Bad stream access reported");
            }
        }
    }
}
Ejemplo n.º 7
0
bool bacfile_write_stream_data(
    BACNET_ATOMIC_WRITE_FILE_DATA * data)
{
    char *pFilename = NULL;
    bool found = false;
    FILE *pFile = NULL;

    pFilename = bacfile_name(data->object_instance);
    if (pFilename) {
        found = true;
        if (data->type.stream.fileStartPosition == 0) {
            /* open the file as a clean slate when starting at 0 */
            pFile = fopen(pFilename, "wb");
        } else if (data->type.stream.fileStartPosition == -1) {
            /* If 'File Start Position' parameter has the special
               value -1, then the write operation shall be treated
               as an append to the current end of file. */
            pFile = fopen(pFilename, "ab+");
        } else {
            /* open for update */
            pFile = fopen(pFilename, "rb+");
        }
        if (pFile) {
            if (data->type.stream.fileStartPosition != -1) {
                (void) fseek(pFile, data->type.stream.fileStartPosition,
                    SEEK_SET);
            }
            if (fwrite(octetstring_value(&data->fileData),
                    octetstring_length(&data->fileData), 1, pFile) != 1) {
                /* do something if it fails? */
            }
            fclose(pFile);
        }
    }

    return found;
}
Ejemplo n.º 8
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    int fileStartPosition = 0;
    unsigned requestedOctetCount = 0;
    uint8_t invoke_id = 0;
    bool found = false;
    uint16_t my_max_apdu = 0;
    FILE *pFile = NULL;
    static BACNET_OCTET_STRING fileData;
    size_t len = 0;
    bool pad_byte = false;

    if (argc < 4) {
        /* FIXME: what about access method - record or stream? */
        printf
            ("%s device-instance file-instance local-name [octet count] [pad value]\r\n",
            filename_remove_path(argv[0]));
        return 0;
    }
    /* decode the command line parameters */
    Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
    Target_File_Object_Instance = strtol(argv[2], NULL, 0);
    Local_File_Name = argv[3];
    if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }
    if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE) {
        fprintf(stderr, "file-instance=%u - it must be less than %u\r\n",
            Target_File_Object_Instance, BACNET_MAX_INSTANCE + 1);
        return 1;
    }
    if (argc > 4) {
        Target_File_Requested_Octet_Count = strtol(argv[4], NULL, 0);
    }
    if (argc > 5) {
        Target_File_Requested_Octet_Pad_Byte = strtol(argv[5], NULL, 0);
        pad_byte = true;
    }
    /* setup my info */
    Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
    /* try to bind with the device */
    Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
    /* loop forever */
    for (;;) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);

        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

        /* process */
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }
        /* at least one second has passed */
        if (current_seconds != last_seconds) {
            tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
        }
        /* wait until the device is bound, or timeout and quit */
        found =
            address_bind_request(Target_Device_Object_Instance, &max_apdu,
            &Target_Address);
        if (found) {
            if (Target_File_Requested_Octet_Count) {
                requestedOctetCount = Target_File_Requested_Octet_Count;
            } else {
                /* calculate the smaller of our APDU size or theirs
                   and remove the overhead of the APDU (varies depending on size).
                   note: we could fail if there is a bottle neck (router)
                   and smaller MPDU in betweeen. */
                if (max_apdu < MAX_APDU) {
                    my_max_apdu = max_apdu;
                } else {
                    my_max_apdu = MAX_APDU;
                }
                /* Typical sizes are 50, 128, 206, 480, 1024, and 1476 octets */
                if (my_max_apdu <= 50) {
                    requestedOctetCount = my_max_apdu - 19;
                } else if (my_max_apdu <= 480) {
                    requestedOctetCount = my_max_apdu - 32;
                } else if (my_max_apdu <= 1476) {
                    requestedOctetCount = my_max_apdu - 64;
                } else {
                    requestedOctetCount = my_max_apdu / 2;
                }
            }
            /* has the previous invoke id expired or returned?
               note: invoke ID = 0 is invalid, so it will be idle */
            if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id)) {
                if (End_Of_File_Detected || Error_Detected) {
                    printf("\r\n");
                    break;
                }
                if (invoke_id != 0) {
                    fileStartPosition += requestedOctetCount;
                }
                /* we'll read the file in chunks
                   less than max_apdu to keep unsegmented */
                pFile = fopen(Local_File_Name, "rb");
                if (pFile) {
                    (void) fseek(pFile, fileStartPosition, SEEK_SET);
                    len =
                        fread(octetstring_value(&fileData), 1,
                        requestedOctetCount, pFile);
                    if (len < requestedOctetCount) {
                        End_Of_File_Detected = true;
                        if (pad_byte) {
                            memset(octetstring_value(&fileData) + len + 1,
                                (int) Target_File_Requested_Octet_Pad_Byte,
                                requestedOctetCount - len);
                            len = requestedOctetCount;
                        }
                    }
                    octetstring_truncate(&fileData, len);
                    fclose(pFile);
                } else {
                    End_Of_File_Detected = true;
                }
                printf("\rSending %d bytes", (fileStartPosition + len));
                invoke_id =
                    Send_Atomic_Write_File_Stream
                    (Target_Device_Object_Instance,
                    Target_File_Object_Instance, fileStartPosition, &fileData);
                Current_Invoke_ID = invoke_id;
            } else if (tsm_invoke_id_failed(invoke_id)) {
                fprintf(stderr, "\rError: TSM Timeout!\r\n");
                tsm_free_invoke_id(invoke_id);
                Error_Detected = true;
                /* try again or abort? */
                break;
            }
        } else {
            /* increment timer - exit if timed out */
            elapsed_seconds += (current_seconds - last_seconds);
            if (elapsed_seconds > timeout_seconds) {
                fprintf(stderr, "\rError: APDU Timeout!\r\n");
                Error_Detected = true;
                break;
            }
        }
        /* keep track of time for next check */
        last_seconds = current_seconds;
    }

    if (Error_Detected) {
        return 1;
    }
    return 0;
}