Revert "Added segmentation support for server reply. (#974)"

This reverts commit 3ea710f92f.
This commit is contained in:
Steve Karg
2025-11-17 22:26:50 -06:00
parent 003073b71e
commit 2a6c251803
25 changed files with 144 additions and 2112 deletions
-5
View File
@@ -16,11 +16,6 @@ The git repositories are hosted at the following sites:
### Security
### Added
* Added segmentation support for server devices for some services.
Configure BACNET_SEGMENTATION_ENABLED=1 to include in the library,
and adjust BACNET_MAX_SEGMENTS_ACCEPTED for maximum number of segments. (#974)
### Changed
* Changed basic object API for units properties to use BACNET_ENGINEERING_UNITS
-9
View File
@@ -84,11 +84,6 @@ option(
"compile with secure-connect support"
OFF)
option(
BACNET_SEGMENTATION_ENABLED
"enable segmentation"
ON)
if(NOT (BACDL_ETHERNET OR
BACDL_MSTP OR
BACDL_ARCNET OR
@@ -677,8 +672,6 @@ add_library(${PROJECT_NAME}
src/bacnet/rp.h
src/bacnet/rpm.c
src/bacnet/rpm.h
$<$<BOOL:${BACNET_SEGMENTATION_ENABLED}>:src/bacnet/segmentack.c>
$<$<BOOL:${BACNET_SEGMENTATION_ENABLED}>:src/bacnet/segmentack.h>
src/bacnet/timer_value.c
src/bacnet/timer_value.h
src/bacnet/timestamp.c
@@ -730,7 +723,6 @@ target_compile_definitions(
$<$<BOOL:${BACDL_NONE}>:BACDL_NONE>
$<$<BOOL:${BACNET_PROPERTY_LISTS}>:BACNET_PROPERTY_LISTS=1>
$<$<BOOL:${BAC_ROUTING}>:BAC_ROUTING>
$<$<BOOL:${BACNET_SEGMENTATION_ENABLED}>:BACNET_SEGMENTATION_ENABLED>
$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:BACNET_STACK_STATIC_DEFINE>
PRIVATE
PRINT_ENABLED=1)
@@ -1283,4 +1275,3 @@ message(STATUS "BACNET: BACDL_ARCNET:...................\"${BACDL_ARCNET}\"")
message(STATUS "BACNET: BACDL_MSTP:.....................\"${BACDL_MSTP}\"")
message(STATUS "BACNET: BACDL_ZIGBEE:...................\"${BACDL_ZIGBEE}\"")
message(STATUS "BACNET: BACDL_ETHERNET:.................\"${BACDL_ETHERNET}\"")
message(STATUS "BACNET: BACNET_SEGMENTATION_ENABLED:....\"${BACNET_SEGMENTATION_ENABLED}\"")
-4
View File
@@ -224,10 +224,6 @@ server-discover:
server-mini:
$(MAKE) LEGACY=true NOTIFY=false -s -C apps $@
.PHONY: server-segmentation
server-segmentation:
$(MAKE) LEGACY=true SEGMENT=true -s -C apps server
.PHONY: sc-hub
sc-hub:
$(MAKE) LEGACY=true BACDL=bsc -s -C apps $@
-5
View File
@@ -223,11 +223,6 @@ ifeq (${LEGACY},true)
BACNET_DEFINES += -DBACNET_STACK_DEPRECATED_DISABLE
endif
ifeq (${SEGMENT},true)
# enable segmentation support
BACNET_DEFINES += -DBACNET_SEGMENTATION_ENABLED=1
endif
ifeq (${NOTIFY},false)
# disable intrinsic reporting
else
-14
View File
@@ -174,20 +174,6 @@ static void Init_Service_Handlers(void)
(unsigned)object_data.object_instance);
}
}
#if BACNET_SEGMENTATION_ENABLED
printf("Segmentation is enabled.\n");
/* create extra object to stress the object list */
for (i = 0; i < 500; i++) {
object_data.object_instance = BACNET_MAX_INSTANCE;
object_data.object_type = OBJECT_ANALOG_INPUT;
if (Device_Create_Object(&object_data)) {
printf(
"Created object %s-%u\n",
bactext_object_type_name(object_data.object_type),
(unsigned)object_data.object_instance);
}
}
#endif
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS, handler_who_is_who_am_i_unicast);
-5
View File
@@ -58,11 +58,6 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
return status;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
{
return SEGMENTATION_NONE;
}
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
-15
View File
@@ -32,21 +32,6 @@ typedef struct _confirmed_service_ack_data {
uint8_t proposed_window_number;
} BACNET_CONFIRMED_SERVICE_ACK_DATA;
typedef struct BACnet_Apdu_Fixed_Header {
/* pdu type Confirmed Request or Complex ACK */
uint8_t pdu_type;
union {
/* Data for pdu type PDU_TYPE_CONFIRMED_SERVICE_REQUEST */
struct _confirmed_service_data request_data;
/* Data for pdu type PDU_TYPE_COMPLEX_ACK */
struct _confirmed_service_ack_data ack_data;
/* Common data for both types */
struct _confirmed_service_ack_data common_data;
} service_data;
/* Service number */
uint8_t service_choice;
} BACNET_APDU_FIXED_HEADER;
uint8_t apdu_network_priority(void);
void apdu_network_priority_set(uint8_t pri);
-16
View File
@@ -212,24 +212,8 @@ typedef struct BACnet_Object_Id {
uint32_t instance;
} BACNET_OBJECT_ID;
#if !defined(BACNET_MAX_SEGMENTS_ACCEPTED)
#if BACNET_SEGMENTATION_ENABLED
/* note: BACNET_MAX_SEGMENTS_ACCEPTED can be 1..255.
ASDU in this library is usually sized for 16-bit at 65535 max.
Therefore, the default here is limited to avoid overflow warnings. */
#define BACNET_MAX_SEGMENTS_ACCEPTED 32
#else
#define BACNET_MAX_SEGMENTS_ACCEPTED 1
#endif
#endif
#if !defined(MAX_APDU)
#define MAX_APDU 1476
#endif
#define MAX_NPDU (1 + 1 + 2 + 1 + MAX_MAC_LEN + 2 + 1 + MAX_MAC_LEN + 1 + 1 + 2)
#define MAX_PDU (MAX_APDU + MAX_NPDU)
/* Application Service Data Unit (ASDU) that has not yet been segmented
into a protocol data unit (PDU) by the lower layer. */
#define MAX_ASDU ((MAX_APDU * BACNET_MAX_SEGMENTS_ACCEPTED) + MAX_NPDU)
#define BACNET_ID_VALUE(bacnet_object_instance, bacnet_object_type) \
((((bacnet_object_type) & BACNET_MAX_OBJECT) << BACNET_INSTANCE_BITS) | \
+2 -40
View File
@@ -45,10 +45,6 @@ static struct Address_Cache_Entry {
uint8_t Flags;
uint32_t device_id;
unsigned max_apdu;
#if BACNET_SEGMENTATION_ENABLED
uint8_t segmentation;
uint16_t maxsegments;
#endif
BACNET_ADDRESS address;
uint32_t TimeToLive;
} Address_Cache[MAX_ADDRESS_CACHE];
@@ -350,16 +346,9 @@ void address_set_device_TTL(
* @param device_id Device-Id
* @param max_apdu Pointer to a variable, taking the maximum APDU size.
* @param src Pointer to address structure for return.
* @param segmentation Pointer to a variable, taking the BACNET_SEGMENTATION
* flag.
* @param maxsegments Pointer to a variable, taking the maximum segments.
*/
bool address_segment_get_by_device(
uint32_t device_id,
unsigned *max_apdu,
BACNET_ADDRESS *src,
uint8_t *segmentation,
uint16_t *maxsegments)
bool address_get_by_device(
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS *src)
{
struct Address_Cache_Entry *pMatch;
bool found = false; /* return value */
@@ -375,20 +364,6 @@ bool address_segment_get_by_device(
if (max_apdu) {
*max_apdu = pMatch->max_apdu;
}
if (segmentation) {
#if BACNET_SEGMENTATION_ENABLED
*segmentation = pMatch->segmentation;
#else
*segmentation = SEGMENTATION_NONE;
#endif
}
if (maxsegments) {
#if BACNET_SEGMENTATION_ENABLED
*maxsegments = pMatch->maxsegments;
#else
*maxsegments = 1;
#endif
}
/* Prove we found it */
found = true;
}
@@ -400,19 +375,6 @@ bool address_segment_get_by_device(
return found;
}
/**
* @brief Return the cached addresBACNET_STACK_EXPORT
s for the given device-id
* @param device_id Device-Id
* @param max_apdu Pointer to a variable, taking the maximum APDU size.
* @param src Pointer to address structure for return.
*/
bool address_get_by_device(
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS *src)
{
return address_segment_get_by_device(device_id, max_apdu, src, NULL, NULL);
}
/**
* Find a device id from a given MAC address.
*
-8
View File
@@ -43,14 +43,6 @@ BACNET_STACK_EXPORT
bool address_get_by_device(
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS *src);
BACNET_STACK_EXPORT
bool address_segment_get_by_device(
uint32_t device_id,
unsigned *max_apdu,
BACNET_ADDRESS *src,
uint8_t *segmentation,
uint16_t *maxsegments);
BACNET_STACK_EXPORT
bool address_get_by_index(
unsigned index,
-8
View File
@@ -1145,11 +1145,7 @@ uint8_t Device_Protocol_Revision(void)
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
{
#if BACNET_SEGMENTATION_ENABLED
return SEGMENTATION_BOTH;
#else
return SEGMENTATION_NONE;
#endif
}
/**
@@ -1620,12 +1616,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
rpdata->object_instance, rpdata->array_index,
Device_Object_List_Element_Encode, count, apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
#if BACNET_SEGMENTATION_ENABLED
rpdata->error_code = ERROR_CODE_ABORT_BUFFER_OVERFLOW;
#else
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
#endif
} else if (apdu_len == BACNET_STATUS_ERROR) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
+24 -290
View File
@@ -26,10 +26,6 @@ static uint16_t Timeout_Milliseconds = 3000;
/* Number of APDU Retries */
static uint8_t Number_Of_Retries = 3;
static uint8_t Local_Network_Priority; /* Fixing test 10.1.2 Network priority */
#if BACNET_SEGMENTATION_ENABLED
/* APDU Segment Timeout in Milliseconds */
static uint16_t Segment_Timeout_Milliseconds = 5000;
#endif
/* a simple table for crossing the services supported */
static BACNET_SERVICES_SUPPORTED
@@ -556,109 +552,6 @@ static bool apdu_unconfirmed_dcc_disabled(uint8_t service_choice)
return status;
}
/* Invoke special handler for confirmed service */
static void invoke_confirmed_service_service_request(
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data,
uint8_t service_choice,
uint8_t *service_request,
uint32_t service_request_len)
{
if (apdu_confirmed_dcc_disabled(service_choice)) {
/* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice
APDUs shall be processed and no messages shall be
initiated. */
return;
}
if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
(Confirmed_Function[service_choice])) {
Confirmed_Function[service_choice](
service_request, service_request_len, src, service_data);
} else if (Unrecognized_Service_Handler) {
Unrecognized_Service_Handler(
service_request, service_request_len, src, service_data);
}
}
#if BACNET_SEGMENTATION_ENABLED
/** Handler for messages with segmentation :
- store new packet if sequence number is ok
- NACK packet if sequence number is not ok
- call the final functions with reassembled data when last packet ok is
received
*/
static void apdu_handler_confirmed_service_segment(
BACNET_ADDRESS *src,
uint8_t *apdu, /* APDU data */
uint32_t apdu_len)
{
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t internal_service_id = 0;
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
uint32_t len = 0; /* counts where we are in PDU */
bool segment_ok;
len = apdu_decode_confirmed_service_request(
&apdu[0], /* APDU data */
apdu_len, &service_data, &service_choice, &service_request,
&service_request_len);
if (len == 0) {
/* service data unable to be decoded - simply drop */
return;
}
/* new segment : memorize it */
segment_ok = tsm_set_segmented_confirmed_service_received(
src, &service_data, &internal_service_id, &service_request,
&service_request_len);
/* last segment */
if (segment_ok && !service_data.more_follows) {
/* Clear peer information */
tsm_clear_peer_id(internal_service_id);
/* Invoke service handler */
invoke_confirmed_service_service_request(
src, &service_data, service_choice, service_request,
service_request_len);
/* We must free invoke_id, and associated data */
tsm_free_invoke_id_check(internal_service_id, NULL, true);
}
}
#endif
/* Handler for normal message without segmentation, or segmented complete
* message reassembled all-in-one */
static void apdu_handler_confirmed_service(
BACNET_ADDRESS *src,
uint8_t *apdu, /* APDU data */
uint32_t apdu_len)
{
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
uint32_t len = 0; /* counts where we are in PDU */
len = apdu_decode_confirmed_service_request(
&apdu[0], /* APDU data */
apdu_len, &service_data, &service_choice, &service_request,
&service_request_len);
if (len == 0) {
/* service data unable to be decoded - simply drop */
return;
}
#if BACNET_SEGMENTATION_ENABLED
/* Check for unexpected request is received in active TSM state */
if (tsm_is_invalid_apdu_in_this_state(src, &service_data)) {
return;
}
#endif
invoke_confirmed_service_service_request(
src, &service_data, service_choice, service_request,
service_request_len);
}
/** Process the APDU header and invoke the appropriate service handler
* to manage the received request.
* Almost all requests and ACKs invoke this function.
@@ -674,15 +567,11 @@ void apdu_handler(
uint16_t apdu_len)
{
BACNET_PDU_TYPE pdu_type;
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
int len = 0; /* counts where we are in PDU */
#if BACNET_SEGMENTATION_ENABLED
uint8_t sequence_number = 0;
uint8_t actual_window_size = 0;
bool nak = false;
#endif
#if !BACNET_SVC_SERVER
uint8_t invoke_id = 0;
BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = { 0 };
@@ -701,14 +590,27 @@ void apdu_handler(
pdu_type = apdu[0] & 0xF0;
switch (pdu_type) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
/* segmented_message_reception ? */
#if BACNET_SEGMENTATION_ENABLED
if (apdu[0] & BIT(3)) {
apdu_handler_confirmed_service_segment(src, apdu, apdu_len);
} else
#endif
{
apdu_handler_confirmed_service(src, apdu, apdu_len);
len = apdu_decode_confirmed_service_request(
apdu, apdu_len, &service_data, &service_choice,
&service_request, &service_request_len);
if (len == 0) {
/* service data unable to be decoded - simply drop */
break;
}
if (apdu_confirmed_dcc_disabled(service_choice)) {
/* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice
APDUs shall be processed and no messages shall be
initiated. */
break;
}
if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
(Confirmed_Function[service_choice])) {
Confirmed_Function[service_choice](
service_request, service_request_len, src, &service_data);
} else if (Unrecognized_Service_Handler) {
Unrecognized_Service_Handler(
service_request, service_request_len, src, &service_data);
}
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
@@ -783,24 +685,9 @@ void apdu_handler(
}
break;
case PDU_TYPE_SEGMENT_ACK:
#if !BACNET_SEGMENTATION_ENABLED
/* FIXME: what about a denial of service attack here?
we could check src to see if that matched the tsm */
tsm_free_invoke_id(invoke_id);
#else
if (apdu_len < 4) {
break;
}
server = apdu[0] & 0x01;
nak = apdu[0] & 0x02;
invoke_id = apdu[1];
sequence_number = apdu[2];
actual_window_size = apdu[3];
/* we care because we support segmented message sending */
tsm_segmentack_received(
invoke_id, sequence_number, actual_window_size, nak, server,
src);
#endif
break;
case PDU_TYPE_ERROR:
if (apdu_len < 3) {
@@ -827,12 +714,7 @@ void apdu_handler(
(BACNET_ERROR_CODE)error_code);
}
}
#if BACNET_SEGMENTATION_ENABLED
/*Release the data*/
tsm_free_invoke_id_segmentation(src, invoke_id);
#else
tsm_free_invoke_id(invoke_id);
#endif
break;
case PDU_TYPE_REJECT:
if (apdu_len < 3) {
@@ -843,12 +725,7 @@ void apdu_handler(
if (Reject_Function) {
Reject_Function(src, invoke_id, reason);
}
#if BACNET_SEGMENTATION_ENABLED
/*Release the data*/
tsm_free_invoke_id_segmentation(src, invoke_id);
#else
tsm_free_invoke_id(invoke_id);
#endif
break;
case PDU_TYPE_ABORT:
if (apdu_len < 3) {
@@ -857,156 +734,13 @@ void apdu_handler(
server = apdu[0] & 0x01;
invoke_id = apdu[1];
reason = apdu[2];
if (!server) {
/*AbortPDU_Received*/
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
#if BACNET_SEGMENTATION_ENABLED
else {
/*SendAbort*/
tsm_abort_pdu_send(invoke_id, src, reason, server);
}
/*Release the data*/
tsm_free_invoke_id_segmentation(src, invoke_id);
#else
tsm_free_invoke_id(invoke_id);
#endif
break;
#endif
default:
break;
}
}
#if BACNET_SEGMENTATION_ENABLED
/*Return the APDU segment timeout*/
uint16_t apdu_segment_timeout(void)
{
return Segment_Timeout_Milliseconds;
}
/*Set the APDU segment timeout*/
void apdu_segment_timeout_set(uint16_t milliseconds)
{
Segment_Timeout_Milliseconds = milliseconds;
}
/** Process the APDU header and invoke the appropriate service handler
* to manage the received request.
* Almost all requests and ACKs invoke this function.
* @ingroup MISCHNDLR
*
* @param apdu [in] The apdu portion of the response, to be sent
* @param fixed_pdu_header [in] The apdu header for the response
* @return apdu_length[out] The length of the apdu header
*/
int apdu_encode_fixed_header(
uint8_t *apdu, BACNET_APDU_FIXED_HEADER *fixed_pdu_header)
{
int apdu_len = 0;
switch (fixed_pdu_header->pdu_type) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
apdu[apdu_len++] = fixed_pdu_header->pdu_type
/* flag 'SA' if we accept many segments */
| (fixed_pdu_header->service_data.request_data
.segmented_response_accepted
? 0x02
: 0x00)
/* flag 'MOR' if we more segments are coming */
| (fixed_pdu_header->service_data.request_data.more_follows
? 0x04
: 0x00)
/* flag 'SEG' if we more segments are coming */
| (fixed_pdu_header->service_data.request_data.segmented_message
? 0x08
: 0x00);
apdu[apdu_len++] = encode_max_segs_max_apdu(
fixed_pdu_header->service_data.request_data.max_segs,
fixed_pdu_header->service_data.request_data.max_resp);
apdu[apdu_len++] =
fixed_pdu_header->service_data.request_data.invoke_id;
/* extra data for segmented messages sending */
if (fixed_pdu_header->service_data.request_data.segmented_message) {
/* packet sequence number */
apdu[apdu_len++] =
fixed_pdu_header->service_data.request_data.sequence_number;
/* window size proposal */
apdu[apdu_len++] = fixed_pdu_header->service_data.request_data
.proposed_window_number;
}
/* service choice */
apdu[apdu_len++] = fixed_pdu_header->service_choice;
break;
case PDU_TYPE_COMPLEX_ACK:
apdu[apdu_len++] = fixed_pdu_header->pdu_type
/* flag 'MOR' if we more segments are coming */
| (fixed_pdu_header->service_data.ack_data.more_follows ? 0x04
: 0x00)
/* flag 'SEG' if we more segments are coming */
| (fixed_pdu_header->service_data.ack_data.segmented_message
? 0x08
: 0x00);
apdu[apdu_len++] =
fixed_pdu_header->service_data.ack_data.invoke_id;
/* extra data for segmented messages sending */
if (fixed_pdu_header->service_data.ack_data.segmented_message) {
/* packet sequence number */
apdu[apdu_len++] =
fixed_pdu_header->service_data.ack_data.sequence_number;
/* window size proposal */
apdu[apdu_len++] = fixed_pdu_header->service_data.ack_data
.proposed_window_number;
}
/* service choice */
apdu[apdu_len++] = fixed_pdu_header->service_choice;
break;
default:
break;
}
return apdu_len;
}
/** Handler to assign the header fields to the response
* The response can be segmented/unsegmented
*
* @param fixed_pdu_header [in] The apdu header of the response, to be sent.
* @param pdu_type [in] The pdu_type of the response.
* @param invoke_id [in] The invoike_id of the response
* @param service[in] The service choice for which the response has to be
* processed
* @param max_apdu[in] The maximum apdu length
*/
void apdu_init_fixed_header(
BACNET_APDU_FIXED_HEADER *fixed_pdu_header,
uint8_t pdu_type,
uint8_t invoke_id,
uint8_t service,
int max_apdu)
{
fixed_pdu_header->pdu_type = pdu_type;
fixed_pdu_header->service_data.common_data.invoke_id = invoke_id;
fixed_pdu_header->service_data.common_data.more_follows = false;
fixed_pdu_header->service_data.common_data.proposed_window_number = 0;
fixed_pdu_header->service_data.common_data.sequence_number = 0;
fixed_pdu_header->service_data.common_data.segmented_message = false;
switch (pdu_type) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
fixed_pdu_header->service_data.request_data.max_segs =
BACNET_MAX_SEGMENTS_ACCEPTED;
/* allow to specify a lower APDU size : support arbitrary reduction
* of APDU packets between peers */
fixed_pdu_header->service_data.request_data.max_resp =
max_apdu < MAX_APDU ? max_apdu : MAX_APDU;
fixed_pdu_header->service_data.request_data
.segmented_response_accepted = BACNET_MAX_SEGMENTS_ACCEPTED > 1;
break;
case PDU_TYPE_COMPLEX_ACK:
default:
break;
}
fixed_pdu_header->service_choice = service;
}
#endif
-18
View File
@@ -162,24 +162,6 @@ void apdu_handler(
uint8_t *apdu, /* APDU data */
uint16_t pdu_len); /* for confirmed messages */
BACNET_STACK_EXPORT
uint16_t apdu_segment_timeout(void);
BACNET_STACK_EXPORT
void apdu_segment_timeout_set(uint16_t milliseconds);
BACNET_STACK_EXPORT
int apdu_encode_fixed_header(
uint8_t *apdu, BACNET_APDU_FIXED_HEADER *fixed_pdu_header);
BACNET_STACK_EXPORT
void apdu_init_fixed_header(
BACNET_APDU_FIXED_HEADER *fixed_pdu_header,
uint8_t pdu_type,
uint8_t invoke_id,
uint8_t service,
int max_apdu);
#ifdef __cplusplus
}
#endif /* __cplusplus */
+1 -4
View File
@@ -108,9 +108,7 @@ void handler_device_communication_control(
debug_print("DeviceCommunicationControl: "
"Missing Required Parameter. Sending Reject!\n");
goto DCC_FAILURE;
}
#if !BACNET_SEGMENTATION_ENABLED
else if (service_data->segmented_message) {
} 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);
@@ -118,7 +116,6 @@ void handler_device_communication_control(
"Sending Abort - segmented message.\n");
goto DCC_FAILURE;
}
#endif
/* decode the service request only */
len = dcc_decode_service_request(
service_request, service_len, &timeDuration, &state, &password);
+1 -4
View File
@@ -71,16 +71,13 @@ void handler_reinitialize_device(
debug_print("ReinitializeDevice: Missing Required Parameter. "
"Sending Reject!\n");
goto RD_ABORT;
}
#if !BACNET_SEGMENTATION_ENABLED
else if (service_data->segmented_message) {
} 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);
debug_print("ReinitializeDevice: Sending Abort - segmented message.\n");
goto RD_ABORT;
}
#endif
/* decode the service request only */
len = rd_decode_service_request(
service_request, service_len, &rd_data.state, &rd_data.password);
+3 -42
View File
@@ -30,12 +30,6 @@
#include "bacnet/basic/sys/debug.h"
#include "bacnet/datalink/datalink.h"
#if BACNET_SEGMENTATION_ENABLED
#define BACNET_RP_BUFFER_OVERFLOW ERROR_CODE_ABORT_BUFFER_OVERFLOW
#else
#define BACNET_RP_BUFFER_OVERFLOW ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED
#endif
/** @file h_rp.c Handles Read Property requests. */
/** Handler for a ReadProperty Service request.
@@ -44,7 +38,7 @@
* by a call to apdu_set_confirmed_handler().
* This handler builds a response packet, which is
* - an Abort if
* - the message is segmented and segmentation is not supported
* - the message is segmented
* - if decoding fails
* - if the response would be too large
* - the result from Device_Read_Property(), if it succeeds
@@ -65,7 +59,6 @@ void handler_read_property(
{
BACNET_READ_PROPERTY_DATA rpdata;
int len = 0;
int max_resp = 0;
int pdu_len = 0;
int apdu_len = -1;
int npdu_len = -1;
@@ -73,13 +66,9 @@ void handler_read_property(
bool error = true; /* assume that there is an error */
int bytes_sent = 0;
BACNET_ADDRESS my_address;
#if BACNET_SEGMENTATION_ENABLED
BACNET_APDU_FIXED_HEADER apdu_fixed_header;
int apdu_header_len = 3;
#endif
/* configure default error code as an abort since it is common */
rpdata.error_code = BACNET_RP_BUFFER_OVERFLOW;
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, service_data->priority);
@@ -93,12 +82,10 @@ void handler_read_property(
len = BACNET_STATUS_REJECT;
rpdata.error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
debug_print("RP: Missing Required Parameter. Sending Reject!\n");
#if !BACNET_SEGMENTATION_ENABLED
} else if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
len = BACNET_STATUS_ABORT;
debug_print("RP: Segmented message. Sending Abort!\n");
#endif
} else {
len = rp_decode_service_request(service_request, service_len, &rpdata);
if (len <= 0) {
@@ -129,13 +116,6 @@ void handler_read_property(
rpdata.object_instance = Network_Port_Index_To_Instance(0);
}
#endif
#if BACNET_SEGMENTATION_ENABLED
apdu_init_fixed_header(
&apdu_fixed_header, PDU_TYPE_COMPLEX_ACK,
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
service_data->max_resp);
#endif
apdu_len = rp_ack_encode_apdu_init(
&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id,
&rpdata);
@@ -154,25 +134,7 @@ void handler_read_property(
len = rp_ack_encode_apdu_object_property_end(
&Handler_Transmit_Buffer[npdu_len + apdu_len]);
apdu_len += len;
/* pick the smaller response packet: ours or theirs */
max_resp = min(service_data->max_resp, MAX_APDU);
if (apdu_len > max_resp) {
#if BACNET_SEGMENTATION_ENABLED
if (service_data->segmented_response_accepted) {
npdu_encode_npdu_data(
&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(
&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
tsm_set_complexack_transaction(
src, &npdu_data, &apdu_fixed_header, service_data,
&Handler_Transmit_Buffer
[npdu_len + apdu_header_len],
(apdu_len - apdu_header_len));
return;
}
#else
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 overridden the default set at start
@@ -181,7 +143,6 @@ void handler_read_property(
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
len = BACNET_STATUS_ABORT;
debug_print("RP: Message too large.\n");
#endif
} else {
debug_print("RP: Sending Ack!\n");
error = false;
+36 -95
View File
@@ -12,7 +12,6 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
@@ -34,17 +33,7 @@
#include "bacnet/basic/sys/debug.h"
#include "bacnet/datalink/datalink.h"
/* Smaller single threaded implementations prefer a
single buffer for encoding each property from the RPM request. */
#ifndef BACNET_RPM_PROPERTY_BUFFER_USE_CSTACK
static uint8_t RPM_Prop_Buffer[MAX_ASDU - MAX_NPDU] = { 0 };
#endif
#if BACNET_SEGMENTATION_ENABLED
#define BACNET_RPM_BUFFER_OVERFLOW ERROR_CODE_ABORT_BUFFER_OVERFLOW
#else
#define BACNET_RPM_BUFFER_OVERFLOW ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED
#endif
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
/**
* @brief Fetches the lists of properties (array of BACNET_PROPERTY_ID's) for
@@ -135,15 +124,12 @@ static int RPM_Encode_Property(
size_t copy_len = 0;
int apdu_len = 0;
BACNET_READ_PROPERTY_DATA rpdata;
#ifdef BACNET_RPM_PROPERTY_BUFFER_USE_CSTACK
uint8_t RPM_Prop_Buffer[MAX_ASDU - MAX_NPDU] = { 0 };
#endif
len = rpm_ack_encode_apdu_object_property(
&RPM_Prop_Buffer[0], rpmdata->object_property, rpmdata->array_index);
copy_len = memcopy(&apdu[0], &RPM_Prop_Buffer[0], offset, len, max_apdu);
&Temp_Buf[0], rpmdata->object_property, rpmdata->array_index);
copy_len = memcopy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
if (copy_len == 0) {
rpmdata->error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
return BACNET_STATUS_ABORT;
}
apdu_len += len;
@@ -153,8 +139,8 @@ static int RPM_Encode_Property(
rpdata.object_instance = rpmdata->object_instance;
rpdata.object_property = rpmdata->object_property;
rpdata.array_index = rpmdata->array_index;
rpdata.application_data = &RPM_Prop_Buffer[0];
rpdata.application_data_len = sizeof(RPM_Prop_Buffer);
rpdata.application_data = &Temp_Buf[0];
rpdata.application_data_len = sizeof(Temp_Buf);
if ((rpmdata->object_property == PROP_ALL) ||
(rpmdata->object_property == PROP_REQUIRED) ||
@@ -175,21 +161,21 @@ static int RPM_Encode_Property(
}
/* error was returned - encode that for the response */
len = rpm_ack_encode_apdu_object_property_error(
&RPM_Prop_Buffer[0], rpdata.error_class, rpdata.error_code);
copy_len = memcopy(
&apdu[0], &RPM_Prop_Buffer[0], offset + apdu_len, len, max_apdu);
&Temp_Buf[0], rpdata.error_class, rpdata.error_code);
copy_len =
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len, max_apdu);
if (copy_len == 0) {
rpmdata->error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
return BACNET_STATUS_ABORT;
}
} else if ((offset + apdu_len + 1 + len + 1) < max_apdu) {
/* enough room to fit the property value and tags */
len = rpm_ack_encode_apdu_object_property_value(
&apdu[offset + apdu_len], &RPM_Prop_Buffer[0], len);
&apdu[offset + apdu_len], &Temp_Buf[0], len);
} else {
/* not enough room - abort! */
rpmdata->error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
return BACNET_STATUS_ABORT;
}
apdu_len += len;
@@ -203,7 +189,7 @@ static int RPM_Encode_Property(
* by a call to apdu_set_confirmed_handler().
* This handler builds a response packet, which is
* - an Abort if
* - the message is segmented and SEGMENTATION_NONE
* - the message is segmented
* - if decoding fails
* - if the response would be too large
* - the result from each included read request, if it succeeds
@@ -234,14 +220,6 @@ void handler_read_property_multiple(
int apdu_len = 0;
int npdu_len = 0;
int error = 0;
int max_resp = 0;
#if BACNET_SEGMENTATION_ENABLED
BACNET_APDU_FIXED_HEADER apdu_fixed_header;
int apdu_header_len = 3;
#endif
#ifdef BACNET_RPM_PROPERTY_BUFFER_USE_CSTACK
uint8_t RPM_Prop_Buffer[MAX_ASDU - MAX_NPDU] = { 0 };
#endif
if (service_data) {
datalink_get_my_address(&my_address);
@@ -252,12 +230,10 @@ void handler_read_property_multiple(
rpmdata.error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
error = BACNET_STATUS_REJECT;
debug_print("RPM: Missing Required Parameter. Sending Reject!\n");
#if !BACNET_SEGMENTATION_ENABLED
} else if (service_data->segmented_message) {
rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
error = BACNET_STATUS_ABORT;
debug_print("RPM: Segmented message. Sending Abort!\r\n");
#endif
} else {
/* decode apdu request & encode apdu reply
encode complex ack, invoke id, service choice */
@@ -303,14 +279,14 @@ void handler_read_property_multiple(
}
#endif
/* Stick this object id into the reply - if it will fit */
len = rpm_ack_encode_apdu_object_begin(
&RPM_Prop_Buffer[0], &rpmdata);
len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], &rpmdata);
copy_len = memcopy(
&Handler_Transmit_Buffer[npdu_len], &RPM_Prop_Buffer[0],
apdu_len, len, sizeof(RPM_Prop_Buffer));
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0], apdu_len,
len, MAX_APDU);
if (copy_len == 0) {
debug_print("RPM: Response too big!\n");
rpmdata.error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata.error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
error = BACNET_STATUS_ABORT;
berror = true;
break;
@@ -345,9 +321,7 @@ void handler_read_property_multiple(
rpmdata.object_type, rpmdata.object_instance)) {
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[npdu_len],
(uint16_t)apdu_len,
sizeof(Handler_Transmit_Buffer) - npdu_len,
&rpmdata);
(uint16_t)apdu_len, MAX_APDU, &rpmdata);
if (len > 0) {
apdu_len += len;
} else {
@@ -362,18 +336,18 @@ void handler_read_property_multiple(
/* No array index options for this special property.
Encode error for this object property response */
len = rpm_ack_encode_apdu_object_property(
&RPM_Prop_Buffer[0], rpmdata.object_property,
&Temp_Buf[0], rpmdata.object_property,
rpmdata.array_index);
copy_len = memcopy(
&Handler_Transmit_Buffer[npdu_len],
&RPM_Prop_Buffer[0], apdu_len, len,
sizeof(RPM_Prop_Buffer));
&Temp_Buf[0], apdu_len, len, MAX_APDU);
if (copy_len == 0) {
debug_print(
"RPM: Too full to encode property!\n");
rpmdata.error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata.error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
error = BACNET_STATUS_ABORT;
/* The berror flag ensures that
both loops will be broken! */
@@ -383,17 +357,17 @@ void handler_read_property_multiple(
apdu_len += len;
len = rpm_ack_encode_apdu_object_property_error(
&RPM_Prop_Buffer[0], ERROR_CLASS_PROPERTY,
&Temp_Buf[0], ERROR_CLASS_PROPERTY,
ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY);
copy_len = memcopy(
&Handler_Transmit_Buffer[npdu_len],
&RPM_Prop_Buffer[0], apdu_len, len,
sizeof(RPM_Prop_Buffer));
&Temp_Buf[0], apdu_len, len, MAX_APDU);
if (copy_len == 0) {
debug_print("RPM: Too full to encode error!\n");
rpmdata.error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata.error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
error = BACNET_STATUS_ABORT;
/* The berror flag ensures that
both loops will be broken! */
@@ -422,10 +396,7 @@ void handler_read_property_multiple(
rpmdata.object_instance)) {
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[npdu_len],
(uint16_t)apdu_len,
sizeof(Handler_Transmit_Buffer) -
npdu_len,
&rpmdata);
(uint16_t)apdu_len, MAX_APDU, &rpmdata);
if (len > 0) {
apdu_len += len;
} else {
@@ -447,10 +418,7 @@ void handler_read_property_multiple(
special_object_property, index);
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[npdu_len],
(uint16_t)apdu_len,
sizeof(Handler_Transmit_Buffer) -
npdu_len,
&rpmdata);
(uint16_t)apdu_len, MAX_APDU, &rpmdata);
if (len > 0) {
apdu_len += len;
} else {
@@ -469,9 +437,7 @@ void handler_read_property_multiple(
/* handle an individual property */
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[npdu_len],
(uint16_t)apdu_len,
sizeof(Handler_Transmit_Buffer) - npdu_len,
&rpmdata);
(uint16_t)apdu_len, MAX_APDU, &rpmdata);
if (len > 0) {
apdu_len += len;
} else {
@@ -490,16 +456,15 @@ void handler_read_property_multiple(
/* Reached end of property list so cap the result list
*/
decode_len++;
len =
rpm_ack_encode_apdu_object_end(&RPM_Prop_Buffer[0]);
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len = memcopy(
&Handler_Transmit_Buffer[npdu_len],
&RPM_Prop_Buffer[0], apdu_len, len,
sizeof(Handler_Transmit_Buffer) - npdu_len);
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len, MAX_APDU);
if (copy_len == 0) {
debug_print(
"RPM: Too full to encode object end!\n");
rpmdata.error_code = BACNET_RPM_BUFFER_OVERFLOW;
rpmdata.error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
error = BACNET_STATUS_ABORT;
/* The berror flag ensures that
both loops will be broken! */
@@ -522,36 +487,12 @@ void handler_read_property_multiple(
}
/* If not having an error so far, check the remaining space. */
if (!berror) {
max_resp = min(service_data->max_resp, MAX_APDU);
if (apdu_len > max_resp) {
#if BACNET_SEGMENTATION_ENABLED
if (service_data->segmented_response_accepted) {
apdu_init_fixed_header(
&apdu_fixed_header, PDU_TYPE_COMPLEX_ACK,
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
service_data->max_resp);
npdu_encode_npdu_data(
&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(
&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
tsm_set_complexack_transaction(
src, &npdu_data, &apdu_fixed_header, service_data,
&Handler_Transmit_Buffer
[npdu_len + apdu_header_len],
(apdu_len - apdu_header_len));
return;
}
#else
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;
debug_print("RPM: Message too large. Sending Abort!\n");
#endif
}
}
}
+1 -4
View File
@@ -107,16 +107,13 @@ void handler_write_property(
REJECT_REASON_MISSING_REQUIRED_PARAMETER);
debug_print("WP: Missing Required Parameter. Sending Reject!\n");
bcontinue = false;
}
#if !BACNET_SEGMENTATION_ENABLED
else if (service_data->segmented_message) {
} 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);
debug_print("WP: Segmented message. Sending Abort!\n");
bcontinue = false;
}
#endif
if (bcontinue) {
/* decode the service request only */
len = wp_decode_service_request(service_request, service_len, &wp_data);
-2
View File
@@ -141,13 +141,11 @@ void handler_write_property_multiple(
len = BACNET_STATUS_REJECT;
debug_print("WPM: Missing Required Parameter. "
"Sending Reject!\n");
#if !BACNET_SEGMENTATION_ENABLED
} else if (service_data->segmented_message) {
wp_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
len = BACNET_STATUS_ABORT;
debug_print("WPM: Segmented message. "
"Sending Abort!\n");
#endif
} else {
/* first time - detect malformed request before writing any data */
len = write_property_multiple_decode(
+2 -2
View File
@@ -85,7 +85,7 @@ int iam_encode_pdu(
/* encode the APDU portion of the packet */
len = iam_encode_apdu(
&buffer[pdu_len], Device_Object_Instance_Number(), MAX_APDU,
Device_Segmentation_Supported(), Device_Vendor_Identifier());
SEGMENTATION_NONE, Device_Vendor_Identifier());
pdu_len += len;
return pdu_len;
@@ -158,7 +158,7 @@ int iam_unicast_encode_pdu(
/* encode the APDU portion of the packet */
apdu_len = iam_encode_apdu(
&buffer[npdu_len], Device_Object_Instance_Number(), MAX_APDU,
Device_Segmentation_Supported(), Device_Vendor_Identifier());
SEGMENTATION_NONE, Device_Vendor_Identifier());
pdu_len = npdu_len + apdu_len;
return pdu_len;
+63 -1243
View File
File diff suppressed because it is too large Load Diff
+11 -102
View File
@@ -15,9 +15,6 @@
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/npdu.h"
#if BACNET_SEGMENTATION_ENABLED
#include "bacnet/apdu.h"
#endif
/* note: TSM functionality is optional - only needed if we are
doing client requests */
@@ -27,7 +24,7 @@ extern "C" {
#endif /* __cplusplus */
/* FIXME: modify basic service handlers to use TSM rather than this buffer! */
BACNET_STACK_EXPORT extern uint8_t Handler_Transmit_Buffer[MAX_ASDU];
BACNET_STACK_EXPORT extern uint8_t Handler_Transmit_Buffer[MAX_PDU];
#ifdef __cplusplus
}
@@ -40,47 +37,31 @@ typedef enum {
TSM_STATE_IDLE,
TSM_STATE_AWAIT_CONFIRMATION,
TSM_STATE_AWAIT_RESPONSE,
TSM_STATE_SEGMENTED_REQUEST_SERVER,
TSM_STATE_SEGMENTED_CONFIRMATION,
TSM_STATE_SEGMENTED_RESPONSE_SERVER
TSM_STATE_SEGMENTED_REQUEST,
TSM_STATE_SEGMENTED_CONFIRMATION
} BACNET_TSM_STATE;
#if BACNET_SEGMENTATION_ENABLED
/* Indirect data state : */
typedef struct BACnet_TSM_Indirect_Data {
/* the address we received data from */
BACNET_ADDRESS PeerAddress;
/* the peer unique id */
uint8_t PeerInvokeID;
/* the unique id to use within our internal states.
zero means : "unused slot". */
uint8_t InternalInvokeID;
} BACNET_TSM_INDIRECT_DATA;
#endif
/* 5.4.1 Variables And Parameters */
/* The following variables are defined for each instance of */
/* Transaction State Machine: */
typedef struct BACnet_TSM_Data {
/* used to count APDU retries */
uint8_t RetryCount;
#if BACNET_SEGMENTATION_ENABLED
/* used to count segment retries */
uint8_t SegmentRetryCount;
/*uint8_t SegmentRetryCount; */
/* used to control APDU retries and the acceptance of server replies */
bool SentAllSegments;
/*bool SentAllSegments; */
/* stores the sequence number of the last segment received in order */
uint8_t LastSequenceNumber;
/*uint8_t LastSequenceNumber; */
/* stores the sequence number of the first segment of */
/* a sequence of segments that fill a window */
uint8_t InitialSequenceNumber;
/*uint8_t InitialSequenceNumber; */
/* stores the current window size */
uint8_t ActualWindowSize;
/*uint8_t ActualWindowSize; */
/* stores the window size proposed by the segment sender */
uint8_t ProposedWindowSize;
/*uint8_t ProposedWindowSize; */
/* used to perform timeout on PDU segments */
uint16_t SegmentTimer;
#endif
/*uint8_t SegmentTimer; */
/* used to perform timeout on Confirmed Requests */
/* in milliseconds */
uint16_t RequestTimer;
@@ -92,28 +73,9 @@ typedef struct BACnet_TSM_Data {
BACNET_ADDRESS dest;
/* the network layer info */
BACNET_NPDU_DATA npdu_data;
unsigned apdu_len;
#if BACNET_SEGMENTATION_ENABLED
/* APDU header information */
BACNET_APDU_FIXED_HEADER apdu_fixed_header;
/* calculated max APDU length / packet */
uint32_t apdu_maximum_length;
/* calculated max APDU length / total */
uint32_t maximum_transmittable_length;
/* Multiple APDU segments blob memorized here */
uint8_t *apdu_blob;
/* Size of allocated Multiple APDU segments blob */
uint32_t apdu_blob_allocated;
/* Size of data within the multiple APDU segments blob */
uint32_t apdu_blob_size;
/* Count received segments (prevents D.O.S.) */
uint32_t ReceivedSegmentsCount;
/* copy of the APDU, should we need to send it again */
uint8_t *apdu;
#else
/* copy of the APDU, should we need to send it again */
uint8_t apdu[MAX_PDU];
#endif
unsigned apdu_len;
} BACNET_TSM_DATA;
typedef void (*tsm_timeout_function)(uint8_t invoke_id);
@@ -161,59 +123,6 @@ bool tsm_invoke_id_free(uint8_t invokeID);
BACNET_STACK_EXPORT
bool tsm_invoke_id_failed(uint8_t invokeID);
#if BACNET_SEGMENTATION_ENABLED
/** Clear TSM Peer data */
BACNET_STACK_EXPORT
void tsm_clear_peer_id(uint8_t InternalInvokeID);
/* frees the invokeID and sets its state to IDLE */
BACNET_STACK_EXPORT
void tsm_free_invoke_id_check(
uint8_t invokeID, BACNET_ADDRESS *peer_address, bool cleanup);
/* Associates a Peer address and invoke ID with our TSM */
BACNET_STACK_EXPORT
uint8_t tsm_get_peer_id(BACNET_ADDRESS *src, uint8_t invokeID);
BACNET_STACK_EXPORT
bool tsm_set_segmented_confirmed_service_received(
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data,
uint8_t *internal_invoke_id,
uint8_t **pservice_request, /* IN/OUT */
uint16_t *pservice_request_len /* IN/OUT */
);
BACNET_STACK_EXPORT
int tsm_set_complexack_transaction(
BACNET_ADDRESS *dest,
BACNET_NPDU_DATA *npdu_data,
BACNET_APDU_FIXED_HEADER *apdu_fixed_header,
BACNET_CONFIRMED_SERVICE_DATA *confirmed_service_data,
uint8_t *pdu,
uint32_t pdu_len);
BACNET_STACK_EXPORT
void tsm_segmentack_received(
uint8_t invoke_id,
uint8_t sequence_number,
uint8_t actual_window_size,
bool nak,
bool server,
BACNET_ADDRESS *src);
BACNET_STACK_EXPORT
bool tsm_is_invalid_apdu_in_this_state(
BACNET_ADDRESS *src, BACNET_CONFIRMED_SERVICE_DATA *service_data);
BACNET_STACK_EXPORT
void tsm_abort_pdu_send(
uint8_t invoke_id, BACNET_ADDRESS *dest, uint8_t reason, bool server);
BACNET_STACK_EXPORT
void tsm_free_invoke_id_segmentation(BACNET_ADDRESS *src, uint8_t invoke_id);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
-5
View File
@@ -164,11 +164,6 @@
#endif
#endif
/* Enable or disable segmentation support in the library */
#ifndef BACNET_SEGMENTATION_ENABLED
#define BACNET_SEGMENTATION_ENABLED 0
#endif
/* for confirmed messages, this is the number of transactions */
/* that we hold in a queue waiting for timeout. */
/* Configure to zero if you don't want any confirmed messages */
-104
View File
@@ -1,104 +0,0 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2010 Julien Bennet
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include "segmentack.h"
/** Method to encode the segment ack .
*
* @param apdu[in] Pointer to the buffer for encoding.
* @param negativeack[in] Acknowedlegment for the segment.
* @param server[in] Set to True if the acknowledgment is from the server, else
* false.
* @param invoke_id[in] Invoke Id
* @param sequence_number[in] Sequence number of the segment to be acknowledged
* @param actual_window_size[in] Actual window size.
*
* @return Length of encoded data or zero on error.
*/
int segmentack_encode_apdu(
uint8_t *apdu,
bool negativeack,
bool server,
uint8_t invoke_id,
uint8_t sequence_number,
uint8_t actual_window_size)
{
int apdu_len = 0; /* total length of the apdu, return value */
uint8_t server_code = server ? 0x01 : 0x00;
uint8_t nak_code = negativeack ? 0x02 : 0x00;
if (apdu) {
apdu[0] = PDU_TYPE_SEGMENT_ACK | server_code | nak_code;
apdu[1] = invoke_id;
apdu[2] = sequence_number;
apdu[3] = actual_window_size;
apdu_len = 4;
}
return apdu_len;
}
/** Method to decode the segment ack service request
*
* @param apdu[in] The apdu portion of the ACK reply.
* @param apdu_len[in] The total length of the apdu.
* @param invoke_id[in] Invoke Id of the request.
* @param sequence_number[in] Sequence number of the segment received.
* @param actual_window_size[in] Actual window size.
*
* @return Length of decoded data or zero on error.
*/
int segmentack_decode_service_request(
uint8_t *apdu,
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *sequence_number,
uint8_t *actual_window_size)
{
int len = 0;
int apdu_header_size = 3;
if (apdu_len >= apdu_header_size) {
if (invoke_id) {
*invoke_id = apdu[0];
}
if (sequence_number) {
*sequence_number = apdu[1];
}
if (actual_window_size) {
*actual_window_size = apdu[2];
}
}
return len;
}
-68
View File
@@ -1,68 +0,0 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2010 Julien Bennet
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef BACNET_SEGMENT_ACK_H
#define BACNET_SEGMENT_ACK_H
#include <stdint.h>
#include <stdbool.h>
#include "bacenum.h"
#include "bacdcode.h"
#include "bacdef.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
int segmentack_encode_apdu(
uint8_t *apdu,
bool negativeack,
bool server,
uint8_t invoke_id,
uint8_t sequence_number,
uint8_t actual_window_size);
BACNET_STACK_EXPORT
int segmentack_decode_service_request(
uint8_t *apdu,
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *sequence_number,
uint8_t *actual_window_size);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SEGMENT_ACK_H */