Fixed BACnet/SC secure connect VMAC, UUID, and initialization sequence (#1142)

* Refactored the BACnet/SC datalink initialization order by moving certificate file checks and hub connection registration to occur after datalink initialization
* Replaced stdlib rand() with platform-specific cryptographically secure random functions (RtlGenRandom for Windows, getrandom for Linux, arc4random_buf for BSD) to generate UUID and VMAC addresses, preventing duplicates that broke connections
* Enabled conditional debug output in BACnet/SC components when BUILD=debug is specified
This commit is contained in:
Steve Karg
2025-11-14 15:41:17 -06:00
committed by GitHub
parent 74972bd025
commit 25d14c7c15
30 changed files with 672 additions and 339 deletions
+2 -5
View File
@@ -558,15 +558,12 @@ uint32_t bacfile_write(
BACNET_UNSIGNED_INTEGER bacfile_file_size(uint32_t object_instance)
{
const char *pathname = NULL;
long file_position = 0;
BACNET_UNSIGNED_INTEGER file_size = 0;
pathname = bacfile_pathname(object_instance);
if (pathname) {
file_position = bacfile_file_size_callback(pathname);
if (file_position >= 0) {
file_size = (BACNET_UNSIGNED_INTEGER)file_position;
}
file_size =
(BACNET_UNSIGNED_INTEGER)bacfile_file_size_callback(pathname);
}
return file_size;
+19
View File
@@ -19,6 +19,25 @@
#include "bacnet/datalink/bsc/bsc-conf.h"
#include "bacnet/datalink/bsc/bvlc-sc.h"
#ifndef SC_NETPORT_BVLC_MAX
#define SC_NETPORT_BVLC_MAX 1500
#endif
#ifndef SC_NETPORT_NPDU_MAX
#define SC_NETPORT_NPDU_MAX 1500
#endif
#ifndef SC_NETPORT_CONNECT_TIMEOUT
#define SC_NETPORT_CONNECT_TIMEOUT 5
#endif
#ifndef SC_NETPORT_HEARTBEAT_TIMEOUT
#define SC_NETPORT_HEARTBEAT_TIMEOUT 60
#endif
#ifndef SC_NETPORT_DISCONNECT_TIMEOUT
#define SC_NETPORT_DISCONNECT_TIMEOUT 150
#endif
#ifndef SC_NETPORT_RECONNECT_TIME
#define SC_NETPORT_RECONNECT_TIME 2
#endif
/* BACnet file instance numbers */
#ifndef BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE
#define BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE \
-19
View File
@@ -164,25 +164,6 @@
#endif
#endif
#ifndef SC_NETPORT_BVLC_MAX
#define SC_NETPORT_BVLC_MAX 1500
#endif
#ifndef SC_NETPORT_NPDU_MAX
#define SC_NETPORT_NPDU_MAX 1500
#endif
#ifndef SC_NETPORT_CONNECT_TIMEOUT
#define SC_NETPORT_CONNECT_TIMEOUT 5
#endif
#ifndef SC_NETPORT_HEARTBEAT_TIMEOUT
#define SC_NETPORT_HEARTBEAT_TIMEOUT 60
#endif
#ifndef SC_NETPORT_DISCONNECT_TIMEOUT
#define SC_NETPORT_DISCONNECT_TIMEOUT 150
#endif
#ifndef SC_NETPORT_RECONNECT_TIME
#define SC_NETPORT_RECONNECT_TIME 2
#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 */
+8 -10
View File
@@ -23,9 +23,8 @@
#include "bacnet/basic/object/bacfile.h"
#define PRINTF debug_printf_stderr
#define DEBUG_BSC_DATALINK 0
#undef DEBUG_PRINTF
#if DEBUG_BSC_DATALINK == 1
#if DEBUG_BSC_DATALINK
#define DEBUG_PRINTF debug_printf
#else
#define DEBUG_PRINTF debug_printf_disabled
@@ -94,7 +93,7 @@ static void bsc_node_event(
FIFO_Add(&bsc_fifo, pdu, pdu16_len);
bsc_event_signal(bsc_data_event);
}
#if DEBUG_ENABLED == 1
#if DEBUG_ENABLED
else {
PRINTF("pdu of size %d\n is dropped\n", pdu_len);
}
@@ -260,7 +259,6 @@ int bsc_send_pdu(
PRINTF("bsc_send_pdu() <<< ret = -1, incorrect dest mac address\n");
return len;
}
len = (int)bvlc_sc_encode_encapsulated_npdu(
buf, sizeof(buf), bsc_get_next_message_id(), NULL, &dest_vmac, pdu,
pdu_len);
@@ -270,6 +268,9 @@ int bsc_send_pdu(
if (ret != BSC_SC_SUCCESS) {
len = -1;
PRINTF(
"bsc_send_pdu(): bsc_node_send() returned %s\n",
bsc_return_code_to_string(ret));
}
}
@@ -313,8 +314,6 @@ uint16_t bsc_receive(
const char *err_desc = NULL;
static uint8_t buf[BVLC_SC_NPDU_SIZE_CONF];
DEBUG_PRINTF("bsc_receive() >>>\n");
bws_dispatch_lock();
if (bsc_datalink_state == BSC_DATALINK_STATE_STARTED) {
@@ -355,7 +354,7 @@ uint16_t bsc_receive(
pdu_len =
(uint16_t)dm.payload.encapsulated_npdu.npdu_len;
}
#if DEBUG_ENABLED == 1
#if DEBUG_ENABLED
else {
PRINTF(
"bsc_receive() pdu of size %d is dropped "
@@ -369,9 +368,8 @@ uint16_t bsc_receive(
DEBUG_PRINTF("bsc_receive() pdu_len = %d\n", pdu_len);
}
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_receive() <<< ret = %d\n", pdu_len);
return pdu_len;
}
@@ -608,7 +606,7 @@ static void bsc_update_failed_requests(void)
Network_Port_SC_Failed_Connection_Requests_Delete_All(instance);
for (i = 0; i < cnt; i++) {
if (r[i].Peer_Address.host[0] != 0) {
#if DEBUG_ENABLED == 1
#if DEBUG_ENABLED
DEBUG_PRINTF(
"failed request record %d, host %s, vmac %s, uuid "
"%s, error %d, details = %s\n",
+1 -1
View File
@@ -56,7 +56,7 @@ void bsc_cleanup(void);
*/
BACNET_STACK_EXPORT
bool bsc_cert_files_check(void);
bool bsc_cert_files_check(uint32_t netport_instance);
/**
* @brief Blocking thread-safe bsc_send_pdu() function
+14
View File
@@ -9,6 +9,8 @@
#define BACNET_DATALINK_BSC_EVENT_H
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack Datalink API */
#include "bacnet/datalink/bsc/bvlc-sc.h"
struct BSC_Event;
typedef struct BSC_Event BSC_EVENT;
@@ -98,4 +100,16 @@ bool bsc_event_timedwait(BSC_EVENT *ev, unsigned int ms_timeout);
void bsc_event_signal(BSC_EVENT *ev);
/**
* @brief Generate random BACnet Secure Connect VMAC address
* @param p - pointer to the VMAC address
*/
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p);
/**
* @brief Generate random BACnet Secure Connect UUID
* @param p - pointer to the UUID
*/
void bsc_generate_random_uuid(BACNET_SC_UUID *p);
#endif
+1 -3
View File
@@ -16,10 +16,8 @@
#include "bacnet/basic/object/sc_netport.h"
#include "bacnet/bactext.h"
#define DEBUG_BSC_HUB_CONNECTOR 0
#undef DEBUG_PRINTF
#if DEBUG_BSC_HUB_CONNECTOR == 1
#if DEBUG_BSC_HUB_CONNECTOR
#define DEBUG_PRINTF debug_printf
#else
#undef DEBUG_ENABLED
+70 -47
View File
@@ -14,15 +14,19 @@
#include "bacnet/bacdef.h"
#include "bacnet/npdu.h"
#include "bacnet/bacenum.h"
#define DEBUG_BSC_HUB_FUNCTION 0
#include "bacnet/bactext.h"
#undef DEBUG_PRINTF
#if DEBUG_BSC_HUB_FUNCTION == 1
#if DEBUG_BSC_HUB_FUNCTION
#define DEBUG_PRINTF debug_printf
#if (DEBUG_BSC_HUB_FUNCTION == 2)
#define DEBUG_PRINTF_VERBOSE debug_printf
#else
#define DEBUG_PRINTF_VERBOSE debug_printf_disabled
#endif
#else
#undef DEBUG_ENABLED
#define DEBUG_PRINTF debug_printf_disabled
#define DEBUG_PRINTF_VERBOSE debug_printf_disabled
#endif
static BSC_SOCKET *hub_function_find_connection_for_vmac(
@@ -152,14 +156,14 @@ hub_function_find_connection_for_uuid(BACNET_SC_UUID *uuid, void *user_arg)
bws_dispatch_lock();
f = (BSC_HUB_FUNCTION *)user_arg;
for (i = 0; i < sizeof(f->sock) / sizeof(BSC_SOCKET); i++) {
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"hubf = %p, sock %p, state = %d, uuid = %s\n", f, &f->sock[i],
f->sock[i].state, bsc_uuid_to_string(&f->sock[i].uuid));
if (f->sock[i].state != BSC_SOCK_STATE_IDLE &&
!memcmp(
&uuid->uuid[0], &f->sock[i].uuid.uuid[0], sizeof(uuid->uuid))) {
bws_dispatch_unlock();
DEBUG_PRINTF("found socket\n");
DEBUG_PRINTF_VERBOSE("found socket\n");
return &f->sock[i];
}
}
@@ -282,14 +286,17 @@ static void hub_function_socket_event(
BSC_HUB_FUNCTION *f;
size_t len;
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"hub_function_socket_event() >>> c = %p, ev = %d, reason = "
"%d, desc = %p, pdu = %p, pdu_len = %d, decoded_pdu = %p\n",
c, ev, reason, reason_desc, pdu, pdu_len, decoded_pdu);
"%s, desc = %p, pdu = %p, pdu_len = %d, decoded_pdu = %p\n",
c, ev, bactext_error_code_name(reason), reason_desc, pdu, pdu_len,
decoded_pdu);
bws_dispatch_lock();
f = (BSC_HUB_FUNCTION *)c->ctx->user_arg;
if (ev == BSC_SOCKET_EVENT_RECEIVED) {
DEBUG_PRINTF(
"BSC-HUB: socket event %s\n", bsc_socket_event_to_string(ev));
/* double check that received message does not contain */
/* originating virtual address and contains dest vaddr */
/* although such kind of check is already in bsc-socket.c */
@@ -299,52 +306,56 @@ static void hub_function_socket_event(
p_pdu = bsc_socket_get_global_buf();
len = pdu_len;
memcpy(p_pdu, pdu, len);
for (i = 0; i < sizeof(f->sock) / sizeof(BSC_SOCKET); i++) {
if (&f->sock[i] != c &&
f->sock[i].state == BSC_SOCK_STATE_CONNECTED) {
if ((&f->sock[i] != c) &&
(f->sock[i].state == BSC_SOCK_STATE_CONNECTED)) {
/* change origin address if presented or add origin
*/
/* address into pdu by extending of it's header */
len = (uint16_t)bvlc_sc_set_orig(
&p_pdu, len, &c->vmac);
ret = bsc_send(&f->sock[i], p_pdu, len);
(void)ret;
#if DEBUG_ENABLED == 1
if (ret != BSC_SC_SUCCESS) {
if (ret == BSC_SC_SUCCESS) {
DEBUG_PRINTF(
"BSC-HUB: "
"sent pdu of %d bytes\n",
len);
} else {
DEBUG_PRINTF(
"BSC-HUB: "
"sending of reconstructed pdu failed, "
"err = %d\n",
ret);
"err = %s\n",
bsc_return_code_to_string(ret));
}
#endif
}
}
} else {
DEBUG_PRINTF(
"BSC-HUB: received pdu with len = %d is dropped\n",
pdu_len);
}
#if DEBUG_ENABLED == 1
else {
DEBUG_PRINTF("pdu with len = %d is dropped\n", pdu_len);
}
#endif
} else {
dst = hub_function_find_connection_for_vmac(
decoded_pdu->hdr.dest, (void *)f);
if (!dst) {
DEBUG_PRINTF(
"can not find socket, hub dropped pdu of size "
"BSC-HUB: cannot find socket. Hub dropped pdu of size "
"%d for dest vmac %s\n",
pdu_len, bsc_vmac_to_string(decoded_pdu->hdr.dest));
} else {
bvlc_sc_remove_dest_set_orig(pdu, pdu_len, &c->vmac);
ret = bsc_send(dst, pdu, pdu_len);
(void)ret;
#if DEBUG_ENABLED == 1
if (ret != BSC_SC_SUCCESS) {
if (ret == BSC_SC_SUCCESS) {
DEBUG_PRINTF(
"sending of pdu of %d bytes failed, err = %d\n",
pdu_len, ret);
"BSC-HUB: "
"sent pdu of %d bytes\n",
pdu_len);
} else {
DEBUG_PRINTF(
"BSC-HUB: sending of pdu of %d bytes failed."
" err = %s\n",
pdu_len, bsc_return_code_to_string(ret));
}
#endif
}
}
}
@@ -355,11 +366,17 @@ static void hub_function_socket_event(
BSC_HUBF_EVENT_ERROR_DUPLICATED_VMAC,
(BSC_HUB_FUNCTION_HANDLE)f, f->user_arg);
}
if (reason != ERROR_CODE_SUCCESS) {
DEBUG_PRINTF(
"BSC-HUB: event=%s reason=%s \"%s\"\n",
bsc_socket_event_to_string(ev), bactext_error_code_name(reason),
reason_desc);
}
} else if (ev == BSC_SOCKET_EVENT_CONNECTED) {
hub_function_update_status(f, c, ev, reason, reason_desc);
}
bws_dispatch_unlock();
DEBUG_PRINTF("hub_function_socket_event() <<<\n");
DEBUG_PRINTF_VERBOSE("hub_function_socket_event() <<<\n");
}
/**
@@ -430,31 +447,30 @@ BSC_SC_RET bsc_hub_function_start(
BSC_SC_RET ret;
BSC_HUB_FUNCTION *f;
DEBUG_PRINTF("bsc_hub_function_start() >>>\n");
DEBUG_PRINTF_VERBOSE("bsc_hub_function_start() >>>\n");
if (!ca_cert_chain || !ca_cert_chain_size || !cert_chain ||
!cert_chain_size || !key || !key_size || !local_uuid || !local_vmac ||
!max_local_npdu_len || !max_local_bvlc_len || !connect_timeout_s ||
!heartbeat_timeout_s || !disconnect_timeout_s || !event_func || !h) {
DEBUG_PRINTF("bsc_hub_function_start() <<< ret = BSC_SC_BAD_PARAM\n");
return BSC_SC_BAD_PARAM;
ret = BSC_SC_BAD_PARAM;
DEBUG_PRINTF(
"BSC-HUB: start failed. err=%s\n", bsc_return_code_to_string(ret));
return ret;
}
*h = NULL;
bws_dispatch_lock();
f = hub_function_alloc();
if (!f) {
bws_dispatch_unlock();
ret = BSC_SC_NO_RESOURCES;
DEBUG_PRINTF(
"bsc_hub_function_start() <<< ret = BSC_SC_NO_RESOURCES\n");
return BSC_SC_NO_RESOURCES;
"BSC-HUB: alloc failed. err=%s\n", bsc_return_code_to_string(ret));
return ret;
}
f->user_arg = user_arg;
f->event_func = event_func;
bsc_init_ctx_cfg(
BSC_SOCKET_CTX_ACCEPTOR, &f->cfg, BSC_WEBSOCKET_HUB_PROTOCOL, port,
iface, ca_cert_chain, ca_cert_chain_size, cert_chain, cert_chain_size,
@@ -470,10 +486,13 @@ BSC_SC_RET bsc_hub_function_start(
f->state = BSC_HUB_FUNCTION_STATE_STARTING;
*h = (BSC_HUB_FUNCTION_HANDLE)f;
} else {
DEBUG_PRINTF(
"BSC-HUB: context initialization failed. err=%s\n",
bsc_return_code_to_string(ret));
hub_function_free(f);
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_hub_function_start() << ret = %d\n", ret);
DEBUG_PRINTF_VERBOSE("bsc_hub_function_start() << ret = %d\n", ret);
return ret;
}
@@ -484,7 +503,7 @@ BSC_SC_RET bsc_hub_function_start(
void bsc_hub_function_stop(BSC_HUB_FUNCTION_HANDLE h)
{
BSC_HUB_FUNCTION *f = (BSC_HUB_FUNCTION *)h;
DEBUG_PRINTF("bsc_hub_function_stop() >>> h = %p\n", h);
DEBUG_PRINTF_VERBOSE("bsc_hub_function_stop() >>> h = %p\n", h);
bws_dispatch_lock();
if (f && f->state != BSC_HUB_FUNCTION_STATE_IDLE &&
f->state != BSC_HUB_FUNCTION_STATE_STOPPING) {
@@ -492,7 +511,7 @@ void bsc_hub_function_stop(BSC_HUB_FUNCTION_HANDLE h)
bsc_deinit_ctx(&f->ctx);
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_hub_function_stop() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_hub_function_stop() <<<\n");
}
/**
@@ -505,13 +524,15 @@ bool bsc_hub_function_stopped(BSC_HUB_FUNCTION_HANDLE h)
BSC_HUB_FUNCTION *f = (BSC_HUB_FUNCTION *)h;
bool ret = false;
DEBUG_PRINTF("bsc_hub_function_stopped() >>> h = %p\n", h);
DEBUG_PRINTF_VERBOSE("bsc_hub_function_stopped() >>> h = %p\n", h);
bws_dispatch_lock();
if (f && f->state == BSC_HUB_FUNCTION_STATE_IDLE) {
ret = true;
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_hub_function_stopped() <<< ret = %d\n", ret);
DEBUG_PRINTF_VERBOSE(
"bsc_hub_function_stopped() <<< ret = %s\n", ret ? "true" : "false");
return ret;
}
@@ -525,12 +546,14 @@ bool bsc_hub_function_started(BSC_HUB_FUNCTION_HANDLE h)
BSC_HUB_FUNCTION *f = (BSC_HUB_FUNCTION *)h;
bool ret = false;
DEBUG_PRINTF("bsc_hub_function_started() >>> h = %p\n", h);
DEBUG_PRINTF_VERBOSE("bsc_hub_function_started() >>> h = %p\n", h);
bws_dispatch_lock();
if (f && f->state == BSC_HUB_FUNCTION_STATE_STARTED) {
ret = true;
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_hub_function_started() <<< ret = %d\n", ret);
DEBUG_PRINTF_VERBOSE(
"bsc_hub_function_started() <<< ret = %s\n", ret ? "true" : "false");
return ret;
}
+1 -3
View File
@@ -16,10 +16,8 @@
#include "bacnet/npdu.h"
#include "bacnet/bacenum.h"
#define DEBUG_BSC_NODE_SWITCH 0
#undef DEBUG_PRINTF
#if DEBUG_BSC_NODE_SWITCH == 1
#if DEBUG_BSC_NODE_SWITCH
#define DEBUG_PRINTF debug_printf
#else
#undef DEBUG_ENABLED
+1 -3
View File
@@ -19,10 +19,8 @@
#include "bacnet/npdu.h"
#include "bacnet/bacenum.h"
#define DEBUG_BSC_NODE 0
#undef DEBUG_PRINTF
#if DEBUG_BSC_NODE == 1
#if DEBUG_BSC_NODE
#define DEBUG_PRINTF debug_printf
#else
#undef DEBUG_ENABLED
+124 -118
View File
@@ -9,20 +9,25 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "bacnet/bactext.h"
#include "bacnet/datalink/bsc/bvlc-sc.h"
#include "bacnet/datalink/bsc/bsc-socket.h"
#include "bacnet/datalink/bsc/bsc-util.h"
#include "bacnet/basic/sys/mstimer.h"
#include "bacnet/basic/sys/debug.h"
#define DEBUG_BSC_SOCKET 0
#undef DEBUG_PRINTF
#if DEBUG_BSC_SOCKET == 1
#if DEBUG_BSC_SOCKET
#define DEBUG_PRINTF debug_printf
#if (DEBUG_BSC_SOCKET == 2)
#define DEBUG_PRINTF_VERBOSE debug_printf
#else
#define DEBUG_PRINTF_VERBOSE debug_printf_disabled
#endif
#else
#undef DEBUG_ENABLED
#define DEBUG_PRINTF debug_printf_disabled
#define DEBUG_PRINTF_VERBOSE debug_printf_disabled
#endif
static const char *s_error_no_origin =
@@ -135,7 +140,7 @@ void bsc_init_ctx_cfg(
unsigned int heartbeat_timeout_s,
unsigned int disconnect_timeout_s)
{
DEBUG_PRINTF("bsc_init_ctx_cfg() >>> cfg = %p\n");
DEBUG_PRINTF_VERBOSE("bsc_init_ctx_cfg() >>> cfg = %p\n");
if (cfg) {
cfg->proto = proto;
cfg->port = port;
@@ -155,7 +160,7 @@ void bsc_init_ctx_cfg(
cfg->heartbeat_timeout_s = heartbeat_timeout_s;
cfg->disconnect_timeout_s = disconnect_timeout_s;
}
DEBUG_PRINTF("bsc_init_ctx_cfg() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_init_ctx_cfg() <<<\n");
}
/**
@@ -200,11 +205,12 @@ static BSC_SOCKET *bsc_find_free_socket(BSC_SOCKET_CTX *ctx)
static void bsc_srv_process_error(BSC_SOCKET *c, BACNET_ERROR_CODE reason)
{
DEBUG_PRINTF(
"bsc_srv_process_error() >>> c = %p, reason = %d\n", c, reason);
"bsc_srv_process_error() >>> c = %p, reason = %s\n", c,
bactext_error_code_name(reason));
c->state = BSC_SOCK_STATE_ERROR;
c->reason = reason;
bws_srv_disconnect(c->ctx->sh, c->wh);
DEBUG_PRINTF("bsc_srv_process_error() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_srv_process_error() <<<\n");
}
/**
@@ -214,11 +220,13 @@ static void bsc_srv_process_error(BSC_SOCKET *c, BACNET_ERROR_CODE reason)
*/
static void bsc_cli_process_error(BSC_SOCKET *c, BACNET_ERROR_CODE reason)
{
DEBUG_PRINTF("bsc_cli_process_error) >>> c = %p, reason = %d\n", c, reason);
DEBUG_PRINTF(
"bsc_cli_process_error() >>> c = %p, reason = %s\n", c,
bactext_error_code_name(reason));
c->state = BSC_SOCK_STATE_ERROR;
c->reason = reason;
bws_cli_disconnect(c->wh);
DEBUG_PRINTF("bsc_cli_process_error) <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_cli_process_error() <<<\n");
}
/**
@@ -283,7 +291,8 @@ static bool bsc_prepare_error_extended(
#endif
message_id = bsc_get_next_message_id();
DEBUG_PRINTF(" message_id = %d\n", message_id);
DEBUG_PRINTF(
" message_id = %04x\n", message_id);
len = bvlc_sc_encode_result(
TX_BUF_PTR(c), TX_BUF_BYTES_AVAIL(c), message_id, origin, dest,
@@ -295,7 +304,7 @@ static bool bsc_prepare_error_extended(
"bsc_prepare_error_extended() <<< ret = true, pdu_len = %d\n", len);
return true;
}
DEBUG_PRINTF("bsc_prepare_error_extended() <<< ret = false\n");
DEBUG_PRINTF_VERBOSE("bsc_prepare_error_extended() <<< ret = false\n");
return false;
}
@@ -349,6 +358,9 @@ static bool bsc_prepare_protocol_error(
BACNET_ERROR_CODE error_code,
const char *utf8_details_string)
{
DEBUG_PRINTF(
"Socket %p Error: %s %s\n", c, bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
return bsc_prepare_protocol_error_extended(
c, dm, origin, dest, NULL, error_class, error_code,
utf8_details_string);
@@ -389,14 +401,14 @@ static void bsc_process_socket_disconnecting(
size_t buflen,
bool *need_disconnect)
{
DEBUG_PRINTF("bsc_process_socket_disconnecting() >>> c = %p\n", c);
DEBUG_PRINTF_VERBOSE("bsc_process_socket_disconnecting() >>> c = %p\n", c);
if (dm->hdr.bvlc_function == BVLC_SC_DISCONNECT_ACK) {
#if DEBUG_BSC_SOCKET == 1
if (dm->hdr.message_id != c->expected_disconnect_message_id) {
DEBUG_PRINTF(
"bsc_process_socket_disconnecting() got disconnect ack with "
"unexpected message id %d for socket %p\n",
"unexpected message id %04x for socket %p\n",
dm->hdr.message_id, c);
} else {
DEBUG_PRINTF(
@@ -429,7 +441,7 @@ static void bsc_process_socket_disconnecting(
c->ctx->funcs->socket_event(
c, BSC_SOCKET_EVENT_RECEIVED, 0, NULL, buf, buflen, dm);
}
DEBUG_PRINTF("bsc_process_socket_disconnecting() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_socket_disconnecting() <<<\n");
}
/**
@@ -452,29 +464,27 @@ static void bsc_process_socket_connected_state(
uint16_t message_id;
size_t len;
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_socket_connected_state() >>> c = %p, dm = %p, buf = %p, "
"buflen = %d\n",
c, dm, buf, buflen);
if (dm->hdr.bvlc_function == BVLC_SC_HEARTBEAT_ACK) {
#if DEBUG_ENABLED == 1
if (dm->hdr.message_id != c->expected_heartbeat_message_id) {
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_socket_connected_state() got heartbeat ack with "
"unexpected message id %d for socket %p\n",
"unexpected message id %04x for socket %p\n",
dm->hdr.message_id, c);
} else {
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_socket_connected_state() got heartbeat ack for "
"socket %p\n",
c);
}
#endif
} else if (dm->hdr.bvlc_function == BVLC_SC_HEARTBEAT_REQUEST) {
DEBUG_PRINTF(
"bsc_process_socket_connected_state() got heartbeat "
"request with message_id %d\n",
"request with message id %04x\n",
dm->hdr.message_id);
message_id = dm->hdr.message_id;
len = bvlc_sc_encode_heartbeat_ack(
@@ -482,20 +492,17 @@ static void bsc_process_socket_connected_state(
if (len) {
TX_BUF_UPDATE(c, len);
*need_send = true;
}
#if DEBUG_BSC_SOCKET == 1
else {
} else {
DEBUG_PRINTF(
"bsc_process_socket_connected_state() no resources to "
"answer on heartbeat request "
"socket %p\n",
c);
}
#endif
} else if (dm->hdr.bvlc_function == BVLC_SC_DISCONNECT_REQUEST) {
DEBUG_PRINTF(
"bsc_process_socket_connected_state() got disconnect "
"request with message_id %d\n",
"request with message id %04x\n",
dm->hdr.message_id);
message_id = dm->hdr.message_id;
len = bvlc_sc_encode_disconnect_ack(
@@ -518,7 +525,7 @@ static void bsc_process_socket_connected_state(
/* and hope that remote peer clears itself up. */
DEBUG_PRINTF(
"bsc_process_socket_connected_state() got unexpected "
"disconnect ack with message_id %d\n",
"disconnect ack with message id %04x\n",
dm->hdr.message_id);
c->state = BSC_SOCK_STATE_DISCONNECTING;
*need_disconnect = true;
@@ -545,7 +552,7 @@ static void bsc_process_socket_connected_state(
c, BSC_SOCKET_EVENT_RECEIVED, 0, NULL, buf, buflen, dm);
}
DEBUG_PRINTF("bsc_process_socket_connected_state() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_socket_connected_state() <<<\n");
}
/**
@@ -572,7 +579,7 @@ static void bsc_process_socket_state(
bool valid = true;
size_t len;
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_socket_state() >>> ctx = %p, c = %p, state = %d, "
"rx_buf = %p, rx_buf_size = %d\n",
c->ctx, c, c->state, rx_buf, rx_buf_size);
@@ -592,18 +599,17 @@ static void bsc_process_socket_state(
*need_send = bsc_prepare_protocol_error(
c, dm, dm->hdr.origin, dm->hdr.dest, error_class,
error_code, err_desc);
}
#if DEBUG_BSC_SOCKET == 1
else {
} else {
DEBUG_PRINTF(
"bsc_process_socket_state() decoding failed, message "
"is silently dropped cause it's length < 4 bytes\n");
}
#endif
} else {
DEBUG_PRINTF(
"c->dm.hdr.bvlc_function == %d, message_id = %d\n",
dm->hdr.bvlc_function, dm->hdr.message_id);
DEBUG_PRINTF_VERBOSE(
"bsc_process_socket_state() "
"bvlc_function %s, message id %04x\n",
bsc_bvlc_message_type_to_string(dm->hdr.bvlc_function),
dm->hdr.message_id);
if (dm->hdr.bvlc_function == BVLC_SC_ENCAPSULATED_NPDU ||
dm->hdr.bvlc_function == BVLC_SC_ADVERTISIMENT ||
dm->hdr.bvlc_function == BVLC_SC_ADDRESS_RESOLUTION_ACK ||
@@ -612,14 +618,12 @@ static void bsc_process_socket_state(
dm->hdr.bvlc_function == BVLC_SC_RESULT) {
if (c->ctx->cfg->type == BSC_SOCKET_CTX_INITIATOR &&
c->ctx->cfg->proto == BSC_WEBSOCKET_HUB_PROTOCOL) {
/* this is a case when socket is a hub connector receiving
*/
/* from hub */
/* this is a case when socket is a hub connector
receiving from hub */
if (dm->hdr.origin == NULL &&
dm->hdr.bvlc_function != BVLC_SC_RESULT) {
error_class = ERROR_CLASS_COMMUNICATION;
error_code = ERROR_CODE_HEADER_ENCODING_ERROR;
*need_send = bsc_prepare_protocol_error(
c, dm, NULL, &c->vmac, error_class, error_code,
s_error_no_origin);
@@ -637,8 +641,8 @@ static void bsc_process_socket_state(
} else if (
c->ctx->cfg->type == BSC_SOCKET_CTX_ACCEPTOR &&
c->ctx->cfg->proto == BSC_WEBSOCKET_HUB_PROTOCOL) {
/* this is a case when socket is hub function receiving */
/* from node */
/* this is a case when socket is hub function
receiving from node */
if (dm->hdr.dest == NULL) {
error_class = ERROR_CLASS_COMMUNICATION;
error_code = ERROR_CODE_HEADER_ENCODING_ERROR;
@@ -656,7 +660,6 @@ static void bsc_process_socket_state(
}
}
}
/* every valid message restarts heartbeat timeout */
/* and only valid messages are processed */
if (valid) {
@@ -680,38 +683,39 @@ static void bsc_process_socket_state(
}
expired = mstimer_expired(&c->t);
DEBUG_PRINTF("bsc_process_socket_state() expired = %d\n", expired);
DEBUG_PRINTF_VERBOSE(
"BSC-Socket: connection mstimer_expired() = %d\n", expired);
if (c->state == BSC_SOCK_STATE_AWAITING_ACCEPT && expired) {
c->state = BSC_SOCK_STATE_ERROR;
c->reason = ERROR_CODE_TIMEOUT;
*need_disconnect = true;
DEBUG_PRINTF("BSC-Socket: connection timeout AWAITING_ACCEPT.\n");
} else if (c->state == BSC_SOCK_STATE_AWAITING_REQUEST && expired) {
c->state = BSC_SOCK_STATE_ERROR;
c->reason = ERROR_CODE_TIMEOUT;
*need_disconnect = true;
DEBUG_PRINTF("BSC-Socket: connection timeout AWAITING_REQUEST.\n");
} else if (c->state == BSC_SOCK_STATE_DISCONNECTING && expired) {
c->state = BSC_SOCK_STATE_ERROR;
c->reason = ERROR_CODE_TIMEOUT;
*need_disconnect = true;
DEBUG_PRINTF("BSC-Socket: connection timeout DISCONNECTING.\n");
} else if (c->state == BSC_SOCK_STATE_CONNECTED) {
expired = mstimer_expired(&c->heartbeat);
DEBUG_PRINTF(
"bsc_process_socket_state() heartbeat timeout expired = %d\n",
expired);
DEBUG_PRINTF_VERBOSE(
"BSC-Socket: heartbeat mstimer_expired() = %d\n", expired);
if (expired) {
DEBUG_PRINTF(
"bsc_process_socket_state() heartbeat timeout elapsed "
DEBUG_PRINTF_VERBOSE(
"BSC-Socket: heartbeat timeout elapsed "
"for socket %p\n",
c);
if (c->ctx->cfg->type == BSC_SOCKET_CTX_INITIATOR) {
DEBUG_PRINTF(
"bsc_process_socket_state() going to send heartbeat "
"request on connection %p\n",
"BSC-Socket: sending heartbeat request on connection %p\n",
c);
c->expected_heartbeat_message_id = bsc_get_next_message_id();
DEBUG_PRINTF(
"bsc_process_socket_state() heartbeat message_id %04x\n",
DEBUG_PRINTF_VERBOSE(
"BSC-Socket: heartbeat message id %04x\n",
c->expected_heartbeat_message_id);
len = bvlc_sc_encode_heartbeat_request(
@@ -725,14 +729,14 @@ static void bsc_process_socket_state(
*need_send = true;
} else {
DEBUG_PRINTF(
"bsc_process_socket_state() sending of "
"BSC-Socket: sending of "
"heartbeat request failed on connection %p\n",
c);
}
} else if (c->ctx->cfg->type == BSC_SOCKET_CTX_ACCEPTOR) {
DEBUG_PRINTF(
"bsc_process_socket_state() zombie socket %p is "
"disconnecting...\n",
"BSC-Socket: zombie socket %p is "
"disconnecting by timeout.\n",
c);
c->state = BSC_SOCK_STATE_ERROR;
c->reason = ERROR_CODE_TIMEOUT;
@@ -740,7 +744,7 @@ static void bsc_process_socket_state(
}
}
}
DEBUG_PRINTF("bsc_process_socket_state() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_socket_state() <<<\n");
}
/**
@@ -785,24 +789,24 @@ static void bsc_runloop_socket(
*/
void bsc_socket_maintenance_timer(uint16_t seconds)
{
int i, j;
(void)seconds;
DEBUG_PRINTF("bsc_socket_maintenance_timer() >>>\n");
int i, j, count = 0;
DEBUG_PRINTF_VERBOSE(
"bsc_socket_maintenance_timer(%us) >>>\n", (unsigned)seconds);
bws_dispatch_lock();
for (i = 0; i < BSC_SOCKET_CTX_NUM; i++) {
if (bsc_socket_ctx[i] != NULL) {
if (bsc_socket_ctx[i]->state == BSC_CTX_STATE_INITIALIZED) {
for (j = 0; j < bsc_socket_ctx[i]->sock_num; j++) {
count++;
bsc_runloop_socket(
&bsc_socket_ctx[i]->sock[j], NULL, NULL, 0);
}
}
}
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_socket_maintenance_timer() <<<\n");
DEBUG_PRINTF_VERBOSE(
"bsc_socket_maintenance_timer() <<< %d sockets processed\n", count);
}
/**
@@ -824,7 +828,7 @@ static void bsc_process_srv_awaiting_request(
uint16_t uclass;
const char *err_desc = NULL;
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_srv_awaiting_request() >>> c = %p, dm = %p, buf = %p, "
"bufsize = %d\n",
c, dm, buf, bufsize);
@@ -858,8 +862,8 @@ static void bsc_process_srv_awaiting_request(
bsc_vmac_to_string(dm->payload.connect_request.vmac));
DEBUG_PRINTF(
"bsc_process_srv_awaiting_request() existing = %p, "
"existing->state = %d, c = %p\n",
existing, existing->state, c);
"existing->state = %s, c = %p\n",
existing, bsc_socket_state_to_string(existing->state), c);
bsc_copy_vmac(&c->vmac, dm->payload.connect_request.vmac);
bsc_copy_uuid(&c->uuid, dm->payload.connect_request.uuid);
c->max_npdu_len = dm->payload.connect_request.max_npdu_len;
@@ -879,7 +883,9 @@ static void bsc_process_srv_awaiting_request(
ERROR_CODE_ABORT_OUT_OF_RESOURCES, NULL);
}
bsc_srv_process_error(c, ERROR_CODE_ABORT_OUT_OF_RESOURCES);
DEBUG_PRINTF("bsc_process_srv_awaiting_request() <<<\n");
DEBUG_PRINTF(
"bsc_process_srv_awaiting_request() connect_accept "
"encoding failed, err = ABORT_OUT_OF_RESOURCES\n");
return;
} else {
TX_BUF_UPDATE(c, len);
@@ -901,25 +907,28 @@ static void bsc_process_srv_awaiting_request(
TX_BUF_UPDATE(existing, len);
DEBUG_PRINTF(
"bsc_process_srv_awaiting_request() request to "
"send disconnect request to socket %d(%p)\n",
existing->wh, existing);
"send disconnect request with message id %04x "
" to existing socket %d(%p)\n",
existing->expected_disconnect_message_id, existing->wh,
existing);
bws_srv_send(existing->ctx->sh, existing->wh);
} else {
DEBUG_PRINTF(
"bsc_process_srv_awaiting_request() sending of disconnect "
"request failed, err = BSC_SC_NO_RESOURCES\n");
"bsc_process_srv_awaiting_request() sending of "
"disconnect request to existing socket (%p) failed. "
"err = BSC_SC_NO_RESOURCES\n",
c);
}
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_srv_awaiting_request() set socket %p to "
"connected state\n",
c);
mstimer_set(
&c->heartbeat, 2 * c->ctx->cfg->heartbeat_timeout_s * 1000);
c->state = BSC_SOCK_STATE_CONNECTED;
c->ctx->funcs->socket_event(
c, BSC_SOCKET_EVENT_CONNECTED, 0, NULL, NULL, 0, NULL);
DEBUG_PRINTF("bsc_process_srv_awaiting_request() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_srv_awaiting_request() <<<\n");
return;
}
@@ -959,7 +968,7 @@ static void bsc_process_srv_awaiting_request(
"message failed, err = BSC_SC_NO_RESOURCES\n");
bsc_srv_process_error(c, ERROR_CODE_NODE_DUPLICATE_VMAC);
}
DEBUG_PRINTF("bsc_process_srv_awaiting_request() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_srv_awaiting_request() <<<\n");
return;
}
@@ -1011,7 +1020,7 @@ static void bsc_process_srv_awaiting_request(
"message failed, err = BSC_SC_NO_RESOURCES\n");
bsc_srv_process_error(c, ERROR_CODE_NODE_DUPLICATE_VMAC);
}
DEBUG_PRINTF("bsc_process_srv_awaiting_request() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_srv_awaiting_request() <<<\n");
return;
}
DEBUG_PRINTF(
@@ -1058,7 +1067,7 @@ static void bsc_process_srv_awaiting_request(
dm->hdr.bvlc_function);
}
#endif
DEBUG_PRINTF("bsc_process_srv_awaiting_request() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_srv_awaiting_request() <<<\n");
}
/**
@@ -1092,7 +1101,7 @@ static void bsc_dispatch_srv_func(
(void)sh;
bws_dispatch_lock();
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_dispatch_srv_func() >>> sh = %p, h = %d, ev = %d, "
"reason = %d, desc = %p, buf "
"= %p, bufsize = %ld, ctx = %p\n",
@@ -1131,7 +1140,7 @@ static void bsc_dispatch_srv_func(
bws_dispatch_unlock();
return;
}
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_dispatch_srv_func() socket %p, state = %d\n", c, c->state);
}
@@ -1163,25 +1172,22 @@ static void bsc_dispatch_srv_func(
mstimer_set(&c->t, c->ctx->cfg->connect_timeout_s * 1000);
}
} else if (ev == BSC_WEBSOCKET_RECEIVED) {
DEBUG_PRINTF("bsc_dispatch_srv_func() processing "
"BSC_WEBSOCKET_RECEIVED event\n");
DEBUG_PRINTF(
"bsc_dispatch_srv_func() socket %p, state = %d\n", c, c->state);
"bsc_dispatch_srv_func() BSC_WEBSOCKET_RECEIVED event "
"socket %p, state = %s\n",
c, bsc_socket_state_to_string(c->state));
if (c->state == BSC_SOCK_STATE_AWAITING_REQUEST) {
bsc_process_srv_awaiting_request(c, &bsc_dm, buf, bufsize);
} else if (
c->state == BSC_SOCK_STATE_DISCONNECTING ||
c->state == BSC_SOCK_STATE_CONNECTED) {
bsc_runloop_socket(c, &bsc_dm, buf, bufsize);
}
#if DEBUG_BSC_SOCKET == 1
else {
} else {
DEBUG_PRINTF(
"bsc_dispatch_srv_func() data was dropped for socket "
"%p, state %d, data_size %d\n",
c, c->state, bufsize);
"%p, state %s, data_size %d\n",
c, bsc_socket_state_to_string(c->state), bufsize);
}
#endif
} else if (ev == BSC_WEBSOCKET_SENDABLE) {
p = c->tx_buf;
@@ -1191,9 +1197,9 @@ static void bsc_dispatch_srv_func(
c->ctx->sh, c->wh, &p[sizeof(len) + BSC_CONF_TX_PRE], len);
if (wret != BSC_WEBSOCKET_SUCCESS) {
DEBUG_PRINTF(
"bsc_dispatch_srv_func() send data failed, start "
"disconnect operation on socket %p\n",
c);
"bsc_dispatch_srv_func() send data failed. "
"Error=%s, start disconnect operation on socket %p\n",
bsc_websocket_return_to_string(wret), c);
bsc_srv_process_error(
c,
c->state != BSC_SOCK_STATE_ERROR_FLUSH_TX
@@ -1215,7 +1221,7 @@ static void bsc_dispatch_srv_func(
}
bsc_socket_maintenance_timer(0);
DEBUG_PRINTF("bsc_dispatch_srv_func() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_dispatch_srv_func() <<<\n");
bws_dispatch_unlock();
}
@@ -1233,7 +1239,7 @@ static void bsc_process_cli_awaiting_accept(
uint16_t error_code;
const char *err_desc = NULL;
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_process_cli_awaiting_accept() >>> c = %p, dm = %p, buf = "
"%p, bufsize = %d\n",
c, dm, buf, bufsize);
@@ -1329,7 +1335,7 @@ static void bsc_process_cli_awaiting_accept(
dm->hdr.bvlc_function);
}
#endif
DEBUG_PRINTF("bsc_process_cli_awaiting_accept() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_process_cli_awaiting_accept() <<<\n");
}
/**
@@ -1363,14 +1369,12 @@ static void bsc_dispatch_cli_func(
bws_dispatch_lock();
DEBUG_PRINTF(
DEBUG_PRINTF_VERBOSE(
"bsc_dispatch_cli_func() >>> h = %d, ev = %d, reason = %d, "
"reason_desc = %p, buf = %p, "
"bufsize = %ld, ctx = %p\n",
h, ev, ws_reason, ws_reason_desc, buf, bufsize, ctx);
c = bsc_find_conn_by_websocket(ctx, h);
if (!c) {
DEBUG_PRINTF(
"bsc_dispatch_cli_func() <<< warning, can not find "
@@ -1379,11 +1383,13 @@ static void bsc_dispatch_cli_func(
bws_dispatch_unlock();
return;
}
DEBUG_PRINTF("bsc_dispatch_cli_func() ev = %d, state = %d\n", ev, c->state);
DEBUG_PRINTF_VERBOSE(
"bsc_dispatch_cli_func() ev = %d, state = %d\n", ev, c->state);
if (ev == BSC_WEBSOCKET_DISCONNECTED) {
DEBUG_PRINTF("bsc_dispatch_cli_func() ctx->state = %d\n", ctx->state);
DEBUG_PRINTF(
"bsc_dispatch_cli_func() websocket %s ctx->state = %s\n",
bsc_websocket_event_to_string(ev),
bsc_context_state_to_string(ctx->state));
if (ctx->state == BSC_CTX_STATE_DEINITIALIZING) {
bsc_set_socket_idle(c);
bsc_clear_vmac_and_uuid(c);
@@ -1412,6 +1418,10 @@ static void bsc_dispatch_cli_func(
bsc_clear_vmac_and_uuid(c);
}
} else if (ev == BSC_WEBSOCKET_CONNECTED) {
DEBUG_PRINTF(
"bsc_dispatch_cli_func() websocket %s c->state = %s\n",
bsc_websocket_event_to_string(ev),
bsc_socket_state_to_string(c->state));
if (c->state == BSC_SOCK_STATE_AWAITING_WEBSOCKET) {
DEBUG_PRINTF(
"bsc_dispatch_cli_func() conn %p, websocket %d, state "
@@ -1494,7 +1504,7 @@ static void bsc_dispatch_cli_func(
}
bsc_socket_maintenance_timer(0);
DEBUG_PRINTF("bsc_dispatch_cli_func() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_dispatch_cli_func() <<<\n");
bws_dispatch_unlock();
}
@@ -1579,7 +1589,7 @@ BSC_SC_RET bsc_init_ctx(
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_init_ctx() <<< ret = %d \n", sc_ret);
DEBUG_PRINTF_VERBOSE("bsc_init_ctx() <<< ret = %d \n", sc_ret);
return sc_ret;
}
@@ -1627,7 +1637,7 @@ void bsc_deinit_ctx(BSC_SOCKET_CTX *ctx)
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_deinit_ctx() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_deinit_ctx() <<<\n");
}
/**
@@ -1642,8 +1652,8 @@ BSC_SC_RET bsc_connect(BSC_SOCKET_CTX *ctx, BSC_SOCKET *c, char *url)
BSC_SC_RET ret = BSC_SC_INVALID_OPERATION;
BSC_WEBSOCKET_RET wret;
DEBUG_PRINTF("bsc_connect() >>> ctx = %p, c = %p, url = %s\n", ctx, c, url);
DEBUG_PRINTF_VERBOSE(
"bsc_connect() >>> ctx = %p, c = %p, url = %s\n", ctx, c, url);
if (!ctx || !c || !url) {
ret = BSC_SC_BAD_PARAM;
} else {
@@ -1654,25 +1664,25 @@ BSC_SC_RET bsc_connect(BSC_SOCKET_CTX *ctx, BSC_SOCKET *c, char *url)
c->ctx = ctx;
c->state = BSC_SOCK_STATE_AWAITING_WEBSOCKET;
c->tx_buf_size = 0;
wret = bws_cli_connect(
ctx->cfg->proto, url, ctx->cfg->ca_cert_chain,
ctx->cfg->ca_cert_chain_size, ctx->cfg->cert_chain,
ctx->cfg->cert_chain_size, ctx->cfg->priv_key,
ctx->cfg->priv_key_size, ctx->cfg->connect_timeout_s,
bsc_dispatch_cli_func, ctx, &c->wh);
ret = bsc_map_websocket_retcode(wret);
if (wret != BSC_WEBSOCKET_SUCCESS) {
DEBUG_PRINTF(
"bsc_connect() failed. %s\n",
bsc_websocket_return_to_string(wret));
bsc_set_socket_idle(c);
bsc_clear_vmac_and_uuid(c);
}
}
bws_dispatch_unlock();
}
DEBUG_PRINTF("bsc_connect() <<< ret = %d\n", ret);
DEBUG_PRINTF_VERBOSE("bsc_connect() <<< ret = %d\n", ret);
return ret;
}
@@ -1685,9 +1695,7 @@ void bsc_disconnect(BSC_SOCKET *c)
size_t len;
DEBUG_PRINTF("bsc_disconnect() >>> c = %p\n", c);
bws_dispatch_lock();
if (c->ctx->state == BSC_CTX_STATE_INITIALIZED) {
if (c->state == BSC_SOCK_STATE_CONNECTED) {
c->expected_disconnect_message_id = bsc_get_next_message_id();
@@ -1723,10 +1731,8 @@ void bsc_disconnect(BSC_SOCKET *c)
}
}
}
bws_dispatch_unlock();
DEBUG_PRINTF("bsc_disconnect() <<<\n");
DEBUG_PRINTF_VERBOSE("bsc_disconnect() <<<\n");
}
/**
@@ -1768,7 +1774,7 @@ BSC_SC_RET bsc_send(BSC_SOCKET *c, uint8_t *pdu, size_t pdu_len)
bws_dispatch_unlock();
}
DEBUG_PRINTF("bsc_send() <<< ret = %d\n", ret);
DEBUG_PRINTF_VERBOSE("bsc_send() <<< ret = %d\n", ret);
return ret;
}
@@ -1790,7 +1796,7 @@ uint16_t bsc_get_next_message_id(void)
message_id++;
}
ret = message_id;
DEBUG_PRINTF("next message id = %u(%04x)\n", ret, ret);
DEBUG_PRINTF_VERBOSE("next message id = %u(%04x)\n", ret, ret);
bws_dispatch_unlock();
return ret;
}
+205 -49
View File
@@ -5,12 +5,12 @@
* @date Jule 2022
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*/
#include "bacnet/datalink/bsc/bsc-util.h"
#include <stdlib.h>
#include "bacnet/basic/object/bacfile.h"
#include "bacnet/basic/object/netport.h"
#include "bacnet/basic/object/sc_netport.h"
#include "bacnet/basic/sys/debug.h"
#include <stdlib.h>
#include "bacnet/datalink/bsc/bsc-util.h"
#define PRINTF debug_printf_stdout
#define PRINTF_ERR debug_printf_stderr
@@ -88,43 +88,6 @@ char *bsc_uuid_to_string(BACNET_SC_UUID *uuid)
return buf;
}
/**
* @brief Generate random BACnet Secure Connect VMAC address
* @param p - pointer to the VMAC address
*/
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p)
{
int i;
for (i = 0; i < BVLC_SC_VMAC_SIZE; i++) {
p->address[i] = rand() % 256;
if (i == 0) {
/* According H.7.3 EUI-48 and Random-48 VMAC Address:
The Random-48 VMAC is a 6-octet VMAC address in which the least
significant 4 bits (Bit 3 to Bit 0) in the first octet shall be
B'0010' (X'2'), and all other 44 bits are randomly selected to be
0 or 1. */
p->address[i] = (p->address[i] & 0xF0) | 0x02;
}
}
debug_printf_hex(
0, p->address, BVLC_SC_VMAC_SIZE, "bsc_generate_random_vmac");
}
/**
* @brief Generate random BACnet Secure Connect UUID
* @param p - pointer to the UUID
*/
void bsc_generate_random_uuid(BACNET_SC_UUID *p)
{
int i;
for (i = 0; i < BVLC_SC_UUID_SIZE; i++) {
p->uuid[i] = rand() % 256;
}
debug_printf_hex(0, p->uuid, BVLC_SC_UUID_SIZE, "bsc_generate_random_uuid");
}
/*
* bsc_node_load_cert_bacfile loads one credentional file from bacfile object
* Note: the function adds null-terminated byte to loaded file
@@ -314,30 +277,223 @@ void bsc_set_timestamp(BACNET_DATE_TIME *timestamp)
* @brief Check if BACnet/SC certificate files exist
* @return true if all files exist, else false
*/
bool bsc_cert_files_check(void)
bool bsc_cert_files_check(uint32_t netport_instance)
{
uint32_t instance;
uint32_t file_instance;
instance = Network_Port_Index_To_Instance(0);
file_instance = Network_Port_Issuer_Certificate_File(instance, 0);
file_instance = Network_Port_Issuer_Certificate_File(netport_instance, 0);
if (bacfile_file_size(file_instance) == 0) {
PRINTF_ERR("CA certificate file not exist\n");
PRINTF_ERR(
"Issuer Certificate file %u size=0. Path=%s\n", file_instance,
bacfile_pathname(file_instance));
return false;
}
file_instance = Network_Port_Operational_Certificate_File(instance);
file_instance = Network_Port_Operational_Certificate_File(netport_instance);
if (bacfile_file_size(file_instance) == 0) {
PRINTF_ERR("Certificate file not exist\n");
PRINTF_ERR(
"Operational Certificate file %u size=0. Path=%s\n", file_instance,
bacfile_pathname(file_instance));
PRINTF_ERR("Operational Certificate file not exist\n");
return false;
}
file_instance = Network_Port_Certificate_Key_File(instance);
file_instance = Network_Port_Certificate_Key_File(netport_instance);
if (bacfile_file_size(file_instance) == 0) {
PRINTF_ERR("Certificate key file not exist\n");
PRINTF_ERR(
"Certificate Key file %u size=0. Path=%s\n", file_instance,
bacfile_pathname(file_instance));
return false;
}
return true;
}
/**
* @brief Return a return code string for human readable log messages
* @param ret BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_return_code_to_string(BSC_SC_RET ret)
{
switch (ret) {
case BSC_SC_SUCCESS:
return "SUCCESS";
case BSC_SC_NO_RESOURCES:
return "NO_RESOURCES";
case BSC_SC_BAD_PARAM:
return "BAD_PARAM";
case BSC_SC_INVALID_OPERATION:
return "INVALID_OPERATION";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_socket_event_to_string(BSC_SOCKET_EVENT ev)
{
switch (ev) {
case BSC_SOCKET_EVENT_CONNECTED:
return "CONNECTED";
case BSC_SOCKET_EVENT_DISCONNECTED:
return "DISCONNECTED";
case BSC_SOCKET_EVENT_RECEIVED:
return "RECEIVED";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_socket_state_to_string(BSC_SOCKET_STATE state)
{
switch (state) {
case BSC_SOCK_STATE_IDLE:
return "IDLE";
case BSC_SOCK_STATE_AWAITING_WEBSOCKET:
return "AWAITING_WEBSOCKET";
case BSC_SOCK_STATE_AWAITING_REQUEST:
return "AWAITING_REQUEST";
case BSC_SOCK_STATE_AWAITING_ACCEPT:
return "AWAITING_ACCEPT";
case BSC_SOCK_STATE_CONNECTED:
return "CONNECTED";
case BSC_SOCK_STATE_DISCONNECTING:
return "DISCONNECTING";
case BSC_SOCK_STATE_ERROR:
return "ERROR";
case BSC_SOCK_STATE_ERROR_FLUSH_TX:
return "ERROR_FLUSH_TX";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_websocket_return_to_string(BSC_WEBSOCKET_RET ret)
{
switch (ret) {
case BSC_WEBSOCKET_SUCCESS:
return "SUCCESS";
case BSC_WEBSOCKET_NO_RESOURCES:
return "NO_RESOURCES";
case BSC_WEBSOCKET_BAD_PARAM:
return "BAD_PARAM";
case BSC_WEBSOCKET_INVALID_OPERATION:
return "INVALID_OPERATION";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_websocket_event_to_string(BSC_WEBSOCKET_EVENT event)
{
switch (event) {
case BSC_WEBSOCKET_CONNECTED:
return "CONNECTED";
case BSC_WEBSOCKET_DISCONNECTED:
return "DISCONNECTED";
case BSC_WEBSOCKET_RECEIVED:
return "RECEIVED";
case BSC_WEBSOCKET_SENDABLE:
return "SENDABLE";
case BSC_WEBSOCKET_SERVER_STARTED:
return "SERVER_STARTED";
case BSC_WEBSOCKET_SERVER_STOPPED:
return "SERVER_STOPPED";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_bvlc_message_type_to_string(BVLC_SC_MESSAGE_TYPE message)
{
switch (message) {
case BVLC_SC_RESULT:
return "RESULT";
case BVLC_SC_ENCAPSULATED_NPDU:
return "ENCAPSULATED_NPDU";
case BVLC_SC_ADDRESS_RESOLUTION:
return "ADDRESS_RESOLUTION";
case BVLC_SC_ADDRESS_RESOLUTION_ACK:
return "ADDRESS_RESOLUTION_ACK";
case BVLC_SC_ADVERTISIMENT:
return "ADVERTISIMENT";
case BVLC_SC_ADVERTISIMENT_SOLICITATION:
return "ADVERTISIMENT_SOLICITATION";
case BVLC_SC_CONNECT_REQUEST:
return "CONNECT_REQUEST";
case BVLC_SC_CONNECT_ACCEPT:
return "CONNECT_ACCEPT";
case BVLC_SC_DISCONNECT_REQUEST:
return "DISCONNECT_REQUEST";
case BVLC_SC_DISCONNECT_ACK:
return "DISCONNECT_ACK";
case BVLC_SC_HEARTBEAT_REQUEST:
return "HEARTBEAT_REQUEST";
case BVLC_SC_HEARTBEAT_ACK:
return "HEARTBEAT_ACK";
case BVLC_SC_PROPRIETARY_MESSAGE:
return "PROPRIETARY_MESSAGE";
default:
break;
}
return "UNKNOWN";
}
/**
* @brief Return a string for human readable log messages
* @param ev BACnet/SC return codes
* @return return code string for human readable log messages
*/
const char *bsc_context_state_to_string(BSC_CTX_STATE state)
{
switch (state) {
case BSC_CTX_STATE_IDLE:
return "IDLE";
case BSC_CTX_STATE_INITIALIZING:
return "INITIALIZING";
case BSC_CTX_STATE_INITIALIZED:
return "INITIALIZED";
case BSC_CTX_STATE_DEINITIALIZING:
return "DEINITIALIZING";
default:
break;
}
return "UNKNOWN";
}
+8 -2
View File
@@ -15,6 +15,7 @@
#include "bacnet/basic/sys/debug.h"
#include "bacnet/datalink/bsc/bsc-node.h"
#include "bacnet/datalink/bsc/bsc-retcodes.h"
#include "bacnet/datalink/bsc/bsc-socket.h"
#include "bacnet/datalink/bsc/bvlc-sc.h"
#include "bacnet/datalink/bsc/websocket.h"
#include "bacnet/datetime.h"
@@ -25,12 +26,17 @@ void bsc_copy_vmac(BACNET_SC_VMAC_ADDRESS *dst, BACNET_SC_VMAC_ADDRESS *src);
void bsc_copy_uuid(BACNET_SC_UUID *dst, BACNET_SC_UUID *src);
char *bsc_vmac_to_string(BACNET_SC_VMAC_ADDRESS *vmac);
char *bsc_uuid_to_string(BACNET_SC_UUID *uuid);
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p);
void bsc_generate_random_uuid(BACNET_SC_UUID *p);
bool bsc_node_conf_fill_from_netport(
BSC_NODE_CONF *bsc_conf, BSC_NODE_EVENT_FUNC event_func);
void bsc_node_conf_cleanup(BSC_NODE_CONF *bsc_conf);
void bsc_copy_str(char *dst, const char *src, size_t dst_len);
void bsc_set_timestamp(BACNET_DATE_TIME *timestamp);
const char *bsc_return_code_to_string(BSC_SC_RET ret);
const char *bsc_socket_event_to_string(BSC_SOCKET_EVENT ev);
const char *bsc_socket_state_to_string(BSC_SOCKET_STATE state);
const char *bsc_websocket_return_to_string(BSC_WEBSOCKET_RET ret);
const char *bsc_websocket_event_to_string(BSC_WEBSOCKET_EVENT event);
const char *bsc_bvlc_message_type_to_string(BVLC_SC_MESSAGE_TYPE message);
const char *bsc_context_state_to_string(BSC_CTX_STATE state);
#endif
+95 -38
View File
@@ -16,6 +16,7 @@
/* BACnet Stack API */
#include "bacnet/apdu.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/basic/bbmd/h_bbmd.h"
#include "bacnet/basic/object/netport.h"
@@ -611,10 +612,29 @@ void dlenv_network_port_zigbee_init(uint32_t instance)
Network_Port_Changes_Pending_Set(instance, false);
}
#if defined(BACDL_BSC)
static bool dlenv_hub_connection_status_check(uint32_t instance)
{
BACNET_SC_HUB_CONNECTION_STATUS *status;
status = Network_Port_SC_Primary_Hub_Connection_Status(instance);
if (status && status->State == BACNET_SC_CONNECTION_STATE_CONNECTED) {
return true;
}
status = Network_Port_SC_Failover_Hub_Connection_Status(instance);
if (status && status->State == BACNET_SC_CONNECTION_STATE_CONNECTED) {
return true;
}
return false;
}
#endif
/**
* @brief Datalink network port object settings
* Datalink network port object settings for BACnet/SC
*/
static void bacnet_secure_connect_network_port_init(uint32_t instance)
void dlenv_network_port_bsc_init(uint32_t instance)
{
#ifdef BACDL_BSC
BACNET_SC_UUID uuid = { 0 };
@@ -629,6 +649,8 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
char *hub_binding;
char *direct_connect_initiate;
char *direct_connect_accept_urls;
uint32_t file_instance;
char c;
primary_hub_uri = getenv("BACNET_SC_PRIMARY_HUB_URI");
failover_hub_uri = getenv("BACNET_SC_FAILOVER_HUB_URI");
@@ -658,9 +680,6 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
/* SC parameters */
#ifdef BACDL_BSC
if (!bsc_cert_files_check()) {
exit(1);
}
bsc_generate_random_uuid(&uuid);
Network_Port_SC_Local_UUID_Set(instance, (BACNET_UUID *)&uuid);
bsc_generate_random_vmac(&vmac);
@@ -675,21 +694,42 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
instance, SC_NETPORT_DISCONNECT_TIMEOUT);
Network_Port_SC_Maximum_Reconnect_Time_Set(
instance, SC_NETPORT_RECONNECT_TIME);
if (filename_ca_1_cert == NULL) {
fprintf(stderr, "BACNET_SC_ISSUER_1_CERTIFICATE_FILE must be set\n");
return;
}
bacfile_create(BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE);
file_instance = bacfile_create(BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE);
if (file_instance != BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE) {
fprintf(
stderr,
"BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE was not created!\n");
return;
}
bacfile_pathname_set(
BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE, filename_ca_1_cert);
if (Datalink_Debug) {
fprintf(
stderr, "Issuer Certificate 1 file %u path=%s\n", file_instance,
bacfile_pathname(file_instance));
}
Network_Port_Issuer_Certificate_File_Set(
instance, 0, BSC_ISSUER_CERTIFICATE_FILE_1_INSTANCE);
if (filename_ca_2_cert) {
bacfile_create(BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE);
file_instance = bacfile_create(BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE);
if (file_instance != BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE) {
fprintf(
stderr,
"BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE was not created!\n");
return;
}
bacfile_pathname_set(
BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE, filename_ca_2_cert);
if (Datalink_Debug) {
fprintf(
stderr, "Issuer Certificate 2 file %u path=%s\n", file_instance,
bacfile_pathname(file_instance));
}
Network_Port_Issuer_Certificate_File_Set(
instance, 1, BSC_ISSUER_CERTIFICATE_FILE_2_INSTANCE);
}
@@ -698,9 +738,20 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
fprintf(stderr, "BACNET_SC_OPERATIONAL_CERTIFICATE_FILE must be set\n");
return;
}
bacfile_create(BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE);
file_instance = bacfile_create(BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE);
if (file_instance != BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE) {
fprintf(
stderr,
"BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE was not created!\n");
return;
}
bacfile_pathname_set(
BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE, filename_cert);
if (Datalink_Debug) {
fprintf(
stderr, "Operational Certificate file %u path=%s\n", file_instance,
bacfile_pathname(file_instance));
}
Network_Port_Operational_Certificate_File_Set(
instance, BSC_OPERATIONAL_CERTIFICATE_FILE_INSTANCE);
@@ -710,9 +761,21 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
"BACNET_SC_OPERATIONAL_CERTIFICATE_PRIVATE_KEY_FILE must be set\n");
return;
}
bacfile_create(BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE);
file_instance =
bacfile_create(BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE);
if (file_instance != BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE) {
fprintf(
stderr,
"BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE was not created!\n");
return;
}
bacfile_pathname_set(
BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE, filename_key);
if (Datalink_Debug) {
fprintf(
stderr, "Certificate Key file %u path=%s\n", file_instance,
bacfile_pathname(file_instance));
}
Network_Port_Certificate_Key_File_Set(
instance, BSC_CERTIFICATE_SIGNING_REQUEST_FILE_INSTANCE);
@@ -727,7 +790,6 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
"BACNET_SC_DIRECT_CONNECT_BINDING for direct connect.\n");
return;
}
Network_Port_SC_Primary_Hub_URI_Set(instance, primary_hub_uri);
Network_Port_SC_Failover_Hub_URI_Set(instance, failover_hub_uri);
@@ -735,7 +797,6 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
Network_Port_SC_Direct_Connect_Accept_Enable_Set(
instance, direct_binding != NULL);
char c;
c = direct_connect_initiate ? direct_connect_initiate[0] : '0';
if ((c != '0') && (c != 'n') && (c != 'N')) {
Network_Port_SC_Direct_Connect_Initiate_Enable_Set(instance, true);
@@ -753,43 +814,31 @@ static void bacnet_secure_connect_network_port_init(uint32_t instance)
/* last thing - clear pending changes - we don't want to set these
since they are already set */
Network_Port_Changes_Pending_Set(instance, false);
}
#if defined(BACDL_BSC)
static bool dlenv_hub_connection_status_check(void)
{
uint32_t instance = Network_Port_Index_To_Instance(0);
BACNET_SC_HUB_CONNECTION_STATUS *status;
status = Network_Port_SC_Primary_Hub_Connection_Status(instance);
if (status && status->State == BACNET_SC_CONNECTION_STATE_CONNECTED) {
return true;
if (!bsc_cert_files_check(instance)) {
debug_printf_stderr("BSC Certificate files missing.\n");
exit(1);
}
status = Network_Port_SC_Failover_Hub_Connection_Status(instance);
if (status && status->State == BACNET_SC_CONNECTION_STATE_CONNECTED) {
return true;
}
return false;
}
#endif
}
/**
* Datalink network port object settings for BACnet/SC
*/
void dlenv_network_port_bsc_init(void)
void bsc_register_as_node(uint32_t instance)
{
#if defined(BACDL_BSC)
/* if a user has configured BACnet/SC port with primary hub URI, */
/* wait for a establishing of a connection to BACnet/SC hub at first */
/* to reduce possibility of packet losses. */
if (Network_Port_SC_Primary_Hub_URI_char(1)) {
while (!dlenv_hub_connection_status_check()) {
if (Network_Port_SC_Primary_Hub_URI_char(instance)) {
debug_printf_stderr("Waiting for a BACnet/SC connection to hub...\n");
while (!dlenv_hub_connection_status_check(instance)) {
bsc_wait(1);
bsc_maintenance_timer(1);
}
debug_printf_stderr("Connected to a BACnet/SC hub!\n");
}
#else
(void)instance;
#endif
}
@@ -929,6 +978,9 @@ void dlenv_init(void)
char *pEnv = NULL;
uint8_t port_type = PORT_TYPE_BIP;
if (getenv("BACNET_DATALINK_DEBUG")) {
dlenv_debug_enable();
}
#if defined(BACDL_MULTIPLE)
pEnv = getenv("BACNET_DATALINK");
if (pEnv) {
@@ -999,6 +1051,9 @@ void dlenv_init(void)
#if defined(BACFILE)
/* initialize the POSIX file objects */
bacfile_posix_init();
if (Datalink_Debug) {
debug_printf_stderr("POSIX file services initialized.\n");
}
#endif
/* === Initialize the Network Port Object Here === */
Network_Port_Type_Set(Network_Port_Instance, port_type);
@@ -1016,8 +1071,7 @@ void dlenv_init(void)
dlenv_network_port_zigbee_init(Network_Port_Instance);
break;
case PORT_TYPE_BSC:
dlenv_network_port_bsc_init();
bacnet_secure_connect_network_port_init(Network_Port_Instance);
dlenv_network_port_bsc_init(Network_Port_Instance);
break;
default:
break;
@@ -1034,7 +1088,7 @@ void dlenv_init(void)
if (pEnv) {
apdu_retries_set((uint8_t)strtol(pEnv, NULL, 0));
}
/* === Initialize the Datalink Here === */
/* === INIT - Initialize the Datalink Here === */
pEnv = getenv("BACNET_IFACE");
if (Datalink_Debug) {
fprintf(stderr, "BACNET_IFACE=%s\n", pEnv ? pEnv : "none");
@@ -1042,6 +1096,7 @@ void dlenv_init(void)
if (!datalink_init(pEnv)) {
exit(1);
}
/* === POST INIT - After the Datalink is Initialized === */
#if (MAX_TSM_TRANSACTIONS)
pEnv = getenv("BACNET_INVOKE_ID");
if (pEnv) {
@@ -1052,5 +1107,7 @@ void dlenv_init(void)
bbmd_register_as_foreign_device();
} else if (port_type == PORT_TYPE_BIP6) {
bbmd6_register_as_foreign_device();
} else if (port_type == PORT_TYPE_BSC) {
bsc_register_as_node(Network_Port_Instance);
}
}