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:
@@ -148,6 +148,12 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the sequence of BACnet/SC datalink initialization that was
|
||||
broken during datalink environment changes and POSIX file refactoring.
|
||||
Refactored the UUID and VMAC random functions into port specific
|
||||
since stdlib rand() is not random and caused duplicate UUID and VMAC
|
||||
preventing BACnet/SC from forming any stable connections.
|
||||
Enabled debug in BACnet/SC datalink when BUILD=debug used.(#1142)
|
||||
* Fixed WPM workaround for BTL Specified Test 9.23.2.X5 by reverting.(#1140)
|
||||
* Fixed the API integration for the additional datatypes now supported
|
||||
in the Channel object by adding CHANNEL_VALUE_ALL to enable and test. (#1135)
|
||||
|
||||
@@ -62,7 +62,7 @@ ethernet:
|
||||
# see .github/workflows/gcc.yml
|
||||
.PHONY: bsc
|
||||
bsc:
|
||||
$(MAKE) BACDL=bsc -s -C apps all
|
||||
$(MAKE) LEGACY=true BACDL=bsc -s -C apps all
|
||||
|
||||
.PHONY: apps
|
||||
apps:
|
||||
@@ -226,7 +226,11 @@ server-mini:
|
||||
|
||||
.PHONY: sc-hub
|
||||
sc-hub:
|
||||
$(MAKE) BACDL=bsc -s -C apps $@
|
||||
$(MAKE) LEGACY=true BACDL=bsc -s -C apps $@
|
||||
|
||||
.PHONY: sc-hub-debug
|
||||
sc-hub-debug:
|
||||
$(MAKE) LEGACY=true BACDL=bsc BUILD=debug -s -C apps sc-hub
|
||||
|
||||
.PHONY: mstpcap
|
||||
mstpcap:
|
||||
|
||||
+12
-2
@@ -43,8 +43,7 @@ ifeq (${BACDL},bip6)
|
||||
BACDL_DEFINE=-DBACDL_BIP6=1
|
||||
endif
|
||||
ifeq (${BACDL},bsc)
|
||||
BACDL_DEFINE=-DBACDL_BSC=1
|
||||
BACNET_DEFINE=-DBACFILE=1
|
||||
BACDL_DEFINE=-DBACDL_BSC=1 -DBACFILE=1
|
||||
endif
|
||||
ifeq (${BACDL},zigbee)
|
||||
BACDL_DEFINE=-DBACDL_ZIGBEE=1
|
||||
@@ -206,6 +205,17 @@ DEBUGGING = -g -DDEBUG_ENABLED=1
|
||||
ifeq (${BACDL},bip)
|
||||
BACNET_DEFINES += -DBIP_DEBUG
|
||||
endif
|
||||
ifeq (${BACDL},bsc)
|
||||
CFLAGS += -DDEBUG_BSC_DATALINK=1
|
||||
CFLAGS += -DDEBUG_BSC_EVENT=0
|
||||
CFLAGS += -DDEBUG_BSC_HUB_CONNECTOR=0
|
||||
CFLAGS += -DDEBUG_BSC_HUB_FUNCTION=0
|
||||
CFLAGS += -DDEBUG_BSC_NODE_SWITCH=0
|
||||
CFLAGS += -DDEBUG_BSC_NODE=0
|
||||
CFLAGS += -DDEBUG_BSC_SOCKET=0
|
||||
CFLAGS += -DDEBUG_WEBSOCKET_CLIENT=0
|
||||
CFLAGS += -DDEBUG_WEBSOCKET_SERVER=0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${LEGACY},true)
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
Test BACnet/SC using the following steps:
|
||||
|
||||
* Build apps for bsc datalink:
|
||||
* Build all the apps and the hub for the BACnet/SC datalink:
|
||||
|
||||
make bsc
|
||||
make clean bsc sc-hub
|
||||
|
||||
* Run hub app:
|
||||
* Run the BACnet/SC hub application:
|
||||
|
||||
cd bin
|
||||
./bsc-server.sh
|
||||
./bacschub 1 Hubster
|
||||
|
||||
* Run server app:
|
||||
* Run BACnet/SC server application:
|
||||
|
||||
cd bin
|
||||
./bsc-client.sh
|
||||
./bacserv 123 Francine
|
||||
|
||||
* Run any client:
|
||||
* Run any BACnet/SC client:
|
||||
|
||||
cd bin
|
||||
./bsc-client.sh
|
||||
|
||||
+24
-4
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of mutex abstraction used in BACNet secure connect.
|
||||
* @brief Implementation of port specific API used in BACNet secure connect.
|
||||
* @author Kirill Neznamov <kirill.neznamov@dsr-corporation.com>
|
||||
* @date August 2022
|
||||
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||
@@ -14,10 +14,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "bacnet/datalink/bsc/bsc-event.h"
|
||||
|
||||
#define DEBUG_BSC_EVENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_BSC_EVENT == 1
|
||||
#if DEBUG_BSC_EVENT
|
||||
#define DEBUG_PRINTF printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
@@ -179,3 +177,25 @@ void bsc_wait_ms(int mseconds)
|
||||
{
|
||||
usleep(mseconds * 1000);
|
||||
}
|
||||
|
||||
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p)
|
||||
{
|
||||
arc4random_buf(p->address, BVLC_SC_VMAC_SIZE);
|
||||
|
||||
/* 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[0] = (p->address[0] & 0xF0) | 0x02;
|
||||
|
||||
debug_printf_hex(
|
||||
0, p->address, BVLC_SC_VMAC_SIZE, "bsc_generate_random_vmac:");
|
||||
}
|
||||
|
||||
void bsc_generate_random_uuid(BACNET_SC_UUID *p)
|
||||
{
|
||||
arc4random_buf(p->uuid, BVLC_SC_UUID_SIZE);
|
||||
debug_printf_hex(
|
||||
0, p->uuid, BVLC_SC_UUID_SIZE, "bsc_generate_random_uuid:");
|
||||
}
|
||||
|
||||
@@ -14,10 +14,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "websocket-global.h"
|
||||
|
||||
#define DEBUG_WEBSOCKET_CLIENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_CLIENT == 1
|
||||
#if DEBUG_WEBSOCKET_CLIENT
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include "websocket-global.h"
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define DEBUG_WEBSOCKET_SERVER 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_SERVER == 1
|
||||
#if DEBUG_WEBSOCKET_SERVER
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
+25
-4
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of mutex abstraction used in BACNet secure connect.
|
||||
* @brief Implementation of port specific API used in BACNet secure connect.
|
||||
* @author Kirill Neznamov <kirill.neznamov@dsr-corporation.com>
|
||||
* @date August 2022
|
||||
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||
@@ -11,13 +11,12 @@
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/random.h>
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "bacnet/datalink/bsc/bsc-event.h"
|
||||
|
||||
#define DEBUG_BSC_EVENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_BSC_EVENT == 1
|
||||
#if DEBUG_BSC_EVENT
|
||||
#define DEBUG_PRINTF printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
@@ -179,3 +178,25 @@ void bsc_wait_ms(int mseconds)
|
||||
{
|
||||
usleep(mseconds * 1000);
|
||||
}
|
||||
|
||||
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p)
|
||||
{
|
||||
getrandom(p->address, BVLC_SC_VMAC_SIZE, 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[0] = (p->address[0] & 0xF0) | 0x02;
|
||||
|
||||
debug_printf_hex(
|
||||
0, p->address, BVLC_SC_VMAC_SIZE, "bsc_generate_random_vmac:");
|
||||
}
|
||||
|
||||
void bsc_generate_random_uuid(BACNET_SC_UUID *p)
|
||||
{
|
||||
getrandom(p->uuid, BVLC_SC_UUID_SIZE, 0);
|
||||
debug_printf_hex(
|
||||
0, p->uuid, BVLC_SC_UUID_SIZE, "bsc_generate_random_uuid:");
|
||||
}
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "websocket-global.h"
|
||||
|
||||
#define DEBUG_WEBSOCKET_CLIENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_CLIENT == 1
|
||||
#if DEBUG_WEBSOCKET_CLIENT
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
#include "websocket-global.h"
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define DEBUG_WEBSOCKET_SERVER 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_SERVER == 1
|
||||
#if DEBUG_WEBSOCKET_SERVER
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string.h>
|
||||
/* BACnet Stack defines - first */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "bacnet/basic/object/bacfile.h"
|
||||
|
||||
#ifndef FILE_RECORD_SIZE
|
||||
@@ -57,6 +58,8 @@ size_t bacfile_posix_file_size(const char *pathname)
|
||||
file_size = (size_t)file_position;
|
||||
}
|
||||
fclose(pFile);
|
||||
} else {
|
||||
debug_printf_stderr("Failed to open %s for reading!\n", pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +106,8 @@ size_t bacfile_posix_read_stream_data(
|
||||
(void)fseek(pFile, fileStartPosition, SEEK_SET);
|
||||
len = fread(fileData, 1, fileDataLen, pFile);
|
||||
fclose(pFile);
|
||||
} else {
|
||||
debug_printf_stderr("Failed to open %s for reading!\n", pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +150,8 @@ size_t bacfile_posix_write_stream_data(
|
||||
}
|
||||
bytes_written = fwrite(fileData, fileDataLen, 1, pFile);
|
||||
fclose(pFile);
|
||||
} else {
|
||||
debug_printf_stderr("Failed to open %s for writing!\n", pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +211,8 @@ bool bacfile_posix_write_record_data(
|
||||
status = true;
|
||||
}
|
||||
fclose(pFile);
|
||||
} else {
|
||||
debug_printf_stderr("Failed to open %s for writing!\n", pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +259,8 @@ bool bacfile_posix_read_record_data(
|
||||
status = true;
|
||||
}
|
||||
fclose(pFile);
|
||||
} else {
|
||||
debug_printf_stderr("Failed to open %s for reading!\n", pathname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,5 +279,7 @@ void bacfile_posix_init(void)
|
||||
bacfile_read_record_data_callback_set(bacfile_posix_read_record_data);
|
||||
bacfile_file_size_callback_set(bacfile_posix_file_size);
|
||||
bacfile_file_size_set_callback_set(bacfile_posix_file_size_set);
|
||||
#elif defined(BACDL_BSC)
|
||||
#error BACFILE is not defined for BACnet/SC!
|
||||
#endif
|
||||
}
|
||||
|
||||
+23
-4
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of mutex abstraction used in BACNet secure connect.
|
||||
* @brief Implementation of port specific API used in BACNet secure connect.
|
||||
* @author Kirill Neznamov <kirill.neznamov@dsr-corporation.com>
|
||||
* @date August 2022
|
||||
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -13,10 +14,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "bacnet/datalink/bsc/bsc-event.h"
|
||||
|
||||
#define DEBUG_BSC_EVENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_BSC_EVENT == 1
|
||||
#if DEBUG_BSC_EVENT
|
||||
#define DEBUG_PRINTF printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
@@ -144,3 +143,23 @@ void bsc_wait_ms(int mseconds)
|
||||
{
|
||||
Sleep(mseconds);
|
||||
}
|
||||
|
||||
void bsc_generate_random_vmac(BACNET_SC_VMAC_ADDRESS *p)
|
||||
{
|
||||
// Use RtlGenRandom (SystemFunction036) for cryptographically secure random
|
||||
// bytes
|
||||
RtlGenRandom(p->address, BVLC_SC_VMAC_SIZE);
|
||||
|
||||
/* According H.7.3 EUI-48 and Random-48 VMAC Address */
|
||||
p->address[0] = (p->address[0] & 0xF0) | 0x02;
|
||||
|
||||
debug_printf_hex(
|
||||
0, p->address, BVLC_SC_VMAC_SIZE, "bsc_generate_random_vmac:");
|
||||
}
|
||||
|
||||
void bsc_generate_random_uuid(BACNET_SC_UUID *p)
|
||||
{
|
||||
RtlGenRandom(p->uuid, BVLC_SC_UUID_SIZE);
|
||||
debug_printf_hex(
|
||||
0, p->uuid, BVLC_SC_UUID_SIZE, "bsc_generate_random_uuid:");
|
||||
}
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "websocket-global.h"
|
||||
|
||||
#define DEBUG_WEBSOCKET_CLIENT 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_CLIENT == 1
|
||||
#if DEBUG_WEBSOCKET_CLIENT
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
#include "bacnet/basic/sys/debug.h"
|
||||
#include "websocket-global.h"
|
||||
|
||||
#define DEBUG_WEBSOCKET_SERVER 0
|
||||
|
||||
#undef DEBUG_PRINTF
|
||||
#if DEBUG_WEBSOCKET_SERVER == 1
|
||||
#if DEBUG_WEBSOCKET_SERVER
|
||||
#define DEBUG_PRINTF debug_printf
|
||||
#else
|
||||
#undef DEBUG_ENABLED
|
||||
|
||||
@@ -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,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 \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
#endif
|
||||
"err = %s\n",
|
||||
bsc_return_code_to_string(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
#if DEBUG_ENABLED == 1
|
||||
else {
|
||||
DEBUG_PRINTF("pdu with len = %d is dropped\n", pdu_len);
|
||||
} else {
|
||||
DEBUG_PRINTF(
|
||||
"BSC-HUB: received 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+94
-37
@@ -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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ add_compile_definitions(
|
||||
BACNET_SC_DIRECT_ACCEPT_URI_MAX=6
|
||||
MAX_TSM_TRANSACTIONS=0
|
||||
BSC_CONF_TX_PRE=0
|
||||
BACFILE=1
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
||||
@@ -10169,7 +10169,7 @@ static void test_sc_datalink(void)
|
||||
|
||||
init_node_ev(&node_ev2);
|
||||
init_node_ev(&node_ev3);
|
||||
zassert_equal(bsc_cert_files_check(), true, NULL);
|
||||
zassert_equal(bsc_cert_files_check(SC_DATALINK_INSTANCE), true, NULL);
|
||||
zassert_equal(bsc_init(NULL), true, NULL);
|
||||
zassert_equal(bsc_init(NULL), false, NULL);
|
||||
memset(broadcast, 0xFF, sizeof(broadcast));
|
||||
@@ -10432,7 +10432,7 @@ static void test_sc_datalink_properties(void)
|
||||
init_node_ev(&node_ev2);
|
||||
init_node_ev(&node_ev3);
|
||||
init_node_ev(&node_ev4);
|
||||
zassert_equal(bsc_cert_files_check(), true, NULL);
|
||||
zassert_equal(bsc_cert_files_check(SC_DATALINK_INSTANCE), true, NULL);
|
||||
zassert_equal(bsc_init(NULL), true, NULL);
|
||||
|
||||
conf2.ca_cert_chain = ca_cert;
|
||||
|
||||
Reference in New Issue
Block a user