コード例 #1
0
ファイル: rpm.c プロジェクト: TemcoHeng/Bacnet_Modbus_Gateway
int rpm_ack_decode_object_property(
    uint8_t * apdu,
    unsigned apdu_len,
    BACNET_PROPERTY_ID * object_property,
    uint32_t * array_index)
{
    unsigned len = 0;
    unsigned tag_len = 0;
    uint8_t tag_number = 0;
    uint32_t len_value_type = 0;
    uint32_t property = 0;      /* for decoding */
    uint32_t array_value = 0;   /* for decoding */

    /* check for valid pointers */
    if (apdu && apdu_len && object_property && array_index) {
        /* Tag 2: propertyIdentifier */
        if (!IS_CONTEXT_SPECIFIC(apdu[len]))
            return -1;
        len +=
            decode_tag_number_and_value(&apdu[len], &tag_number,
            &len_value_type);
        if (tag_number != 2)
            return -1;
        len += decode_enumerated(&apdu[len], len_value_type, &property);
        if (object_property)
            *object_property = (BACNET_PROPERTY_ID) property;
        /* Tag 3: Optional propertyArrayIndex */
        if ((len < apdu_len) && IS_CONTEXT_SPECIFIC(apdu[len]) &&
            (!IS_CLOSING_TAG(apdu[len]))) {
            tag_len =
                (unsigned) decode_tag_number_and_value(&apdu[len], &tag_number,
                &len_value_type);
            if (tag_number == 3) {
                len += tag_len;
                len +=
                    decode_unsigned(&apdu[len], len_value_type, &array_value);
                *array_index = array_value;
            } else {
                *array_index = BACNET_ARRAY_ALL;
            }
        } else {
            *array_index = BACNET_ARRAY_ALL;
        }
    }

    return (int) len;
}
コード例 #2
0
ファイル: h_rp_a.c プロジェクト: aniston/node-bacnet
/** Decode the received RP data into a linked list of the results, with the
 *  same data structure used by RPM ACK replies.
 *  This function is provided to provide common handling for RP and RPM data,
 *  and fully decodes the value(s) portion of the data for one property.
 * @ingroup DSRP
 * @see rp_ack_decode_service_request(), rpm_ack_decode_service_request()
 *
 * @param apdu [in] The received apdu data.
 * @param apdu_len [in] Total length of the apdu.
 * @param read_access_data [out] Pointer to the head of the linked list
 * 			where the RP data is to be stored.
 * @return Number of decoded bytes (could be less than apdu_len),
 * 			or -1 on decoding error.
 */
int rp_ack_fully_decode_service_request(
    uint8_t * apdu,
    int apdu_len,
    BACNET_READ_ACCESS_DATA * read_access_data)
{
    int decoded_len = 0;        /* return value */
    BACNET_READ_PROPERTY_DATA rp1data;
    BACNET_PROPERTY_REFERENCE *rp1_property;    /* single property */
    BACNET_APPLICATION_DATA_VALUE *value, *old_value;
    uint8_t *vdata;
    int vlen, len;

    decoded_len = rp_ack_decode_service_request(apdu, apdu_len, &rp1data);
    if (decoded_len > 0) {
        /* Then we have to transfer to the BACNET_READ_ACCESS_DATA structure
         * and decode the value(s) portion
         */
        read_access_data->object_type = rp1data.object_type;
        read_access_data->object_instance = rp1data.object_instance;
        rp1_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
        read_access_data->listOfProperties = rp1_property;
        if (rp1_property == NULL) {
            /* can't proceed if calloc failed. */
            return BACNET_STATUS_ERROR;
        }
        rp1_property->propertyIdentifier = rp1data.object_property;
        rp1_property->propertyArrayIndex = rp1data.array_index;
        /* Is there no Error case possible here, as there is when decoding RPM? */
        /* rp1_property->error.error_class = ?? */
        /* rp_ack_decode_service_request() processing already removed the
         * Opening and Closing '3' Tags.
         * note: if this is an array, there will be
         more than one element to decode */
        vdata = rp1data.application_data;
        vlen = rp1data.application_data_len;
        value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
        rp1_property->value = value;
        old_value = value;
        while (value && vdata && (vlen > 0)) {
            if (IS_CONTEXT_SPECIFIC(*vdata)) {
                len =
                    bacapp_decode_context_data(vdata, vlen, value,
                                               rp1_property->propertyIdentifier);
            } else {
                len = bacapp_decode_application_data(vdata, vlen, value);
            }
            if (len < 0) {
                /* unable to decode the data */
                while (value) {
                    /* free the linked list of values */
                    old_value = value;
                    value = value->next;
                    free(old_value);
                }
                free(rp1_property);
                read_access_data->listOfProperties = NULL;
                return len;
            }
            decoded_len += len;
            vlen -= len;
            vdata += len;
            /* If unexpected closing tag here: */
            if (vlen && decode_is_closing_tag_number(vdata, 3)) {
                decoded_len++;
                vlen--;
                vdata++;
                break;
            } else {
                if (len == 0) {
                    /* nothing decoded and no closing tag, so malformed */
                    while (value) {
                        /* free the linked list of values */
                        old_value = value;
                        value = value->next;
                        free(old_value);
                    }
                    free(rp1_property);
                    read_access_data->listOfProperties = NULL;
                    return BACNET_STATUS_ERROR;
                }
                if (vlen > 0) {
                    /* If more values */
                    old_value = value;
                    value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
                    old_value->next = value;
                }
            }
        }
    }

    return decoded_len;
}
コード例 #3
0
ファイル: h_rpm_a.c プロジェクト: 8bitgeek/bacnet-stack
/** Decode the received RPM data and make a linked list of the results.
 * @ingroup DSRPM
 *
 * @param apdu [in] The received apdu data.
 * @param apdu_len [in] Total length of the apdu.
 * @param read_access_data [out] Pointer to the head of the linked list
 * 			where the RPM data is to be stored.
 * @return The number of bytes decoded, or -1 on error
 */
int rpm_ack_decode_service_request(
    uint8_t * apdu,
    int apdu_len,
    BACNET_READ_ACCESS_DATA * read_access_data)
{
    int decoded_len = 0;        /* return value */
    uint32_t error_value = 0;   /* decoded error value */
    int len = 0;        /* number of bytes returned from decoding */
    uint8_t tag_number = 0;     /* decoded tag number */
    uint32_t len_value = 0;     /* decoded length value */
    BACNET_READ_ACCESS_DATA *rpm_object;
    BACNET_READ_ACCESS_DATA *old_rpm_object;
    BACNET_PROPERTY_REFERENCE *rpm_property;
    BACNET_PROPERTY_REFERENCE *old_rpm_property;
    BACNET_APPLICATION_DATA_VALUE *value;
    BACNET_APPLICATION_DATA_VALUE *old_value;

    assert(read_access_data != NULL);
    rpm_object = read_access_data;
    old_rpm_object = rpm_object;
    while (rpm_object && apdu_len) {
        len =
            rpm_ack_decode_object_id(apdu, apdu_len, &rpm_object->object_type,
            &rpm_object->object_instance);
        if (len <= 0) {
            old_rpm_object->next = NULL;
            free(rpm_object);
            break;
        }
        decoded_len += len;
        apdu_len -= len;
        apdu += len;
        rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
        rpm_object->listOfProperties = rpm_property;
        old_rpm_property = rpm_property;
        while (rpm_property && apdu_len) {
            len =
                rpm_ack_decode_object_property(apdu, apdu_len,
                &rpm_property->propertyIdentifier,
                &rpm_property->propertyArrayIndex);
            if (len <= 0) {
                old_rpm_property->next = NULL;
                if (rpm_object->listOfProperties == rpm_property) {
                    /* was this the only property in the list? */
                    rpm_object->listOfProperties = NULL;
                }
                free(rpm_property);
                break;
            }
            decoded_len += len;
            apdu_len -= len;
            apdu += len;
            if (apdu_len && decode_is_opening_tag_number(apdu, 4)) {
                /* propertyValue */
                decoded_len++;
                apdu_len--;
                apdu++;
                /* note: if this is an array, there will be
                   more than one element to decode */
                value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
                rpm_property->value = value;
                old_value = value;
                while (value && (apdu_len > 0)) {
                    if (IS_CONTEXT_SPECIFIC(*apdu)) {
                        len =
                            bacapp_decode_context_data(apdu, apdu_len, value,
                            rpm_property->propertyIdentifier);
                    } else {
                        len =
                            bacapp_decode_application_data(apdu, apdu_len,
                            value);
                    }
                    /* If len == 0 then it's an empty structure, which is OK. */
                    if (len < 0) {
                        /* problem decoding */
                        /* calling function will free the memory */
                        return BACNET_STATUS_ERROR;
                    }
                    decoded_len += len;
                    apdu_len -= len;
                    apdu += len;
                    if (apdu_len && decode_is_closing_tag_number(apdu, 4)) {
                        decoded_len++;
                        apdu_len--;
                        apdu++;
                        break;
                    } else {
                        old_value = value;
                        value =
                            calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
                        old_value->next = value;
                    }
                }
            } else if (apdu_len && decode_is_opening_tag_number(apdu, 5)) {
                /* propertyAccessError */
                decoded_len++;
                apdu_len--;
                apdu++;
                /* decode the class and code sequence */
                len =
                    decode_tag_number_and_value(apdu, &tag_number, &len_value);
                decoded_len += len;
                apdu_len -= len;
                apdu += len;
                /* FIXME: we could validate that the tag is enumerated... */
                len = decode_enumerated(apdu, len_value, &error_value);
                rpm_property->error.error_class = error_value;
                decoded_len += len;
                apdu_len -= len;
                apdu += len;
                len =
                    decode_tag_number_and_value(apdu, &tag_number, &len_value);
                decoded_len += len;
                apdu_len -= len;
                apdu += len;
                /* FIXME: we could validate that the tag is enumerated... */
                len = decode_enumerated(apdu, len_value, &error_value);
                rpm_property->error.error_code = error_value;
                decoded_len += len;
                apdu_len -= len;
                apdu += len;
                if (apdu_len && decode_is_closing_tag_number(apdu, 5)) {
                    decoded_len++;
                    apdu_len--;
                    apdu++;
                }
            }
            old_rpm_property = rpm_property;
            rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
            old_rpm_property->next = rpm_property;
        }
        len = rpm_decode_object_end(apdu, apdu_len);
        if (len) {
            decoded_len += len;
            apdu_len -= len;
            apdu += len;
        }
        if (apdu_len) {
            old_rpm_object = rpm_object;
            rpm_object = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
            old_rpm_object->next = rpm_object;
        }
    }

    return decoded_len;
}
コード例 #4
0
ファイル: rpm.c プロジェクト: TemcoHeng/Bacnet_Modbus_Gateway
/*  BACnetPropertyReference ::= SEQUENCE {
        propertyIdentifier [0] BACnetPropertyIdentifier,
        propertyArrayIndex [1] Unsigned OPTIONAL
        --used only with array datatype
        -- if omitted with an array the entire array is referenced
    }
*/
int rpm_decode_object_property(
    uint8_t * apdu,
    unsigned apdu_len,
    BACNET_RPM_DATA * rpmdata)
{
    unsigned len = 0;
    unsigned option_len = 0;
    uint8_t tag_number = 0;
    uint32_t len_value_type = 0;
    uint32_t property = 0;      /* for decoding */
    uint32_t array_value = 0;   /* for decoding */

    /* check for valid pointers */
    if (apdu && apdu_len && rpmdata) {
        /* Tag 0: propertyIdentifier */

        if (!IS_CONTEXT_SPECIFIC(apdu[len])) {
           
		    rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG;
           
		    return BACNET_STATUS_REJECT;
        
		}

        len +=
            decode_tag_number_and_value(&apdu[len], &tag_number,
            &len_value_type);
        if (tag_number != 0) {
            rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG;
            return BACNET_STATUS_REJECT;
        }
        /* Should be at least the unsigned value + 1 tag left */
        if ((len + len_value_type) >= apdu_len) {
            rpmdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
            return BACNET_STATUS_REJECT;
        }
        len += decode_enumerated(&apdu[len], len_value_type, &property);
        rpmdata->object_property = (BACNET_PROPERTY_ID) property;
        /* Assume most probable outcome */
        rpmdata->array_index = BACNET_ARRAY_ALL;
        /* Tag 1: Optional propertyArrayIndex */
        if (IS_CONTEXT_SPECIFIC(apdu[len]) && !IS_CLOSING_TAG(apdu[len])) {
            option_len =
                (unsigned) decode_tag_number_and_value(&apdu[len], &tag_number,
                &len_value_type);
            if (tag_number == 1) {
                len += option_len;
                /* Should be at least the unsigned array index + 1 tag left */
                if ((len + len_value_type) >= apdu_len) {
                    rpmdata->error_code =
                        ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
                    return BACNET_STATUS_REJECT;
                }
                len +=
                    decode_unsigned(&apdu[len], len_value_type, &array_value);
                rpmdata->array_index = array_value;
            }
        }
    }

    return (int) len;
}