Exemple #1
0
void Send_UnconfirmedPrivateTransfer(
    BACNET_ADDRESS * dest,
    BACNET_PRIVATE_TRANSFER_DATA * private_data)
{
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;
    if (!dcc_communication_enabled())
        return;
    datalink_get_my_address(&my_address);
    /* encode the NPDU portion of the packet */
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address,
        &npdu_data);
    /* encode the APDU portion of the packet */
    len =
        ptransfer_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],invoke_id,
        private_data);
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(dest, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr,
            "Failed to Send UnconfirmedPrivateTransfer Request (%s)!\n",
            strerror(errno));
#endif
}
Exemple #2
0
/** Send a Who-Is request to a remote network for a specific device, a range,
 * or any device.
 * If low_limit and high_limit both are -1, then the range is unlimited.
 * If low_limit and high_limit have the same non-negative value, then only
 * that device will respond.
 * Otherwise, low_limit must be less than high_limit.
 * @param target_address [in] BACnet address of target router
 * @param low_limit [in] Device Instance Low Range, 0 - 4,194,303 or -1
 * @param high_limit [in] Device Instance High Range, 0 - 4,194,303 or -1
 */
void Send_WhoIs_To_Network(
    BACNET_ADDRESS * target_address,
    int32_t low_limit,
    int32_t high_limit)
{
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    datalink_get_my_address(&my_address);
    /* encode the NPDU portion of the packet */
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);

    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], target_address,
        &my_address, &npdu_data);
    /* encode the APDU portion of the packet */
    len =
        whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len], low_limit,
        high_limit);
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(target_address, &npdu_data,
        &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n",
            strerror(errno));
#endif
}
Exemple #3
0
/**
 * Sends a TimeSync message to a specific destination
 *
 * @param dest - #BACNET_ADDRESS - the specific destination
 * @param bdate - #BACNET_DATE
 * @param btime - #BACNET_TIME
 */
void Send_TimeSync_Remote(
    BACNET_ADDRESS * dest,
    BACNET_DATE * bdate,
    BACNET_TIME * btime)
{
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    if (!dcc_communication_enabled())
        return;

    datalink_get_my_address(&my_address);
    /* encode the NPDU portion of the packet */
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address,
        &npdu_data);
    /* encode the APDU portion of the packet */
    len =
        timesync_encode_apdu(&Handler_Transmit_Buffer[pdu_len], bdate, btime);
    pdu_len += len;
    /* send it out the datalink */
    bytes_sent =
        datalink_send_pdu(dest, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr, "Failed to Send Time-Synchronization Request (%s)!\n",
            strerror(errno));
#endif
}
Exemple #4
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 */
    BACNET_ADDRESS my_address, broadcast_address;

    (void) argc;
    (void) argv;
    Device_Set_Object_Instance_Number(4194300);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    datalink_get_broadcast_address(&broadcast_address);
    print_address("Broadcast", &broadcast_address);
    datalink_get_my_address(&my_address);
    print_address("Address", &my_address);
    printf("BACnet stack running...\n");
    /* loop forever */
    for (;;) {
        /* input */

        /* 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);
        }
        if (I_Am_Request) {
            I_Am_Request = false;
            Send_I_Am(&Handler_Transmit_Buffer[0]);
        } else if (Who_Is_Request) {
            Who_Is_Request = false;
            Send_WhoIs(-1, -1);
        } else {
            Read_Properties();
        }

        /* output */

        /* blink LEDs, Turn on or off outputs, etc */

        /* wait for ESC from keyboard before quitting */
        if (kbhit() && (getch() == 0x1B))
            break;
    }

    print_address_cache();

    return 0;
}
int Send_ConfirmedPrivateTransfer(
	BACNET_ADDRESS * dest,
	BACNET_PRIVATE_TRANSFER_DATA * private_data)
{
	int len = 0;
	int pdu_len = 0;
	int bytes_sent = 0;
	BACNET_NPDU_DATA npdu_data;
	BACNET_ADDRESS my_address;
	int invoke_id = 0;
	if (!dcc_communication_enabled())
		return -1;

	datalink_get_my_address(&my_address);
	/* encode the NPDU portion of the packet */
	// npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);	//Fance
	npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
	pdu_len =
		npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address,
		&npdu_data);

	/* encode the APDU portion of the packet */

	 invoke_id = tsm_next_free_invokeID();
	 if(invoke_id==0)//这里是当没有可用的调用ID的时候将所有ID都清零;变为可用;
		 tsm_free_all_invoke_id();
	len =
		ptransfer_encode_apdu(&Handler_Transmit_Buffer[pdu_len],invoke_id,private_data);	//这里的还需要完善 Invoke ID
	// uptransfer_encode_apdu(&Handler_Transmit_Buffer[pdu_len],		//Fance
	// private_data);
	pdu_len += len;
	bytes_sent =
		datalink_send_pdu(dest, &npdu_data, &Handler_Transmit_Buffer[0],
		pdu_len);
#if PRINT_ENABLED
	if (bytes_sent <= 0)
		fprintf(stderr,
		"Failed to Send UnconfirmedPrivateTransfer Request (%s)!\n",
		strerror(errno));
#endif
	if(bytes_sent>0)
		return invoke_id;
	else
		return -2;
}
Exemple #6
0
/** Send a Who-Has request for a device which has a specific Object type and ID.
 * @ingroup DMDOB
 * If low_limit and high_limit both are -1, then the device ID range is unlimited.
 * If low_limit and high_limit have the same non-negative value, then only
 * that device will respond.
 * Otherwise, low_limit must be less than high_limit for a range.
 * @param low_limit [in] Device Instance Low Range, 0 - 4,194,303 or -1
 * @param high_limit [in] Device Instance High Range, 0 - 4,194,303 or -1
 * @param object_type [in] The BACNET_OBJECT_TYPE of the desired Object.
 * @param object_instance [in] The ID of the desired Object.
 */
void Send_WhoHas_Object(
    int32_t low_limit,
    int32_t high_limit,
    BACNET_OBJECT_TYPE object_type,
    uint32_t object_instance)
{
    int len = 0;
    int pdu_len = 0;
    BACNET_ADDRESS dest;
    int bytes_sent = 0;
    BACNET_WHO_HAS_DATA data;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* if we are forbidden to send, don't send! */
    if (!dcc_communication_enabled())
        return;
    /* Who-Has is a global broadcast */
    datalink_get_broadcast_address(&dest);
    datalink_get_my_address(&my_address);
    /* encode the NPDU portion of the packet */
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, &my_address,
        &npdu_data);

    /* encode the APDU portion of the packet */
    data.low_limit = low_limit;
    data.high_limit = high_limit;
    data.is_object_name = false;
    data.object.identifier.type = object_type;
    data.object.identifier.instance = object_instance;
    len = whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &data);
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr, "Failed to Send Who-Has Request (%s)!\n",
            strerror(errno));
#endif
}
Exemple #7
0
/** Sends an Abort message
 * @param buffer The buffer to build the message for sending.
 * @param dest - Destination address to send the message
 * @param invoke_id - use to match up a reply
 * @param reason - #BACNET_ABORT_REASON enumeration
 * @param server - true or false
 *
 * @return Size of the message sent (bytes), or a negative value on error.
 */
int Send_Error_To_Network(
    uint8_t * buffer,
    BACNET_ADDRESS *dest,
    uint8_t invoke_id,
    BACNET_CONFIRMED_SERVICE service,
    BACNET_ERROR_CLASS error_class,
    BACNET_ERROR_CODE error_code)
{
    int pdu_len = 0;
    BACNET_ADDRESS src;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;

    datalink_get_my_address(&src);
    pdu_len = error_encode_pdu(buffer, dest, &src, &npdu_data,
        invoke_id, service, error_class, error_code);
    bytes_sent = datalink_send_pdu(dest, &npdu_data, &buffer[0], pdu_len);

    return bytes_sent;
}
Exemple #8
0
int ucov_notify_encode_pdu(
    uint8_t * buffer,
    BACNET_ADDRESS * dest,
    BACNET_NPDU_DATA * npdu_data,
    BACNET_COV_DATA * cov_data)
{
    int len = 0;
    int pdu_len = 0;
    BACNET_ADDRESS my_address;
    datalink_get_my_address(&my_address);

    /* unconfirmed is a broadcast */
    datalink_get_broadcast_address(dest);
    /* encode the NPDU portion of the packet */
    npdu_encode_npdu_data(npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len = npdu_encode_pdu(&buffer[0], dest, &my_address, npdu_data);

    /* encode the APDU portion of the packet */
    len = ucov_notify_encode_apdu(&buffer[pdu_len], cov_data);
    pdu_len += len;

    return pdu_len;
}
Exemple #9
0
/** Handler for a Reinitialize Device (RD) request.
 * @ingroup DMRD
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 * - an Error if
 *   - the RD password is incorrect
 *   - the Reinitialize Device operation fails
 * - a Reject if the request state is invalid
 * - else tries to send a simple ACK for the RD on success.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_reinitialize_device(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_REINITIALIZE_DEVICE_DATA rd_data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* 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, "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, &rd_data.state,
        &rd_data.password);
#if PRINT_ENABLED
    if (len > 0) {
        fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n",
            (unsigned) rd_data.state,
            characterstring_value(&rd_data.password));
    } else {
        fprintf(stderr, "ReinitializeDevice: 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,
            "ReinitializeDevice: Sending Abort - could not decode.\n");
#endif
        goto RD_ABORT;
    }
    /* check the data from the request */
    if (rd_data.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
        fprintf(stderr,
            "ReinitializeDevice: Sending Reject - undefined enumeration\n");
#endif
    } else {
#if BAC_ROUTING
        /* Check to see if the current Device supports this service. */
        len =
            Routed_Device_Service_Approval
            (SERVICE_CONFIRMED_REINITIALIZE_DEVICE, (int) rd_data.state,
            &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id);
        if (len > 0)
            goto RD_ABORT;
#endif

        if (Device_Reinitialize(&rd_data)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n");
#endif
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
                rd_data.error_class, rd_data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Error.\n");
#endif
        }
    }
  RD_ABORT:
    pdu_len += len;
    len =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
    if (len <= 0) {
#if PRINT_ENABLED
        fprintf(stderr, "ReinitializeDevice: Failed to send PDU (%s)!\n",
            strerror(errno));
#endif
    }

    return;
}
Exemple #10
0
void handler_conf_private_trans(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_PRIVATE_TRANSFER_DATA data;
    int len;
    int pdu_len;
    bool error;
    int bytes_sent;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;
    BACNET_ERROR_CLASS error_class;
    BACNET_ERROR_CODE error_code;

    len = 0;
    pdu_len = 0;
    error = false;
    bytes_sent = 0;
    error_class = ERROR_CLASS_OBJECT;
    error_code = ERROR_CODE_UNKNOWN_OBJECT;

#if PRINT_ENABLED
    fprintf(stderr, "Received Confirmed Private Transfer Request!\n");
#endif
    /* encode the NPDU portion of the response packet as it will be needed */
    /* no matter what the outcome. */

    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, "CPT: Segmented Message. Sending Abort!\n");
#endif
        goto CPT_ABORT;
    }

    len =
        ptransfer_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, "CPT: Bad Encoding. Sending Abort!\n");
#endif
        goto CPT_ABORT;
    }

    /*  Simple example with service number of 0 for
       read block and 1 for write block
       We also only support our own vendor ID.
       In theory we could support others
       for compatability purposes but these
       interfaces are rarely documented... */
    if ((data.vendorID == BACNET_VENDOR_ID) &&
        (data.serviceNumber <= MY_SVC_WRITE)) {
        /* We only try to understand our own IDs and service numbers */
        /* Will either return a result block or an app level status block */
        ProcessPT(&data);
        if (data.serviceParametersLen == 0) {
            /* No respopnse means fatal error */
            error = true;
            error_class = ERROR_CLASS_SERVICES;
            error_code = ERROR_CODE_OTHER;
#if PRINT_ENABLED
            fprintf(stderr, "CPT: Error servicing request!\n");
#endif
        }
        len =
            ptransfer_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, &data);
    } else {    /* Not our vendor ID or bad service parameter */

        error = true;
        error_class = ERROR_CLASS_SERVICES;
        error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
#if PRINT_ENABLED
        fprintf(stderr, "CPT: Not our Vendor ID or invalid service code!\n");
#endif
    }

    if (error) {
        len =
            ptransfer_error_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, error_class, error_code, &data);
    }
  CPT_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;
}
Exemple #11
0
/* returns invoke id of 0 if device is not bound or no tsm available */
uint8_t Send_ReadRange_Request(
    uint32_t device_id, /* destination device */
    BACNET_READ_RANGE_DATA * read_access_data)
{
    BACNET_ADDRESS dest;
    BACNET_ADDRESS my_address;
    unsigned max_apdu = 0;
    uint8_t invoke_id = 0;
    bool status = false;
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;

    if (!dcc_communication_enabled())
        return 0;

    /* is the device bound? */
    status = address_get_by_device(device_id, &max_apdu, &dest);
    /* is there a tsm available? */
    if (status)
        invoke_id = tsm_next_free_invokeID();

    if (invoke_id) {
        /* encode the NPDU portion of the packet */
        datalink_get_my_address(&my_address);
        npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
        pdu_len =
            npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, &my_address,
            &npdu_data);

        /* encode the APDU portion of the packet */
        len =
            rr_encode_apdu(&Handler_Transmit_Buffer[pdu_len], invoke_id,
            read_access_data);
        if (len <= 0) {
            return 0;
        }

        pdu_len += len;
        /* is it small enough for the the destination to receive?
           note: if there is a bottleneck router in between
           us and the destination, we won't know unless
           we have a way to check for that and update the
           max_apdu in the address binding table. */
        if ((unsigned) pdu_len < max_apdu) {
            tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
                &npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
            bytes_sent =
                datalink_send_pdu(&dest, &npdu_data,
                &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
            if (bytes_sent <= 0)
                fprintf(stderr, "Failed to Send ReadRange Request (%s)!\n",
                    strerror(errno));
#endif
        } else {
            tsm_free_invoke_id(invoke_id);
            invoke_id = 0;
#if PRINT_ENABLED
            fprintf(stderr,
                "Failed to Send ReadRange Request (exceeds destination maximum APDU)!\n");
#endif
        }
    }

    return invoke_id;
}
Exemple #12
0
int BacnetTimeSync(
    int deviceInstanceNumber,
    int year,
    int month,
    int day,
    int hour,
    int minute,
    int second,
    int isUTC,
    int UTCOffset)
{
    BACNET_DATE bdate;
    BACNET_TIME btime;
    struct tm my_time;
    time_t aTime;
    struct tm *newTime;

    my_time.tm_sec = second;
    my_time.tm_min = minute;
    my_time.tm_hour = hour;
    my_time.tm_mday = day;
    my_time.tm_mon = month - 1;
    my_time.tm_year = year - 1900;
    my_time.tm_wday = 0;        /* does not matter */
    my_time.tm_yday = 0;        /* does not matter */
    my_time.tm_isdst = 0;       /* does not matter */

    aTime = mktime(&my_time);
    newTime = localtime(&aTime);

    bdate.year = newTime->tm_year;
    bdate.month = newTime->tm_mon + 1;
    bdate.day = newTime->tm_mday;
    bdate.wday = newTime->tm_wday ? newTime->tm_wday : 7;
    btime.hour = newTime->tm_hour;
    btime.min = newTime->tm_min;
    btime.sec = newTime->tm_sec;
    btime.hundredths = 0;

    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;
    uint8_t Handler_Transmit_Buffer[MAX_PDU] = { 0 };

    /* Loop for eary exit */
    do {
        if (!dcc_communication_enabled()) {
            LogError("DCC communicaiton is not enabled");
            break;
        }

        /* encode the NPDU portion of the packet */
        npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
        datalink_get_my_address(&my_address);
        pdu_len =
            npdu_encode_pdu(&Handler_Transmit_Buffer[0], &Target_Address,
            &my_address, &npdu_data);

        /* encode the APDU portion of the packet */
        len =
            timesync_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &bdate,
            &btime);
        pdu_len += len;

        /* send it out the datalink */
        bytes_sent =
            datalink_send_pdu(&Target_Address, &npdu_data,
            &Handler_Transmit_Buffer[0], pdu_len);
        if (bytes_sent <= 0) {
            char errorMsg[64];
            sprintf(errorMsg,
                "Failed to Send Time-Synchronization Request (%s)!",
                strerror(errno));
            LogError(errorMsg);
            break;
        }

        Wait_For_Answer_Or_Timeout(100, waitAnswer);
    } while (false);

    int isFailure = Error_Detected;
    Error_Detected = 0;
    return isFailure;
}
Exemple #13
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;
}
Exemple #14
0
void handler_read_property_ack2(
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_ACK_DATA * service_ack_data,
    uint8_t * apdu,
    uint16_t apdu_len)
{
    BACNET_READ_PROPERTY_DATA rpdata;
    int len = 0;
    int pdu_len = 0;
    int npdu_len = -1;
    BACNET_NPDU_DATA npdu_data;
    bool error = true;  /* assume that there is an error */
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    fprintf(stderr, "Entering handler_RP2 in h_rp.c.\n");
    /* configure default error code as an abort since it is common */
    rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    /* returns my IP addr (4 bytes) and port num (2bytes)*/
    datalink_get_my_address(&my_address);
    //set up NPCI header field npdu_data
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer_ACK[0], src, &my_address,//src!!
        &npdu_data);//set up handler transmit buffer by injecting npci/src/dst addr info
    if (service_ack_data->segmented_message) {
        /* we don't support segmentation - send an abort */
        len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Segmented message.  Sending Abort!\n");
#endif
        goto RP_FAILURE;
    }

    int i;
    for (i = 0; i < apdu_len; ++i){
        Handler_Transmit_Buffer_ACK[npdu_len + i] = apdu[i];
    }
    fprintf(stderr, "Finish copying apdu to ack buffer in h_rp.c.\n");

  RP_FAILURE:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id,
                abort_convert_error_code(rpdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
                rpdata.error_class, rpdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id,
                reject_convert_error_code(rpdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Reject!\n");
#endif
        }
    }


    pdu_len = npdu_len + apdu_len;
    bytes_sent =
        datalink_send_pdu(rp_serv_addr, &npdu_data, &Handler_Transmit_Buffer_ACK[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0) {
        fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
    }else{
        fprintf(stderr, "sent pdu back to server in h_rp.c.\n");
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemple #15
0
/** Handler for a Device Communication Control (DCC) request.
 * @ingroup DMDCC
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 *   - if not a known DCC state
 * - an Error if the DCC password is incorrect
 * - else tries to send a simple ACK for the DCC on success,
 *   and sets the DCC state requested.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_device_communication_control(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    uint16_t timeDuration = 0;
    BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
    BACNET_CHARACTER_STRING password;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* 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",
            (unsigned) timeDuration, (unsigned) state,
            characterstring_value(&password));
#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,
            "DeviceCommunicationControl: "
            "Sending Abort - could not decode.\n");
#endif
        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
        fprintf(stderr,
            "DeviceCommunicationControl: "
            "Sending Reject - undefined enumeration\n");
#endif
    } else {
#if BAC_ROUTING
        /* Check to see if the current Device supports this service. */
        len =
            Routed_Device_Service_Approval
            (SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, (int) state,
            &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id);
        if (len > 0)
            goto DCC_ABORT;
#endif

        if (characterstring_ansi_same(&password, My_Password)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
#if PRINT_ENABLED
            fprintf(stderr,
                "DeviceCommunicationControl: " "Sending Simple Ack!\n");
#endif
            dcc_set_status_duration(state, timeDuration);
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
                ERROR_CLASS_SECURITY, ERROR_CODE_PASSWORD_FAILURE);
#if PRINT_ENABLED
            fprintf(stderr,
                "DeviceCommunicationControl: "
                "Sending Error - password failure.\n");
#endif
        }
    }
  DCC_ABORT:
    pdu_len += len;
    len =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
    if (len <= 0) {
#if PRINT_ENABLED
        fprintf(stderr,
            "DeviceCommunicationControl: " "Failed to send PDU (%s)!\n",
            strerror(errno));
#endif
    }

    return;
}
Exemple #16
0
void handler_write_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
    BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* 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);
        goto WP_ABORT;
    }
    /* decode the service request only */
    len = wp_decode_service_request(service_request, service_len, &wp_data);
    /* 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);
        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 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;
            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!\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_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;
        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;
    }
  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));
#endif

    return;
}
Exemple #17
0
/** Handler for a ReadProperty Service request.
 * @ingroup DSRP
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 *   - if the response would be too large
 * - the result from Device_Read_Property(), if it succeeds
 * - an Error if Device_Read_Property() fails
 *   or there isn't enough room in the APDU to fit the data.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_read_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_READ_PROPERTY_DATA rpdata;
    int len = 0;
    int pdu_len = 0;
    int apdu_len = -1;
    int npdu_len = -1;
    BACNET_NPDU_DATA npdu_data;
    bool error = true;  /* assume that there is an error */
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* configure default error code as an abort since it is common */
    rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_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 = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Segmented message.  Sending Abort!\n");
#endif
        goto RP_FAILURE;
    }
    len = rp_decode_service_request(service_request, service_len, &rpdata);
#if PRINT_ENABLED
    if (len <= 0) {
        fprintf(stderr, "RP: Unable to decode Request!\n");
    }
#endif
    if (len < 0) {
        /* bad decoding - skip to error/reject/abort handling */
        error = true;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Bad Encoding.\n");
#endif
        goto RP_FAILURE;
    }
    /* Test for case of indefinite Device object instance */
    if ((rpdata.object_type == OBJECT_DEVICE) &&
        (rpdata.object_instance == BACNET_MAX_INSTANCE)) {
        rpdata.object_instance = Device_Object_Instance_Number();
    }

    apdu_len =
        rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
        service_data->invoke_id, &rpdata);
    /* configure our storage */
    rpdata.application_data = &Handler_Transmit_Buffer[npdu_len + apdu_len];
    rpdata.application_data_len =
        sizeof(Handler_Transmit_Buffer) - (npdu_len + apdu_len);
    len = Device_Read_Property(&rpdata);
    if (len >= 0) {
        apdu_len += len;
        len =
            rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
            [npdu_len + apdu_len]);
        apdu_len += len;
        if (apdu_len > service_data->max_resp) {
            /* too big for the sender - send an abort
             * Setting of error code needed here as read property processing may
             * have overriden the default set at start */
            rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
            len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
            fprintf(stderr, "RP: Message too large.\n");
#endif
        } else {
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Ack!\n");
#endif
            error = false;
        }
    } else {
#if PRINT_ENABLED
        fprintf(stderr, "RP: Device_Read_Property: ");
        if (len == BACNET_STATUS_ABORT) {
            fprintf(stderr, "Abort!\n");
        } else if (len == BACNET_STATUS_ERROR) {
            fprintf(stderr, "Error!\n");
        } else if (len == BACNET_STATUS_REJECT) {
            fprintf(stderr, "Reject!\n");
        } else {
            fprintf(stderr, "Unknown Len=%d\n", len);
        }
#endif
    }

  RP_FAILURE:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                abort_convert_error_code(rpdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
                rpdata.error_class, rpdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                reject_convert_error_code(rpdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Reject!\n");
#endif
        }
    }

    pdu_len = npdu_len + apdu_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));
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemple #18
0
void handler_read_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_READ_PROPERTY_DATA data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    bool error = false;
    int bytes_sent = 0;
    BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
    BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
    BACNET_ADDRESS my_address;

    /* 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);
        goto RP_ABORT;
    }
    len = rp_decode_service_request(service_request, service_len, &data);
    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);
        goto RP_ABORT;
    }
    /* 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);
        error = false;
    }
    if (error) {
        if (len == -2) {
            /* BACnet APDU too small to fit data, so proper response is Abort */
            len =
                abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
            goto RP_ABORT;
        }
        len =
            bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
            error_class, error_code);
    }
  RP_ABORT:
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);

    return;
}
Exemple #19
0
/** Handler for an Confirmed COV Notification.
 * @ingroup DSCOV
 * Decodes the received list of Properties to update,
 * and print them out with the subscription information.
 * @note Nothing is specified in BACnet about what to do with the
 *       information received from Confirmed COV Notifications.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_ccov_notification(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_NPDU_DATA npdu_data;
    BACNET_COV_DATA cov_data;
    BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES];
    BACNET_PROPERTY_VALUE *pProperty_value = NULL;
    unsigned index = 0;
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* create linked list to store data if more
       than one property value is expected */
    pProperty_value = &property_value[0];
    while (pProperty_value) {
        index++;
        if (index < MAX_COV_PROPERTIES) {
            pProperty_value->next = &property_value[index];
        } else {
            pProperty_value->next = NULL;
        }
        pProperty_value = pProperty_value->next;
    }
    cov_data.listOfValues = &property_value[0];
    /* 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, "CCOV: Received Notification!\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, "CCOV: Segmented message.  Sending Abort!\n");
#endif
        goto CCOV_ABORT;
    }
    /* decode the service request only */
    len =
        cov_notify_decode_service_request(service_request, service_len,
        &cov_data);
#if PRINT_ENABLED
    if (len > 0) {
        fprintf(stderr, "CCOV: PID=%u ", cov_data.subscriberProcessIdentifier);
        fprintf(stderr, "instance=%u ", cov_data.initiatingDeviceIdentifier);
        fprintf(stderr, "%s %u ",
            bactext_object_type_name(cov_data.monitoredObjectIdentifier.type),
            cov_data.monitoredObjectIdentifier.instance);
        fprintf(stderr, "time remaining=%u seconds ", cov_data.timeRemaining);
        fprintf(stderr, "\n");
        pProperty_value = &property_value[0];
        while (pProperty_value) {
            fprintf(stderr, "CCOV: ");
            if (pProperty_value->propertyIdentifier < 512) {
                fprintf(stderr, "%s ",
                    bactext_property_name
                    (pProperty_value->propertyIdentifier));
            } else {
                fprintf(stderr, "proprietary %u ",
                    pProperty_value->propertyIdentifier);
            }
            if (pProperty_value->propertyArrayIndex != BACNET_ARRAY_ALL) {
                fprintf(stderr, "%u ", pProperty_value->propertyArrayIndex);
            }
            fprintf(stderr, "\n");
            pProperty_value = pProperty_value->next;
        }
    }
#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, "CCOV: Bad Encoding. Sending Abort!\n");
#endif
        goto CCOV_ABORT;
    } else {
        len =
            encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, SERVICE_CONFIRMED_COV_NOTIFICATION);
#if PRINT_ENABLED
        fprintf(stderr, "CCOV: Sending Simple Ack!\n");
#endif
    }
  CCOV_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, "CCOV: Failed to send PDU (%s)!\n", strerror(errno));
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemple #20
0
void handler_reinitialize_device(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_REINITIALIZED_STATE state;
    BACNET_CHARACTER_STRING their_password;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* 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);
        goto RD_ABORT;
    }
    /* decode the service request only */
    len =
        rd_decode_service_request(service_request, service_len, &state,
        &their_password);
    /* 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);
        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);
    } else {
        characterstring_init_ansi(&My_Password, Password);
        if (characterstring_same(&their_password, &My_Password)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
            /* FIXME: now you can reboot, restart, quit, or something clever */
            /* Note: you can use a mix of state and password to do specific stuff */
            /* Note: if you don't do something clever like actually restart,
               you probably should clear any DCC status and timeouts */
            /* Note: you probably need to send the reply BEFORE restarting */
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
                ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
        }
    }
  RD_ABORT:
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);

    return;
}
Exemple #21
0
/** returns the invoke ID for confirmed request, or zero on failure */
uint8_t Send_Write_Property_Request_Data(
    BACNET_ADDRESS * dest,
    uint16_t max_apdu,
    BACNET_OBJECT_TYPE object_type,
    uint32_t object_instance,
    BACNET_PROPERTY_ID object_property,
    uint8_t * application_data,
    int application_data_len,
    uint8_t priority,
    uint32_t array_index)
{
    BACNET_ADDRESS my_address;
    uint8_t invoke_id = 0;
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_WRITE_PROPERTY_DATA data;
    BACNET_NPDU_DATA npdu_data;

    if (!dcc_communication_enabled())
        return 0;

    /* is there a tsm available? */
    invoke_id = tsm_next_free_invokeID();
    if (invoke_id) {
        /* encode the NPDU portion of the packet */
        datalink_get_my_address(&my_address);
        npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
        pdu_len =
            npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address,
            &npdu_data);
        /* encode the APDU portion of the packet */
        data.object_type = object_type;
        data.object_instance = object_instance;
        data.object_property = object_property;
        data.array_index = array_index;
        data.application_data_len = application_data_len;
        memcpy(&data.application_data[0], &application_data[0],
            application_data_len);
        data.priority = priority;
        len =
            wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len], invoke_id,
            &data);
        pdu_len += len;
        /* will it fit in the sender?
           note: if there is a bottleneck router in between
           us and the destination, we won't know unless
           we have a way to check for that and update the
           max_apdu in the address binding table. */
        if (pdu_len < max_apdu) {
            tsm_set_confirmed_unsegmented_transaction(invoke_id, dest,
                &npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
            bytes_sent =
                datalink_send_pdu(dest, &npdu_data,
                &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
            if (bytes_sent <= 0)
                fprintf(stderr, "Failed to Send WriteProperty Request (%s)!\n",
                    strerror(errno));
#endif
        } else {
            tsm_free_invoke_id(invoke_id);
            invoke_id = 0;
#if PRINT_ENABLED
            fprintf(stderr,
                "Failed to Send WriteProperty Request "
                "(exceeds destination maximum APDU)!\n");
#endif
        }
    } else {
#if PRINT_ENABLED
            fprintf(stderr,
                "Ran out of invoke ids!\n");
#endif
    }

    return invoke_id;
}
Exemple #22
0
void handler_write_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
    BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
    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);
    /* 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);
    } 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);
    } 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);
                } else {
                    len =
                        bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                        service_data->invoke_id,
                        SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
                        error_code);
                }
                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);
                } else {
                    len =
                        bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                        service_data->invoke_id,
                        SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
                        error_code);
                }
                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);
                } else {
                    len =
                        bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                        service_data->invoke_id,
                        SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
                        error_code);
                }
                break;
            default:
                len =
                    bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                    service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
                    error_class, error_code);
                break;
        }
    }
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);

    return;
}
Exemple #23
0
/** Handler for a WriteProperty Service request.
 * @ingroup DSWP
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 * - an ACK if Device_Write_Property() succeeds
 * - an Error if Device_Write_Property() fails
 *   or there isn't enough room in the APDU to fit the data.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_write_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_WRITE_PROPERTY_DATA wp_data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* 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, "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,
            "WP: type=%lu instance=%lu property=%lu priority=%lu index=%ld\n",
            (unsigned long) wp_data.object_type,
            (unsigned long) wp_data.object_instance,
            (unsigned long) wp_data.object_property,
            (unsigned long) wp_data.priority, (long) wp_data.array_index);
    else
        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, "WP: Bad Encoding. Sending Abort!\n");
#endif
        goto WP_ABORT;
    }
    if (Device_Write_Property(&wp_data)) {
        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!\n");
#endif
    } else {
        len =
            bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
            wp_data.error_class, wp_data.error_code);
#if PRINT_ENABLED
        fprintf(stderr, "WP: Sending Error!\n");
#endif
    }
  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, "WP: Failed to send PDU (%s)!\n", strerror(errno));
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemple #24
0
void handler_lso(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_LSO_DATA data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* 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, "LSO: Segmented message.  Sending Abort!\n");
#endif
        goto LSO_ABORT;
    }

    len = lso_decode_service_request(service_request, service_len, &data);
#if PRINT_ENABLED
    if (len <= 0)
        fprintf(stderr, "LSO: 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, "LSO: Bad Encoding.  Sending Abort!\n");
#endif
        goto LSO_ABORT;
    }

    /*
     ** Process Life Safety Operation Here
     */
#if PRINT_ENABLED
    fprintf(stderr,
        "Life Safety Operation: Received operation %d from process id %d for object %id\n",
        data.operation, data.processId, data.targetObject.instance);
#endif

    len =
        encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
        service_data->invoke_id, SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION);
#if PRINT_ENABLED
    fprintf(stderr, "Life Safety Operation: " "Sending Simple Ack!\n");
#endif

  LSO_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, "Life Safety Operation: " "Failed to send PDU (%s)!\n",
            strerror(errno));
#endif

    return;
}
Exemple #25
0
void handler_read_range(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_READ_RANGE_DATA data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    bool error = false;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    data.error_class = ERROR_CLASS_OBJECT;
    data.error_code = ERROR_CODE_UNKNOWN_OBJECT;
    /* 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, "RR: Segmented message.  Sending Abort!\n");
#endif
        goto RR_ABORT;
    }
    memset(&data, 0, sizeof(data));     /* start with blank canvas */
    len = rr_decode_service_request(service_request, service_len, &data);
#if PRINT_ENABLED
    if (len <= 0)
        fprintf(stderr, "RR: 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, "RR: Bad Encoding.  Sending Abort!\n");
#endif
        goto RR_ABORT;
    }

    /* assume that there is an error */
    error = true;
    len = Encode_RR_payload(&Temp_Buf[0], &data);
    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 =
            rr_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, &data);
#if PRINT_ENABLED
        fprintf(stderr, "RR: Sending Ack!\n");
#endif
        error = false;
    }
    if (error) {
        if (len == -2) {
            /* BACnet APDU too small to fit data, so proper response is 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, "RR: 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_RANGE,
                data.error_class, data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RR: Sending Error!\n");
#endif
        }
    }
  RR_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;
}
Exemple #26
0
uint8_t Send_Atomic_Write_File_Stream(
    uint32_t device_id,
    uint32_t file_instance,
    int fileStartPosition,
    BACNET_OCTET_STRING * fileData)
{
    BACNET_ADDRESS dest;
    BACNET_ADDRESS my_address;
    BACNET_NPDU_DATA npdu_data;
    unsigned max_apdu = 0;
    uint8_t invoke_id = 0;
    bool status = false;
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_ATOMIC_WRITE_FILE_DATA data;

    /* if we are forbidden to send, don't send! */
    if (!dcc_communication_enabled())
        return 0;

    /* is the device bound? */
    status = address_get_by_device(device_id, &max_apdu, &dest);
    /* is there a tsm available? */
    if (status)
        invoke_id = tsm_next_free_invokeID();
    if (invoke_id) {
        /* load the data for the encoding */
        data.object_type = OBJECT_FILE;
        data.object_instance = file_instance;
        data.access = FILE_STREAM_ACCESS;
        data.type.stream.fileStartPosition = fileStartPosition;
        status = octetstring_copy(&data.fileData[0], fileData);
        if (status) {
            /* encode the NPDU portion of the packet */
            datalink_get_my_address(&my_address);
            npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
            pdu_len =
                npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
                &my_address, &npdu_data);
            /* encode the APDU portion of the packet */
            len =
                awf_encode_apdu(&Handler_Transmit_Buffer[pdu_len], invoke_id,
                &data);
            pdu_len += len;
            /* will the APDU fit the target device?
               note: if there is a bottleneck router in between
               us and the destination, we won't know unless
               we have a way to check for that and update the
               max_apdu in the address binding table. */
            if ((unsigned) pdu_len <= max_apdu) {
                tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
                    &npdu_data, &Handler_Transmit_Buffer[0],
                    (uint16_t) pdu_len);
                bytes_sent =
                    datalink_send_pdu(&dest, &npdu_data,
                    &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
                if (bytes_sent <= 0)
                    fprintf(stderr,
                        "Failed to Send AtomicWriteFile Request (%s)!\n",
                        strerror(errno));
#endif
            } else {
                tsm_free_invoke_id(invoke_id);
                invoke_id = 0;
#if PRINT_ENABLED
                fprintf(stderr,
                    "Failed to Send AtomicWriteFile Request "
                    "(payload [%d] exceeds destination maximum APDU [%u])!\n",
                    pdu_len, max_apdu);
#endif
            }
        } else {
            tsm_free_invoke_id(invoke_id);
            invoke_id = 0;
#if PRINT_ENABLED
            fprintf(stderr,
                "Failed to Send AtomicWriteFile Request "
                "(payload [%d] exceeds octet string capacity)!\n", pdu_len);
#endif
        }
    }

    return invoke_id;
}
/** Handler for a ReadPropertyMultiple Service request.
 * @ingroup DSRPM
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 *   - if the response would be too large
 * - the result from each included read request, if it succeeds
 * - an Error if processing fails for all, or individual errors if only some fail,
 *   or there isn't enough room in the APDU to fit the data.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_read_property_multiple(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    int len = 0;
    uint16_t copy_len = 0;
    uint16_t decode_len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent;
    BACNET_ADDRESS my_address;
    BACNET_RPM_DATA rpmdata;
    int apdu_len = 0;
    int npdu_len = 0;
    int error = 0;

    /* jps_debug - see if we are utilizing all the buffer */
    /* memset(&Handler_Transmit_Buffer[0], 0xff, sizeof(Handler_Transmit_Buffer)); */
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
                        &npdu_data);
    if (service_data->segmented_message) {
        rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
        error = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RPM: Segmented message. Sending Abort!\r\n");
#endif
        goto RPM_FAILURE;
    }
    /* 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);
    for (;;) {
        /* Start by looking for an object ID */
        len =
            rpm_decode_object_id(&service_request[decode_len],
                                 service_len - decode_len, &rpmdata);
        if (len >= 0) {
            /* Got one so skip to next stage */
            decode_len += len;
        } else {
            /* bad encoding - skip to error/reject/abort handling */
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Bad Encoding.\n");
#endif
            error = len;
            goto RPM_FAILURE;
        }

        /* Test for case of indefinite Device object instance */
        if ((rpmdata.object_type == OBJECT_DEVICE) &&
                (rpmdata.object_instance == BACNET_MAX_INSTANCE)) {
            rpmdata.object_instance = Device_Object_Instance_Number();
        }

        /* Stick this object id into the reply - if it will fit */
        len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], &rpmdata);
        copy_len =
            memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0], apdu_len,
                    len, MAX_APDU);
        if (copy_len == 0) {
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Response too big!\r\n");
#endif
            rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
            error = BACNET_STATUS_ABORT;
            goto RPM_FAILURE;
        }

        apdu_len += copy_len;
        /* do each property of this object of the RPM request */
        for (;;) {
            /* Fetch a property */
            len =
                rpm_decode_object_property(&service_request[decode_len],
                                           service_len - decode_len, &rpmdata);
            if (len < 0) {
                /* bad encoding - skip to error/reject/abort handling */
#if PRINT_ENABLED
                fprintf(stderr, "RPM: Bad Encoding.\n");
#endif
                error = len;
                goto RPM_FAILURE;
            }
            decode_len += len;
            /* handle the special properties */
            if ((rpmdata.object_property == PROP_ALL) ||
                    (rpmdata.object_property == PROP_REQUIRED) ||
                    (rpmdata.object_property == PROP_OPTIONAL)) {
                struct special_property_list_t property_list;
                unsigned property_count = 0;
                unsigned index = 0;
                BACNET_PROPERTY_ID special_object_property;

                if (rpmdata.array_index != BACNET_ARRAY_ALL) {
                    /*  No array index options for this special property.
                       Encode error for this object property response */
                    len =
                        rpm_ack_encode_apdu_object_property(&Temp_Buf[0],
                                                            rpmdata.object_property, rpmdata.array_index);
                    copy_len =
                        memcopy(&Handler_Transmit_Buffer[npdu_len],
                                &Temp_Buf[0], apdu_len, len, MAX_APDU);
                    if (copy_len == 0) {
#if PRINT_ENABLED
                        fprintf(stderr,
                                "RPM: Too full to encode property!\r\n");
#endif
                        rpmdata.error_code =
                            ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                        error = BACNET_STATUS_ABORT;
                        goto RPM_FAILURE;
                    }
                    apdu_len += len;
                    len =
                        rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
                                ERROR_CLASS_PROPERTY,
                                ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY);
                    copy_len =
                        memcopy(&Handler_Transmit_Buffer[npdu_len],
                                &Temp_Buf[0], apdu_len, len, MAX_APDU);
                    if (copy_len == 0) {
#if PRINT_ENABLED
                        fprintf(stderr, "RPM: Too full to encode error!\r\n");
#endif
                        rpmdata.error_code =
                            ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                        error = BACNET_STATUS_ABORT;
                        goto RPM_FAILURE;
                    }
                    apdu_len += len;
                } else {
                    special_object_property = rpmdata.object_property;
                    Device_Objects_Property_List(rpmdata.object_type,
                                                 &property_list);
                    property_count =
                        RPM_Object_Property_Count(&property_list,
                                                  special_object_property);
                    if (property_count == 0) {
                        /* handle the error code - but use the special property */
                        len =
                            RPM_Encode_Property(&Handler_Transmit_Buffer
                                                [npdu_len], (uint16_t) apdu_len, MAX_APDU,
                                                &rpmdata);
                        if (len > 0) {
                            apdu_len += len;
                        } else {
#if PRINT_ENABLED
                            fprintf(stderr,
                                    "RPM: Too full for special property!\r\n");
#endif
                            error = len;
                            goto RPM_FAILURE;
                        }
                    } else {
                        for (index = 0; index < property_count; index++) {
                            rpmdata.object_property =
                                RPM_Object_Property(&property_list,
                                                    special_object_property, index);
                            len =
                                RPM_Encode_Property(&Handler_Transmit_Buffer
                                                    [npdu_len], (uint16_t) apdu_len, MAX_APDU,
                                                    &rpmdata);
                            if (len > 0) {
                                apdu_len += len;
                            } else {
#if PRINT_ENABLED
                                fprintf(stderr,
                                        "RPM: Too full for property!\r\n");
#endif
                                error = len;
                                goto RPM_FAILURE;
                            }
                        }
                    }
                }
            } else {
                /* handle an individual property */
                len =
                    RPM_Encode_Property(&Handler_Transmit_Buffer[npdu_len],
                                        (uint16_t) apdu_len, MAX_APDU, &rpmdata);
                if (len > 0) {
                    apdu_len += len;
                } else {
#if PRINT_ENABLED
                    fprintf(stderr,
                            "RPM: Too full for individual property!\r\n");
#endif
                    error = len;
                    goto RPM_FAILURE;
                }
            }
            if (decode_is_closing_tag_number(&service_request[decode_len], 1)) {
                /* Reached end of property list so cap the result list */
                decode_len++;
                len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
                copy_len =
                    memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
                            apdu_len, len, MAX_APDU);
                if (copy_len == 0) {
#if PRINT_ENABLED
                    fprintf(stderr, "RPM: Too full to encode object end!\r\n");
#endif
                    rpmdata.error_code =
                        ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                    error = BACNET_STATUS_ABORT;
                    goto RPM_FAILURE;
                } else {
                    apdu_len += copy_len;
                }
                break;  /* finished with this property list */
            }
        }
        if (decode_len >= service_len) {
            /* Reached the end so finish up */
            break;
        }
    }

    if (apdu_len > service_data->max_resp) {
        /* too big for the sender - send an abort */
        rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
        error = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RPM: Message too large.  Sending Abort!\n");
#endif
        goto RPM_FAILURE;
    }

RPM_FAILURE:
    if (error) {
        if (error == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                  service_data->invoke_id,
                                  abort_convert_error_code(rpmdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Abort!\n");
#endif
        } else if (error == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                     service_data->invoke_id, SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
                                     rpmdata.error_class, rpmdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Error!\n");
#endif
        } else if (error == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                   service_data->invoke_id,
                                   reject_convert_error_code(rpmdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Reject!\n");
#endif
        }
    }

    pdu_len = apdu_len + npdu_len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
                          pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0) {
        fprintf(stderr, "RPM: Failed to send PDU (%s)!\n", strerror(errno));
    }
#else
    bytes_sent = bytes_sent;
#endif
}
Exemple #28
0
static bool cov_send_request(
    BACNET_COV_SUBSCRIPTION * cov_subscription,
    BACNET_PROPERTY_VALUE * value_list)
{
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;
    int bytes_sent = 0;
    uint8_t invoke_id = 0;
    bool status = false;        /* return value */
    BACNET_COV_DATA cov_data;

    if (!dcc_communication_enabled()) {
        return status;
    }
#if PRINT_ENABLED
    fprintf(stderr, "COVnotification: requested\n");
#endif
    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], &cov_subscription->dest,
        &my_address, &npdu_data);
    /* load the COV data structure for outgoing message */
    cov_data.subscriberProcessIdentifier =
        cov_subscription->subscriberProcessIdentifier;
    cov_data.initiatingDeviceIdentifier = Device_Object_Instance_Number();
    cov_data.monitoredObjectIdentifier.type =
        cov_subscription->monitoredObjectIdentifier.type;
    cov_data.monitoredObjectIdentifier.instance =
        cov_subscription->monitoredObjectIdentifier.instance;
    cov_data.timeRemaining = cov_subscription->lifetime;
    cov_data.listOfValues = value_list;
    if (cov_subscription->flag.issueConfirmedNotifications) {
        invoke_id = tsm_next_free_invokeID();
        if (invoke_id) {
            cov_subscription->invokeID = invoke_id;
            len =
                ccov_notify_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                invoke_id, &cov_data);
        } else {
            goto COV_FAILED;
        }
    } else {
        len =
            ucov_notify_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            &cov_data);
    }
    pdu_len += len;
    if (cov_subscription->flag.issueConfirmedNotifications) {
        tsm_set_confirmed_unsegmented_transaction(invoke_id,
            &cov_subscription->dest, &npdu_data, &Handler_Transmit_Buffer[0],
            (uint16_t) pdu_len);
    }
    bytes_sent =
        datalink_send_pdu(&cov_subscription->dest, &npdu_data,
        &Handler_Transmit_Buffer[0], pdu_len);
    if (bytes_sent > 0) {
        status = true;
    }

  COV_FAILED:

    return status;
}
Exemple #29
0
/** Sends a Write Property Multiple request.
 * @param device_id [in] ID of the destination device
 * @param write_access_data [in] Ptr to structure with the linked list of
 *        objects and properties to be written.
 * @return invoke id of outgoing message, or 0 if device is not bound or no tsm available
 */
uint8_t Send_Write_Property_Multiple_Request_Data(
    uint32_t device_id,
    BACNET_WRITE_ACCESS_DATA * write_access_data)
{
    BACNET_ADDRESS dest;
    BACNET_ADDRESS my_address;
    unsigned max_apdu = 0;
    uint8_t invoke_id = 0;
    bool status = false;
    int len = 0;
    int pdu_len = 0;
    int bytes_sent = 0;
    BACNET_NPDU_DATA npdu_data;

    /* is the device bound? */
    status = address_get_by_device(device_id, &max_apdu, &dest);
    /* is there a tsm available? */
    if (status)
        invoke_id = tsm_next_free_invokeID();
    if (invoke_id) {
        /* encode the NPDU portion of the packet */
        datalink_get_my_address(&my_address);
        npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
        pdu_len =
            npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, &my_address,
            &npdu_data);

        len =
            wpm_encode_apdu(&Handler_Transmit_Buffer[pdu_len], max_apdu,
            invoke_id, write_access_data);

        pdu_len += len;

        /* will it fit in the sender?
           note: if there is a bottleneck router in between
           us and the destination, we won't know unless
           we have a way to check for that and update the
           max_apdu in the address binding table. */
        if ((unsigned) pdu_len < max_apdu) {
            tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
                &npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
            bytes_sent =
                datalink_send_pdu(&dest, &npdu_data,
                &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
            if (bytes_sent <= 0)
                fprintf(stderr, "Failed to Send WriteProperty Request (%s)!\n",
                    strerror(errno));
#endif
        } else {
            tsm_free_invoke_id(invoke_id);
            invoke_id = 0;
#if PRINT_ENABLED
            fprintf(stderr,
                "Failed to Send WriteProperty Request "
                "(exceeds destination maximum APDU)!\n");
#endif
        }
    }

    return invoke_id;
}
Exemple #30
0
/** Handler for a COV Subscribe Service request.
 * @ingroup DSCOV
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 * - an ACK, if cov_subscribe() succeeds
 * - an Error if cov_subscribe() fails
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_cov_subscribe(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_SUBSCRIBE_COV_DATA cov_data;
    int len = 0;
    int pdu_len = 0;
    int npdu_len = 0;
    int apdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    bool success = false;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;
    bool error = false;

    /* initialize a common abort code */
    cov_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_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 = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Segmented message.  Sending Abort!\n");
#endif
        error = true;
        goto COV_ABORT;
    }
    len =
        cov_subscribe_decode_service_request(service_request, service_len,
        &cov_data);
#if PRINT_ENABLED
    if (len <= 0)
        fprintf(stderr, "SubscribeCOV: Unable to decode Request!\n");
#endif
    if (len < 0) {
        error = true;
        goto COV_ABORT;
    }
    cov_data.error_class = ERROR_CLASS_OBJECT;
    cov_data.error_code = ERROR_CODE_UNKNOWN_OBJECT;
    success =
        cov_subscribe(src, &cov_data, &cov_data.error_class,
        &cov_data.error_code);
    if (success) {
        apdu_len =
            encode_simple_ack(&Handler_Transmit_Buffer[npdu_len],
            service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV);
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Sending Simple Ack!\n");
#endif
    } else {
        len = BACNET_STATUS_ERROR;
        error = true;
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Sending Error!\n");
#endif
    }
  COV_ABORT:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                abort_convert_error_code(cov_data.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV,
                cov_data.error_class, cov_data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                reject_convert_error_code(cov_data.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Reject!\n");
#endif
        }
    }
    pdu_len = npdu_len + apdu_len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr, "SubscribeCOV: Failed to send PDU (%s)!\n",
            strerror(errno));
#else
    bytes_sent = bytes_sent;
#endif

    return;
}