int ptransfer_ack_decode_apdu( uint8_t * apdu, int apdu_len, /* total length of the apdu */ uint8_t * invoke_id, BACNET_PRIVATE_TRANSFER_DATA * private_data) { int len = 0; int offset = 0; if (!apdu) return -1; /* optional checking - most likely was already done prior to this call */ if (apdu[0] != PDU_TYPE_COMPLEX_ACK) return -1; *invoke_id = apdu[1]; if (apdu[2] != SERVICE_CONFIRMED_PRIVATE_TRANSFER) return -1; offset = 3; if (apdu_len > offset) { len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset, private_data); } return len; }
int uptransfer_decode_apdu( uint8_t * apdu, unsigned apdu_len, BACNET_PRIVATE_TRANSFER_DATA * private_data) { int len = 0; unsigned offset = 0; if (!apdu) { return -1; } /* optional checking - most likely was already done prior to this call */ if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST) { return -1; } if (apdu[1] != SERVICE_UNCONFIRMED_PRIVATE_TRANSFER) { return -1; } offset = 2; if (apdu_len > offset) { len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset, private_data); } return len; }
int ptransfer_decode_apdu( uint8_t * apdu, unsigned apdu_len, uint8_t * invoke_id, BACNET_PRIVATE_TRANSFER_DATA * private_data) { int len = 0; unsigned offset = 0; if (!apdu) return -1; /* optional checking - most likely was already done prior to this call */ if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) return -1; /* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */ /* invoke id - filled in by net layer */ *invoke_id = apdu[2]; if (apdu[3] != SERVICE_CONFIRMED_PRIVATE_TRANSFER) return -1; offset = 4; if (apdu_len > offset) { len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset, private_data); } return len; }
void handler_conf_private_trans_ack( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data) { BACNET_PRIVATE_TRANSFER_DATA data; int len; /* * Note: * We currently don't look at the source address and service data * but we probably should to verify that the ack is oneit is what * we were expecting. But this is just to silence some compiler * warnings from Borland. */ src = src; service_data = service_data; len = 0; #if PRINT_ENABLED printf("Received Confirmed Private Transfer Ack!\n"); #endif len = ptransfer_decode_service_request(service_request, service_len, &data); /* Same decode for ack as for service request! */ if (len < 0) { #if PRINT_ENABLED printf("cpta: Bad Encoding!\n"); #endif } ProcessPTA(&data); /* See what to do with the response */ return; }
void handler_unconfirmed_private_transfer( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src) { BACNET_PRIVATE_TRANSFER_DATA private_data; int len = 0; #if PRINT_ENABLED fprintf(stderr, "Received Unconfirmed Private Transfer Request!\n"); #endif (void) src; len = ptransfer_decode_service_request(service_request, service_len, &private_data); if (len >= 0) { #if PRINT_ENABLED fprintf(stderr, "UnconfirmedPrivateTransfer: " "vendorID=%u serviceNumber=%u\n", private_data.vendorID, private_data.serviceNumber); #endif } }
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; }