2059 lines
55 KiB
C
2059 lines
55 KiB
C
/**
|
|
* @file
|
|
* @brief Helper Network port objects for implement secure connect attributes
|
|
* @author Mikhail Antropov <michail.antropov@dsr-corporation.com>
|
|
* @date June 2022
|
|
* @copyright SPDX-License-Identifier: MIT
|
|
*/
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <bacnet/config.h>
|
|
#include <bacnet/basic/binding/address.h>
|
|
#include <bacnet/bacdef.h>
|
|
#include <bacnet/bacapp.h>
|
|
#include <bacnet/bacint.h>
|
|
#include <bacnet/bacdcode.h>
|
|
#include <bacnet/npdu.h>
|
|
#include <bacnet/apdu.h>
|
|
#include <bacnet/datalink/datalink.h>
|
|
#include <bacnet/basic/object/device.h>
|
|
#include <bacnet/timestamp.h>
|
|
/* me */
|
|
#include <bacnet/basic/object/bacfile.h>
|
|
#include <bacnet/basic/object/netport.h>
|
|
#include <bacnet/basic/object/sc_netport.h>
|
|
#include <bacnet/basic/object/netport_internal.h>
|
|
#include <bacnet/datalink/bsc/bsc-util.h>
|
|
|
|
#define SC_MIN_RECONNECT_MIN 2
|
|
#define SC_MIN_RECONNECT_MAX 300
|
|
|
|
#define SC_MAX_RECONNECT_MIN 2
|
|
#define SC_MAX_RECONNECT_MAX 600
|
|
|
|
#define SC_WAIT_CONNECT_MIN 5
|
|
#define SC_WAIT_CONNECT_MAX 300
|
|
|
|
static int
|
|
string_splite(const char *str, char separator, int *indexes, int length);
|
|
static bool
|
|
string_subsstr(char *str, int length, int index, const char *substr);
|
|
|
|
static void sc_binding_parse(char *str, uint16_t *port, char **ifname)
|
|
{
|
|
char *p = NULL;
|
|
|
|
*port = 0;
|
|
*ifname = NULL;
|
|
|
|
if (str != NULL) {
|
|
for (p = str; (*p != 0) && (*p != BACNET_SC_BINDING_SEPARATOR); ++p)
|
|
;
|
|
|
|
if (p != str) {
|
|
if (*p == BACNET_SC_BINDING_SEPARATOR) {
|
|
*p = 0;
|
|
*port = (uint16_t)strtol(p + 1, NULL, 0);
|
|
*ifname = (char *)str;
|
|
} else {
|
|
*port = (uint16_t)strtol(str, NULL, 0);
|
|
*ifname = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_Max_BVLC_Length_Accepted(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER max_length = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
max_length = params->Max_BVLC_Length_Accepted;
|
|
}
|
|
|
|
return max_length;
|
|
}
|
|
|
|
bool Network_Port_Max_BVLC_Length_Accepted_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Max_BVLC_Length_Accepted = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_Max_BVLC_Length_Accepted_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Max_BVLC_Length_Accepted_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_Max_NPDU_Length_Accepted(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER max_length = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
max_length = params->Max_NPDU_Length_Accepted;
|
|
}
|
|
|
|
return max_length;
|
|
}
|
|
|
|
bool Network_Port_Max_NPDU_Length_Accepted_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Max_NPDU_Length_Accepted = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_Max_NPDU_Length_Accepted_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Max_NPDU_Length_Accepted_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Primary_Hub_URI(
|
|
uint32_t object_instance, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
status = characterstring_init_ansi(str, params->SC_Primary_Hub_URI);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
const char *Network_Port_SC_Primary_Hub_URI_char(uint32_t object_instance)
|
|
{
|
|
char *p = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params && params->SC_Primary_Hub_URI[0]) {
|
|
p = params->SC_Primary_Hub_URI;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
bool Network_Port_SC_Primary_Hub_URI_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Primary_Hub_URI, sizeof(params->SC_Primary_Hub_URI),
|
|
"%s", str);
|
|
} else {
|
|
params->SC_Primary_Hub_URI[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Primary_Hub_URI_Dirty_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Primary_Hub_URI_dirty,
|
|
sizeof(params->SC_Primary_Hub_URI_dirty), "%s", str);
|
|
} else {
|
|
params->SC_Primary_Hub_URI_dirty[0] = 0;
|
|
}
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Failover_Hub_URI(
|
|
uint32_t object_instance, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
status = characterstring_init_ansi(str, params->SC_Failover_Hub_URI);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
const char *Network_Port_SC_Failover_Hub_URI_char(uint32_t object_instance)
|
|
{
|
|
char *p = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params && params->SC_Failover_Hub_URI[0]) {
|
|
p = params->SC_Failover_Hub_URI;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
bool Network_Port_SC_Failover_Hub_URI_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Failover_Hub_URI, sizeof(params->SC_Failover_Hub_URI),
|
|
"%s", str);
|
|
} else {
|
|
params->SC_Failover_Hub_URI[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Failover_Hub_URI_Dirty_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Failover_Hub_URI_dirty,
|
|
sizeof(params->SC_Failover_Hub_URI_dirty), "%s", str);
|
|
} else {
|
|
params->SC_Failover_Hub_URI_dirty[0] = 0;
|
|
}
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_SC_Minimum_Reconnect_Time(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER timeout = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
timeout = params->SC_Minimum_Reconnect_Time;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
bool Network_Port_SC_Minimum_Reconnect_Time_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_MIN_RECONNECT_MIN) || (value > SC_MIN_RECONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Minimum_Reconnect_Time = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Minimum_Reconnect_Time_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_MIN_RECONNECT_MIN) || (value > SC_MIN_RECONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Minimum_Reconnect_Time_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_SC_Maximum_Reconnect_Time(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER timeout = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
timeout = params->SC_Maximum_Reconnect_Time;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
bool Network_Port_SC_Maximum_Reconnect_Time_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_MAX_RECONNECT_MIN) || (value > SC_MAX_RECONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Maximum_Reconnect_Time = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Maximum_Reconnect_Time_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_MAX_RECONNECT_MIN) || (value > SC_MAX_RECONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Maximum_Reconnect_Time_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_SC_Connect_Wait_Timeout(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER timeout = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
timeout = params->SC_Connect_Wait_Timeout;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
bool Network_Port_SC_Connect_Wait_Timeout_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_WAIT_CONNECT_MIN) || (value > SC_WAIT_CONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Connect_Wait_Timeout = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Connect_Wait_Timeout_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if ((value < SC_WAIT_CONNECT_MIN) || (value > SC_WAIT_CONNECT_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Connect_Wait_Timeout_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_SC_Disconnect_Wait_Timeout(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER timeout = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
timeout = params->SC_Disconnect_Wait_Timeout;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
bool Network_Port_SC_Disconnect_Wait_Timeout_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Disconnect_Wait_Timeout = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Disconnect_Wait_Timeout_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Disconnect_Wait_Timeout_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_UNSIGNED_INTEGER
|
|
Network_Port_SC_Heartbeat_Timeout(uint32_t object_instance)
|
|
{
|
|
BACNET_UNSIGNED_INTEGER timeout = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
timeout = params->SC_Heartbeat_Timeout;
|
|
}
|
|
|
|
return timeout;
|
|
}
|
|
|
|
bool Network_Port_SC_Heartbeat_Timeout_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Heartbeat_Timeout = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Heartbeat_Timeout_Dirty_Set(
|
|
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Heartbeat_Timeout_dirty = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_SC_HUB_CONNECTOR_STATE
|
|
Network_Port_SC_Hub_Connector_State(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_HUB_CONNECTOR_STATE state =
|
|
BACNET_SC_HUB_CONNECTOR_STATE_NO_HUB_CONNECTION;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
state = params->SC_Hub_Connector_State;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Connector_State_Set(
|
|
uint32_t object_instance, BACNET_SC_HUB_CONNECTOR_STATE value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Hub_Connector_State = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t Network_Port_Operational_Certificate_File(uint32_t object_instance)
|
|
{
|
|
uint32_t id = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
id = params->Operational_Certificate_File;
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
bool Network_Port_Operational_Certificate_File_Set(
|
|
uint32_t object_instance, uint32_t value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Operational_Certificate_File = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t
|
|
Network_Port_Issuer_Certificate_File(uint32_t object_instance, uint8_t index)
|
|
{
|
|
uint32_t id = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params && (index < BACNET_ISSUER_CERT_FILE_MAX)) {
|
|
id = params->Issuer_Certificate_Files[index];
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
bool Network_Port_Issuer_Certificate_File_Set(
|
|
uint32_t object_instance, uint8_t index, uint32_t value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params || (index >= BACNET_ISSUER_CERT_FILE_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
params->Issuer_Certificate_Files[index] = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode one BACnetARRAY property element; a function template
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param index [in] array index requested:
|
|
* 0 to n for individual array members
|
|
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
|
|
* return the length of buffer if it had been built
|
|
* @return The length of the apdu encoded or
|
|
* BACNET_STATUS_ERROR for invalid array index
|
|
*/
|
|
int Network_Port_Issuer_Certificate_File_Encode(
|
|
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
|
|
{
|
|
int apdu_len = 0;
|
|
uint32_t file_instance = 0;
|
|
|
|
if (index >= BACNET_ISSUER_CERT_FILE_MAX) {
|
|
apdu_len = BACNET_STATUS_ERROR;
|
|
} else {
|
|
file_instance =
|
|
Network_Port_Issuer_Certificate_File(object_instance, index);
|
|
apdu_len = encode_application_unsigned(apdu, file_instance);
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
uint32_t Network_Port_Certificate_Signing_Request_File(uint32_t object_instance)
|
|
{
|
|
uint32_t id = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
id = params->Certificate_Signing_Request_File;
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
bool Network_Port_Certificate_Signing_Request_File_Set(
|
|
uint32_t object_instance, uint32_t value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Certificate_Signing_Request_File = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef BACNET_SECURE_CONNECT_ROUTING_TABLE
|
|
|
|
#if 0
|
|
/* This function will needed if the Network_Port_Routing_Table_Find()
|
|
or Network_Port_Routing_Table_Get() will return individual fields,
|
|
not the entire struct. */
|
|
static bool MAC_Address_Get(uint8_t network_type, uint8_t *mac,
|
|
BACNET_OCTET_STRING *mac_address)
|
|
{
|
|
bool status = false;
|
|
uint8_t ip_mac[4 + 2] = { 0 };
|
|
size_t mac_len = 0;
|
|
|
|
switch (network_type) {
|
|
case PORT_TYPE_ETHERNET:
|
|
mac_len = 6;
|
|
break;
|
|
case PORT_TYPE_MSTP:
|
|
mac_len = 1;
|
|
break;
|
|
case PORT_TYPE_BIP:
|
|
memcpy(&ip_mac[0], mac, 4);
|
|
/* convert port from host-byte-order to network-byte-order */
|
|
encode_unsigned16(&ip_mac[4], *(uint16_t*)(mac + 4));
|
|
mac = &ip_mac[0];
|
|
mac_len = sizeof(ip_mac);
|
|
break;
|
|
case PORT_TYPE_BIP6:
|
|
mac_len = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (mac) {
|
|
status = octetstring_init(mac_address, mac, mac_len);
|
|
}
|
|
return status;
|
|
}
|
|
#endif
|
|
|
|
static bool MAC_Address_Set(
|
|
uint8_t network_type, uint8_t *mac_dest, uint8_t *mac_src, uint8_t mac_len)
|
|
{
|
|
bool status = false;
|
|
size_t mac_size = 0;
|
|
uint8_t ip_mac[4 + 2] = { 0 };
|
|
|
|
switch (network_type) {
|
|
case PORT_TYPE_ETHERNET:
|
|
mac_size = 6;
|
|
break;
|
|
case PORT_TYPE_MSTP:
|
|
mac_size = 1;
|
|
break;
|
|
case PORT_TYPE_BIP:
|
|
memcpy(&ip_mac[0], mac_src, 4);
|
|
/* convert port from host-byte-order to network-byte-order */
|
|
decode_unsigned16(&mac_src[4], (uint16_t *)&ip_mac[4]);
|
|
mac_src = &ip_mac[0];
|
|
mac_len = sizeof(ip_mac);
|
|
break;
|
|
case PORT_TYPE_BIP6:
|
|
mac_size = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (mac_src && mac_dest && (mac_len == mac_size)) {
|
|
memcpy(mac_dest, mac_src, mac_size);
|
|
status = true;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
BACNET_ROUTER_ENTRY *Network_Port_Routing_Table_Find(
|
|
uint32_t object_instance, uint16_t network_number)
|
|
{
|
|
BACNET_ROUTER_ENTRY *entry = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return entry;
|
|
}
|
|
|
|
entry = Keylist_Data(params->Routing_Table, network_number);
|
|
|
|
return entry;
|
|
}
|
|
|
|
BACNET_ROUTER_ENTRY *
|
|
Network_Port_Routing_Table_Get(uint32_t object_instance, uint8_t index)
|
|
{
|
|
BACNET_ROUTER_ENTRY *entry = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return entry;
|
|
}
|
|
|
|
entry = Keylist_Data_Index(params->Routing_Table, index);
|
|
|
|
return entry;
|
|
}
|
|
|
|
bool Network_Port_Routing_Table_Add(
|
|
uint32_t object_instance,
|
|
uint16_t network_number,
|
|
uint8_t *mac,
|
|
uint8_t mac_len,
|
|
uint8_t status,
|
|
uint8_t performance_index)
|
|
{
|
|
int index;
|
|
uint8_t network_type;
|
|
BACNET_ROUTER_ENTRY *entry;
|
|
BACNET_SC_PARAMS *params;
|
|
|
|
params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
network_type = Network_Port_Type(object_instance);
|
|
entry = calloc(1, sizeof(BACNET_ROUTER_ENTRY));
|
|
if (!entry) {
|
|
return false;
|
|
}
|
|
entry->Network_Number = network_number;
|
|
MAC_Address_Set(network_type, entry->Mac_Address, mac, mac_len);
|
|
entry->Status = status;
|
|
entry->Performance_Index = performance_index;
|
|
index = Keylist_Data_Add(params->Routing_Table, network_number, entry);
|
|
if (index < 0) {
|
|
free(entry);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_Routing_Table_Delete(
|
|
uint32_t object_instance, uint16_t network_number)
|
|
{
|
|
BACNET_ROUTER_ENTRY *entry;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
entry = Keylist_Data_Delete(params->Routing_Table, network_number);
|
|
free(entry);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_Routing_Table_Delete_All(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
Keylist_Delete(params->Routing_Table);
|
|
params->Routing_Table = Keylist_Create();
|
|
|
|
return true;
|
|
}
|
|
|
|
uint8_t Network_Port_Routing_Table_Count(uint32_t object_instance)
|
|
{
|
|
uint8_t count = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return 0;
|
|
}
|
|
|
|
count = Keylist_Count(params->Routing_Table);
|
|
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle a request to encode all the the routing table entries
|
|
* @param apdu [out] Buffer in which the APDU contents are built.
|
|
* @param max_apdu [in] Max length of the APDU buffer.
|
|
*
|
|
* @return How many bytes were encoded in the buffer, or
|
|
* BACNET_STATUS_ABORT if the response would not fit within the buffer.
|
|
*/
|
|
int Network_Port_Routing_Table_Encode(
|
|
uint32_t object_instance, uint8_t *apdu, int max_apdu)
|
|
{
|
|
BACNET_ROUTER_ENTRY *entry = NULL;
|
|
int apdu_len = 0;
|
|
unsigned index = 0;
|
|
unsigned size = 0;
|
|
|
|
size = Network_Port_Routing_Table_Count(object_instance);
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_Routing_Table_Get(object_instance, index);
|
|
apdu_len += bacapp_encode_RouterEntry(NULL, entry);
|
|
}
|
|
if (apdu_len > max_apdu) {
|
|
return BACNET_STATUS_ABORT;
|
|
}
|
|
apdu_len = 0;
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_Routing_Table_Get(object_instance, index);
|
|
apdu_len += bacapp_encode_RouterEntry(&apdu[apdu_len], entry);
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
#endif /* BACNET_SECURE_CONNECT_ROUTING_TABLE */
|
|
|
|
#if BSC_CONF_HUB_FUNCTIONS_NUM != 0
|
|
|
|
BACNET_SC_HUB_CONNECTION_STATUS *
|
|
Network_Port_SC_Primary_Hub_Connection_Status(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_HUB_CONNECTION_STATUS *connection = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
connection = ¶ms->SC_Primary_Hub_Connection_Status;
|
|
}
|
|
|
|
return connection;
|
|
}
|
|
|
|
bool Network_Port_SC_Primary_Hub_Connection_Status_Set(
|
|
uint32_t object_instance,
|
|
BACNET_SC_CONNECTION_STATE state,
|
|
BACNET_DATE_TIME *connect_ts,
|
|
BACNET_DATE_TIME *disconnect_ts,
|
|
BACNET_ERROR_CODE error,
|
|
const char *error_details)
|
|
{
|
|
BACNET_SC_HUB_CONNECTION_STATUS *st;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
st = ¶ms->SC_Primary_Hub_Connection_Status;
|
|
st->State = state;
|
|
st->Connect_Timestamp = *connect_ts;
|
|
st->Disconnect_Timestamp = *disconnect_ts;
|
|
st->Error = error;
|
|
if (error_details) {
|
|
bsc_copy_str(
|
|
st->Error_Details, error_details, sizeof(st->Error_Details));
|
|
} else {
|
|
st->Error_Details[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_SC_HUB_CONNECTION_STATUS *
|
|
Network_Port_SC_Failover_Hub_Connection_Status(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_HUB_CONNECTION_STATUS *connection = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
connection = ¶ms->SC_Failover_Hub_Connection_Status;
|
|
}
|
|
|
|
return connection;
|
|
}
|
|
|
|
bool Network_Port_SC_Failover_Hub_Connection_Status_Set(
|
|
uint32_t object_instance,
|
|
BACNET_SC_CONNECTION_STATE state,
|
|
BACNET_DATE_TIME *connect_ts,
|
|
BACNET_DATE_TIME *disconnect_ts,
|
|
BACNET_ERROR_CODE error,
|
|
const char *error_details)
|
|
{
|
|
BACNET_SC_HUB_CONNECTION_STATUS *st;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
st = ¶ms->SC_Failover_Hub_Connection_Status;
|
|
st->State = state;
|
|
st->Connect_Timestamp = *connect_ts;
|
|
st->Disconnect_Timestamp = *disconnect_ts;
|
|
st->Error = error;
|
|
if (error_details) {
|
|
bsc_copy_str(
|
|
st->Error_Details, error_details, sizeof(st->Error_Details));
|
|
} else {
|
|
st->Error_Details[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Enable(uint32_t object_instance)
|
|
{
|
|
bool enable = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
enable = params->SC_Hub_Function_Enable;
|
|
}
|
|
|
|
return enable;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Enable_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Hub_Function_Enable = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Enable_Dirty_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Hub_Function_Enable_dirty = value;
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Accept_URI(
|
|
uint32_t object_instance, uint8_t index, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
int idx[BACNET_SC_DIRECT_ACCEPT_URI_MAX + 1] = { 0 };
|
|
int len;
|
|
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params && (index < BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
len = string_splite(
|
|
params->SC_Hub_Function_Accept_URIs, ' ', idx, sizeof(idx));
|
|
if (index < len) {
|
|
status = characterstring_init_ansi_safe(
|
|
str, params->SC_Hub_Function_Accept_URIs + idx[index],
|
|
idx[index + 1] - idx[index] - 1);
|
|
} else {
|
|
status = characterstring_init_ansi(str, "");
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Accept_URI_Set(
|
|
uint32_t object_instance, uint8_t index, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params || (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
string_subsstr(
|
|
params->SC_Hub_Function_Accept_URIs,
|
|
sizeof(params->SC_Hub_Function_Accept_URIs), index, str);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode a BACnetARRAY property element; a function template
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param index [in] array index requested:
|
|
* 0 to n for individual array members
|
|
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
|
|
* return the length of buffer if it had been built
|
|
* @return The length of the apdu encoded or
|
|
* BACNET_STATUS_ERROR for invalid array index
|
|
*/
|
|
int Network_Port_SC_Hub_Function_Accept_URI_Encode(
|
|
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
|
|
{
|
|
int apdu_len = 0;
|
|
BACNET_CHARACTER_STRING uri = { 0 };
|
|
|
|
if (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX) {
|
|
apdu_len = BACNET_STATUS_ERROR;
|
|
} else {
|
|
if (Network_Port_SC_Hub_Function_Accept_URI(
|
|
object_instance, index, &uri)) {
|
|
apdu_len = encode_application_character_string(apdu, &uri);
|
|
}
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Accept_URI_Dirty_Set(
|
|
uint32_t object_instance, uint8_t index, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params || (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
string_subsstr(
|
|
params->SC_Hub_Function_Accept_URIs_dirty,
|
|
sizeof(params->SC_Hub_Function_Accept_URIs_dirty), index, str);
|
|
|
|
return true;
|
|
}
|
|
|
|
const char *
|
|
Network_Port_SC_Hub_Function_Accept_URIs_char(uint32_t object_instance)
|
|
{
|
|
char *p = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
p = params->SC_Hub_Function_Accept_URIs;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Accept_URIs_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Hub_Function_Accept_URIs,
|
|
sizeof(params->SC_Hub_Function_Accept_URIs), "%s", str);
|
|
} else {
|
|
params->SC_Hub_Function_Accept_URIs[0] = 0;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Binding(
|
|
uint32_t object_instance, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
char tmp[sizeof(params->SC_Hub_Function_Binding)];
|
|
|
|
if (params) {
|
|
snprintf(
|
|
tmp, sizeof(tmp), "%s:%d",
|
|
params->SC_Hub_Function_Binding + sizeof(uint16_t),
|
|
*(uint16_t *)params->SC_Hub_Function_Binding);
|
|
|
|
status = characterstring_init_ansi(str, tmp);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void Network_Port_SC_Hub_Function_Binding_get(
|
|
uint32_t object_instance, uint16_t *port, char **ifname)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
*port = 0;
|
|
*ifname = NULL;
|
|
|
|
if (params && params->SC_Hub_Function_Binding[0]) {
|
|
*port = *(uint16_t *)params->SC_Hub_Function_Binding;
|
|
*ifname = params->SC_Hub_Function_Binding + sizeof(uint16_t);
|
|
if (**ifname == 0) {
|
|
*ifname = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Binding_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
uint16_t port;
|
|
char *ifname;
|
|
char tmp[BACNET_BINDING_STRING_LENGTH];
|
|
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str && str[0]) {
|
|
bsc_copy_str(tmp, str, sizeof(tmp));
|
|
sc_binding_parse(tmp, &port, &ifname);
|
|
*(uint16_t *)params->SC_Hub_Function_Binding = port;
|
|
if (ifname) {
|
|
bsc_copy_str(
|
|
params->SC_Hub_Function_Binding + sizeof(uint16_t), ifname,
|
|
sizeof(params->SC_Hub_Function_Binding) - sizeof(uint16_t));
|
|
} else {
|
|
*(params->SC_Hub_Function_Binding + sizeof(uint16_t)) = 0;
|
|
}
|
|
} else {
|
|
memset(
|
|
params->SC_Hub_Function_Binding, 0,
|
|
sizeof(params->SC_Hub_Function_Binding));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Binding_Dirty_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Hub_Function_Binding_dirty,
|
|
sizeof(params->SC_Hub_Function_Binding_dirty), "%s", str);
|
|
} else {
|
|
params->SC_Hub_Function_Binding_dirty[0] = 0;
|
|
}
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_SC_HUB_FUNCTION_CONNECTION_STATUS *
|
|
Network_Port_SC_Hub_Function_Connection_Status_Get(
|
|
uint32_t object_instance, uint8_t index)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (!params) {
|
|
return NULL;
|
|
}
|
|
|
|
if (index >= params->SC_Hub_Function_Connection_Status_Count) {
|
|
return NULL;
|
|
}
|
|
|
|
return ¶ms->SC_Hub_Function_Connection_Status[index];
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Connection_Status_Add(
|
|
uint32_t object_instance,
|
|
BACNET_SC_CONNECTION_STATE state,
|
|
BACNET_DATE_TIME *connect_ts,
|
|
BACNET_DATE_TIME *disconnect_ts,
|
|
BACNET_HOST_N_PORT_DATA *peer_address,
|
|
uint8_t *peer_VMAC,
|
|
uint8_t *peer_UUID,
|
|
BACNET_ERROR_CODE error,
|
|
const char *error_details)
|
|
{
|
|
BACNET_SC_HUB_FUNCTION_CONNECTION_STATUS *st;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (params->SC_Hub_Function_Connection_Status_Count + 1 >
|
|
ARRAY_SIZE(params->SC_Hub_Function_Connection_Status)) {
|
|
return false;
|
|
}
|
|
|
|
st = ¶ms->SC_Hub_Function_Connection_Status
|
|
[params->SC_Hub_Function_Connection_Status_Count];
|
|
params->SC_Hub_Function_Connection_Status_Count += 1;
|
|
|
|
st->State = state;
|
|
st->Connect_Timestamp = *connect_ts;
|
|
st->Disconnect_Timestamp = *disconnect_ts;
|
|
st->Peer_Address = *peer_address;
|
|
memcpy(st->Peer_VMAC, peer_VMAC, sizeof(st->Peer_VMAC));
|
|
memcpy(
|
|
st->Peer_UUID.uuid.uuid128, peer_UUID,
|
|
sizeof(st->Peer_UUID.uuid.uuid128));
|
|
st->Error = error;
|
|
if (error_details) {
|
|
bsc_copy_str(
|
|
st->Error_Details, error_details, sizeof(st->Error_Details));
|
|
} else {
|
|
st->Error_Details[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Hub_Function_Connection_Status_Delete_All(
|
|
uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Hub_Function_Connection_Status_Count = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
int Network_Port_SC_Hub_Function_Connection_Status_Count(
|
|
uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return 0;
|
|
}
|
|
|
|
return params->SC_Hub_Function_Connection_Status_Count;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle a request to encode all the the entries
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param apdu [out] Buffer in which the APDU contents are built.
|
|
* @param max_apdu [in] Max length of the APDU buffer.
|
|
*
|
|
* @return How many bytes were encoded in the buffer, or
|
|
* BACNET_STATUS_ABORT if the response would not fit within the buffer.
|
|
*/
|
|
int Network_Port_SC_Hub_Function_Connection_Status_Encode(
|
|
uint32_t object_instance, uint8_t *apdu, int max_apdu)
|
|
{
|
|
BACNET_SC_HUB_FUNCTION_CONNECTION_STATUS *entry = NULL;
|
|
int apdu_len = 0;
|
|
unsigned index = 0;
|
|
unsigned size = 0;
|
|
|
|
size =
|
|
Network_Port_SC_Hub_Function_Connection_Status_Count(object_instance);
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Hub_Function_Connection_Status_Get(
|
|
object_instance, index);
|
|
apdu_len += bacapp_encode_SCHubFunctionConnection(NULL, entry);
|
|
}
|
|
if (apdu_len > max_apdu) {
|
|
return BACNET_STATUS_ABORT;
|
|
}
|
|
apdu_len = 0;
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Hub_Function_Connection_Status_Get(
|
|
object_instance, index);
|
|
apdu_len +=
|
|
bacapp_encode_SCHubFunctionConnection(&apdu[apdu_len], entry);
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
#endif /* BSC_CONF_HUB_FUNCTIONS_NUM!=0 */
|
|
|
|
#if BSC_CONF_HUB_CONNECTORS_NUM != 0
|
|
|
|
bool Network_Port_SC_Direct_Connect_Initiate_Enable(uint32_t object_instance)
|
|
{
|
|
bool enable = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
enable = params->SC_Direct_Connect_Initiate_Enable;
|
|
}
|
|
|
|
return enable;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Initiate_Enable_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Direct_Connect_Initiate_Enable = value;
|
|
|
|
return true;
|
|
}
|
|
bool Network_Port_SC_Direct_Connect_Initiate_Enable_Dirty_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Direct_Connect_Initiate_Enable_dirty = value;
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_Enable(uint32_t object_instance)
|
|
{
|
|
bool enable = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
enable = params->SC_Direct_Connect_Accept_Enable;
|
|
}
|
|
|
|
return enable;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_Enable_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Direct_Connect_Accept_Enable = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_Enable_Dirty_Set(
|
|
uint32_t object_instance, bool value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Direct_Connect_Accept_Enable_dirty = value;
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/* return number of urls, */
|
|
/* indexes are fill first position of urls plus position of end string */
|
|
static int
|
|
string_splite(const char *str, char separator, int *indexes, int length)
|
|
{
|
|
int i;
|
|
int k = 0;
|
|
indexes[0] = 0;
|
|
for (i = 0; str[i] != 0 && k < length; i++) {
|
|
if (str[i] == separator) {
|
|
k++;
|
|
indexes[k] = i + 1;
|
|
}
|
|
}
|
|
|
|
if (k < length) {
|
|
k++;
|
|
indexes[k] = i + 1;
|
|
}
|
|
|
|
return k;
|
|
}
|
|
|
|
static bool string_subsstr(char *str, int length, int index, const char *substr)
|
|
{
|
|
int idx[BACNET_SC_DIRECT_ACCEPT_URI_MAX + 1] = { 0 };
|
|
int len;
|
|
char *head;
|
|
char *tail_old;
|
|
char *tail_new;
|
|
|
|
len = string_splite(str, ' ', idx, sizeof(idx));
|
|
if (index < len) {
|
|
head = str + idx[index];
|
|
tail_old = str + idx[index + 1] - 1;
|
|
tail_new = head + strlen(substr);
|
|
if (tail_new + strlen(tail_old) + 1 - str >= length) {
|
|
return false;
|
|
}
|
|
|
|
memmove(tail_new, tail_old, strlen(tail_old) + 1);
|
|
memcpy(head, substr, strlen(substr));
|
|
} else {
|
|
head = str + strlen(str);
|
|
if (head != str) {
|
|
*head = ' ';
|
|
head++;
|
|
}
|
|
if (head + strlen(substr) + 1 - str >= length) {
|
|
return false;
|
|
}
|
|
memcpy(head, substr, strlen(substr) + 1);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_URI(
|
|
uint32_t object_instance, uint8_t index, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
int idx[BACNET_SC_DIRECT_ACCEPT_URI_MAX + 1] = { 0 };
|
|
int len;
|
|
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params && (index < BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
len = string_splite(
|
|
params->SC_Direct_Connect_Accept_URIs, ' ', idx, sizeof(idx));
|
|
if (index < len) {
|
|
status = characterstring_init_ansi_safe(
|
|
str, params->SC_Direct_Connect_Accept_URIs + idx[index],
|
|
idx[index + 1] - idx[index] - 1);
|
|
} else {
|
|
status = characterstring_init_ansi(str, "");
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_URI_Set(
|
|
uint32_t object_instance, uint8_t index, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params || (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
string_subsstr(
|
|
params->SC_Direct_Connect_Accept_URIs,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs), index, str);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode a BACnetARRAY property element; a function template
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param index [in] array index requested:
|
|
* 0 to n for individual array members
|
|
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
|
|
* return the length of buffer if it had been built
|
|
* @return The length of the apdu encoded or
|
|
* BACNET_STATUS_ERROR for ERROR_CODE_INVALID_ARRAY_INDEX
|
|
*/
|
|
int Network_Port_SC_Direct_Connect_Accept_URI_Encode(
|
|
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
|
|
{
|
|
int apdu_len = 0;
|
|
BACNET_CHARACTER_STRING uri = { 0 };
|
|
|
|
if (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX) {
|
|
apdu_len = BACNET_STATUS_ERROR;
|
|
} else {
|
|
if (Network_Port_SC_Direct_Connect_Accept_URI(
|
|
object_instance, index, &uri)) {
|
|
apdu_len = encode_application_character_string(apdu, &uri);
|
|
}
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_URI_Dirty_Set(
|
|
uint32_t object_instance, uint8_t index, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params || (index >= BACNET_SC_DIRECT_ACCEPT_URI_MAX)) {
|
|
return false;
|
|
}
|
|
|
|
string_subsstr(
|
|
params->SC_Direct_Connect_Accept_URIs_dirty,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs_dirty), index, str);
|
|
|
|
return true;
|
|
}
|
|
|
|
char *Network_Port_SC_Direct_Connect_Accept_URIs_char(uint32_t object_instance)
|
|
{
|
|
char *p = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
p = params->SC_Direct_Connect_Accept_URIs;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_URIs_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Direct_Connect_Accept_URIs,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs), "%s", str);
|
|
} else {
|
|
params->SC_Direct_Connect_Accept_URIs[0] = 0;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Accept_URIs_Dirty_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
if (params) {
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Direct_Connect_Accept_URIs_dirty,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs_dirty), "%s", str);
|
|
} else {
|
|
params->SC_Direct_Connect_Accept_URIs_dirty[0] = 0;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Binding(
|
|
uint32_t object_instance, BACNET_CHARACTER_STRING *str)
|
|
{
|
|
bool status = false;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
char tmp[sizeof(params->SC_Direct_Connect_Binding)];
|
|
|
|
if (params) {
|
|
snprintf(
|
|
tmp, sizeof(tmp), "%s:%d",
|
|
params->SC_Direct_Connect_Binding + sizeof(uint16_t),
|
|
*(uint16_t *)params->SC_Direct_Connect_Binding);
|
|
|
|
status = characterstring_init_ansi(str, tmp);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void Network_Port_SC_Direct_Connect_Binding_get(
|
|
uint32_t object_instance, uint16_t *port, char **ifname)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
|
|
*port = 0;
|
|
*ifname = NULL;
|
|
if (params && params->SC_Direct_Connect_Binding[0]) {
|
|
*port = *(uint16_t *)params->SC_Direct_Connect_Binding;
|
|
*ifname = params->SC_Direct_Connect_Binding + sizeof(uint16_t);
|
|
if (**ifname == 0) {
|
|
*ifname = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Binding_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
uint16_t port;
|
|
char *ifname;
|
|
char tmp[BACNET_BINDING_STRING_LENGTH];
|
|
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str && str[0]) {
|
|
bsc_copy_str(tmp, str, sizeof(tmp));
|
|
sc_binding_parse(tmp, &port, &ifname);
|
|
*(uint16_t *)params->SC_Direct_Connect_Binding = port;
|
|
if (ifname) {
|
|
bsc_copy_str(
|
|
params->SC_Direct_Connect_Binding + sizeof(uint16_t), ifname,
|
|
sizeof(params->SC_Direct_Connect_Binding) - sizeof(uint16_t));
|
|
} else {
|
|
*(params->SC_Direct_Connect_Binding + sizeof(uint16_t)) = 0;
|
|
}
|
|
} else {
|
|
memset(
|
|
params->SC_Direct_Connect_Binding, 0,
|
|
sizeof(params->SC_Direct_Connect_Binding));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Binding_Dirty_Set(
|
|
uint32_t object_instance, const char *str)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (str) {
|
|
snprintf(
|
|
params->SC_Direct_Connect_Binding_dirty,
|
|
sizeof(params->SC_Direct_Connect_Binding_dirty), "%s", str);
|
|
} else {
|
|
params->SC_Direct_Connect_Binding_dirty[0] = 0;
|
|
}
|
|
|
|
Network_Port_Changes_Pending_Set(object_instance, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
BACNET_SC_DIRECT_CONNECTION_STATUS *
|
|
Network_Port_SC_Direct_Connect_Connection_Status_Get(
|
|
uint32_t object_instance, uint8_t index)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return NULL;
|
|
}
|
|
|
|
if (index >= params->SC_Direct_Connect_Connection_Status_Count) {
|
|
return NULL;
|
|
}
|
|
|
|
return ¶ms->SC_Direct_Connect_Connection_Status[index];
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Connection_Status_Add(
|
|
uint32_t object_instance,
|
|
const char *uri,
|
|
BACNET_SC_CONNECTION_STATE state,
|
|
BACNET_DATE_TIME *connect_ts,
|
|
BACNET_DATE_TIME *disconnect_ts,
|
|
BACNET_HOST_N_PORT_DATA *peer_address,
|
|
uint8_t *peer_VMAC,
|
|
uint8_t *peer_UUID,
|
|
BACNET_ERROR_CODE error,
|
|
const char *error_details)
|
|
{
|
|
BACNET_SC_DIRECT_CONNECTION_STATUS *st;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (params->SC_Direct_Connect_Connection_Status_Count + 1 >
|
|
ARRAY_SIZE(params->SC_Direct_Connect_Connection_Status)) {
|
|
return false;
|
|
}
|
|
|
|
st = ¶ms->SC_Direct_Connect_Connection_Status
|
|
[params->SC_Direct_Connect_Connection_Status_Count];
|
|
params->SC_Direct_Connect_Connection_Status_Count += 1;
|
|
|
|
if (uri) {
|
|
bsc_copy_str(st->URI, uri, sizeof(st->URI));
|
|
} else {
|
|
st->URI[0] = 0;
|
|
}
|
|
st->State = state;
|
|
st->Connect_Timestamp = *connect_ts;
|
|
st->Disconnect_Timestamp = *disconnect_ts;
|
|
|
|
memcpy(&st->Peer_Address, peer_address, sizeof(st->Peer_Address));
|
|
memcpy(st->Peer_VMAC, peer_VMAC, sizeof(st->Peer_VMAC));
|
|
memcpy(
|
|
st->Peer_UUID.uuid.uuid128, peer_UUID,
|
|
sizeof(st->Peer_UUID.uuid.uuid128));
|
|
st->Error = error;
|
|
if (error_details) {
|
|
bsc_copy_str(
|
|
st->Error_Details, error_details, sizeof(st->Error_Details));
|
|
} else {
|
|
st->Error_Details[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Direct_Connect_Connection_Status_Delete_All(
|
|
uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Direct_Connect_Connection_Status_Count = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
int Network_Port_SC_Direct_Connect_Connection_Status_Count(
|
|
uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return 0;
|
|
}
|
|
|
|
return params->SC_Direct_Connect_Connection_Status_Count;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle a request to encode all the the entries
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param apdu [out] Buffer in which the APDU contents are built.
|
|
* @param max_apdu [in] Max length of the APDU buffer.
|
|
*
|
|
* @return How many bytes were encoded in the buffer, or
|
|
* BACNET_STATUS_ABORT if the response would not fit within the buffer.
|
|
*/
|
|
int Network_Port_SC_Direct_Connect_Connection_Status_Encode(
|
|
uint32_t object_instance, uint8_t *apdu, int max_apdu)
|
|
{
|
|
BACNET_SC_DIRECT_CONNECTION_STATUS *entry = NULL;
|
|
int apdu_len = 0;
|
|
unsigned index = 0;
|
|
unsigned size = 0;
|
|
|
|
size =
|
|
Network_Port_SC_Direct_Connect_Connection_Status_Count(object_instance);
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Direct_Connect_Connection_Status_Get(
|
|
object_instance, index);
|
|
apdu_len += bacapp_encode_SCDirectConnection(NULL, entry);
|
|
}
|
|
if (apdu_len > max_apdu) {
|
|
return BACNET_STATUS_ABORT;
|
|
}
|
|
apdu_len = 0;
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Direct_Connect_Connection_Status_Get(
|
|
object_instance, index);
|
|
apdu_len += bacapp_encode_SCDirectConnection(&apdu[apdu_len], entry);
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
#endif /* BSC_CONF_HUB_CONNECTORS_NUM!=0 */
|
|
|
|
BACNET_SC_FAILED_CONNECTION_REQUEST *
|
|
Network_Port_SC_Failed_Connection_Requests_Get(
|
|
uint32_t object_instance, uint8_t index)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return NULL;
|
|
}
|
|
|
|
if (index >= params->SC_Failed_Connection_Requests_Count) {
|
|
return NULL;
|
|
}
|
|
|
|
return ¶ms->SC_Failed_Connection_Requests[index];
|
|
}
|
|
|
|
bool Network_Port_SC_Failed_Connection_Requests_Add(
|
|
uint32_t object_instance,
|
|
BACNET_DATE_TIME *ts,
|
|
BACNET_HOST_N_PORT_DATA *peer_address,
|
|
uint8_t *peer_VMAC,
|
|
uint8_t *peer_UUID,
|
|
BACNET_ERROR_CODE error,
|
|
const char *error_details)
|
|
{
|
|
BACNET_SC_FAILED_CONNECTION_REQUEST *entry;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
if (params->SC_Failed_Connection_Requests_Count + 1 >
|
|
ARRAY_SIZE(params->SC_Failed_Connection_Requests)) {
|
|
return false;
|
|
}
|
|
|
|
entry = ¶ms->SC_Failed_Connection_Requests
|
|
[params->SC_Failed_Connection_Requests_Count];
|
|
params->SC_Failed_Connection_Requests_Count += 1;
|
|
|
|
entry->Timestamp = *ts;
|
|
memcpy(&entry->Peer_Address, peer_address, sizeof(entry->Peer_Address));
|
|
memcpy(entry->Peer_VMAC, peer_VMAC, sizeof(entry->Peer_VMAC));
|
|
memcpy(
|
|
entry->Peer_UUID.uuid.uuid128, peer_UUID,
|
|
sizeof(entry->Peer_UUID.uuid.uuid128));
|
|
entry->Error = error;
|
|
if (error_details) {
|
|
bsc_copy_str(
|
|
entry->Error_Details, error_details, sizeof(entry->Error_Details));
|
|
} else {
|
|
entry->Error_Details[0] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Network_Port_SC_Failed_Connection_Requests_Delete_All(
|
|
uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->SC_Failed_Connection_Requests_Count = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
int Network_Port_SC_Failed_Connection_Requests_Count(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return 0;
|
|
}
|
|
|
|
return params->SC_Failed_Connection_Requests_Count;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle a request to encode all the the entries
|
|
* @param object_instance [in] BACnet network port object instance number
|
|
* @param apdu [out] Buffer in which the APDU contents are built.
|
|
* @param max_apdu [in] Max length of the APDU buffer.
|
|
* @return How many bytes were encoded in the buffer, or
|
|
* BACNET_STATUS_ABORT if the response would not fit within the buffer.
|
|
*/
|
|
int Network_Port_SC_Failed_Connection_Requests_Encode(
|
|
uint32_t object_instance, uint8_t *apdu, int max_apdu)
|
|
{
|
|
BACNET_SC_FAILED_CONNECTION_REQUEST *entry = NULL;
|
|
int apdu_len = 0;
|
|
unsigned index = 0;
|
|
unsigned size = 0;
|
|
|
|
size = Network_Port_SC_Failed_Connection_Requests_Count(object_instance);
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Failed_Connection_Requests_Get(
|
|
object_instance, index);
|
|
apdu_len += bacapp_encode_SCFailedConnectionRequest(NULL, entry);
|
|
}
|
|
if (apdu_len > max_apdu) {
|
|
return BACNET_STATUS_ABORT;
|
|
}
|
|
apdu_len = 0;
|
|
for (index = 0; index < size; index++) {
|
|
entry = Network_Port_SC_Failed_Connection_Requests_Get(
|
|
object_instance, index);
|
|
apdu_len +=
|
|
bacapp_encode_SCFailedConnectionRequest(&apdu[apdu_len], entry);
|
|
}
|
|
|
|
return apdu_len;
|
|
}
|
|
|
|
uint32_t Network_Port_Certificate_Key_File(uint32_t object_instance)
|
|
{
|
|
uint32_t id = 0;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return 0;
|
|
}
|
|
|
|
id = params->Certificate_Key_File;
|
|
|
|
return id;
|
|
}
|
|
|
|
bool Network_Port_Certificate_Key_File_Set(
|
|
uint32_t object_instance, uint32_t value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
params->Certificate_Key_File = value;
|
|
|
|
return true;
|
|
}
|
|
|
|
const BACNET_UUID *Network_Port_SC_Local_UUID(uint32_t object_instance)
|
|
{
|
|
const BACNET_UUID *uuid = NULL;
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return NULL;
|
|
}
|
|
|
|
uuid = ¶ms->Local_UUID;
|
|
|
|
return uuid;
|
|
}
|
|
|
|
bool Network_Port_SC_Local_UUID_Set(
|
|
uint32_t object_instance, BACNET_UUID *value)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return false;
|
|
}
|
|
|
|
memcpy(¶ms->Local_UUID, value, sizeof(*value));
|
|
|
|
return true;
|
|
}
|
|
|
|
void Network_Port_SC_Pending_Params_Apply(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
if (!params) {
|
|
return;
|
|
}
|
|
|
|
params->Max_BVLC_Length_Accepted = params->Max_BVLC_Length_Accepted_dirty;
|
|
params->Max_NPDU_Length_Accepted = params->Max_NPDU_Length_Accepted_dirty;
|
|
params->SC_Minimum_Reconnect_Time = params->SC_Minimum_Reconnect_Time_dirty;
|
|
params->SC_Maximum_Reconnect_Time = params->SC_Maximum_Reconnect_Time_dirty;
|
|
params->SC_Connect_Wait_Timeout = params->SC_Connect_Wait_Timeout_dirty;
|
|
params->SC_Disconnect_Wait_Timeout =
|
|
params->SC_Disconnect_Wait_Timeout_dirty;
|
|
params->SC_Heartbeat_Timeout = params->SC_Heartbeat_Timeout_dirty;
|
|
|
|
#if BSC_CONF_HUB_FUNCTIONS_NUM != 0
|
|
memcpy(
|
|
params->SC_Primary_Hub_URI, params->SC_Primary_Hub_URI_dirty,
|
|
sizeof(params->SC_Primary_Hub_URI));
|
|
memcpy(
|
|
params->SC_Failover_Hub_URI, params->SC_Failover_Hub_URI_dirty,
|
|
sizeof(params->SC_Failover_Hub_URI));
|
|
|
|
params->SC_Hub_Function_Enable = params->SC_Hub_Function_Enable_dirty;
|
|
|
|
memcpy(
|
|
params->SC_Hub_Function_Accept_URIs,
|
|
params->SC_Hub_Function_Accept_URIs_dirty,
|
|
sizeof(params->SC_Hub_Function_Accept_URIs));
|
|
|
|
Network_Port_SC_Hub_Function_Binding_Set(
|
|
object_instance, params->SC_Hub_Function_Binding_dirty);
|
|
#endif /* BSC_CONF_HUB_FUNCTIONS_NUM!=0 */
|
|
|
|
#if BSC_CONF_HUB_CONNECTORS_NUM != 0
|
|
params->SC_Direct_Connect_Initiate_Enable =
|
|
params->SC_Direct_Connect_Initiate_Enable_dirty;
|
|
params->SC_Direct_Connect_Accept_Enable =
|
|
params->SC_Direct_Connect_Accept_Enable_dirty;
|
|
|
|
memcpy(
|
|
params->SC_Direct_Connect_Accept_URIs,
|
|
params->SC_Direct_Connect_Accept_URIs_dirty,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs));
|
|
|
|
Network_Port_SC_Direct_Connect_Binding_Set(
|
|
object_instance, params->SC_Direct_Connect_Binding_dirty);
|
|
#endif /* BSC_CONF_HUB_CONNECTORS_NUM!=0 */
|
|
}
|
|
|
|
void Network_Port_SC_Pending_Params_Discard(uint32_t object_instance)
|
|
{
|
|
BACNET_SC_PARAMS *params = Network_Port_SC_Params(object_instance);
|
|
uint16_t port = 0;
|
|
char *ifname = NULL;
|
|
|
|
if (!params) {
|
|
return;
|
|
}
|
|
params->Max_BVLC_Length_Accepted_dirty = params->Max_BVLC_Length_Accepted;
|
|
params->Max_NPDU_Length_Accepted_dirty = params->Max_NPDU_Length_Accepted;
|
|
params->SC_Minimum_Reconnect_Time_dirty = params->SC_Minimum_Reconnect_Time;
|
|
params->SC_Maximum_Reconnect_Time_dirty = params->SC_Maximum_Reconnect_Time;
|
|
params->SC_Connect_Wait_Timeout_dirty = params->SC_Connect_Wait_Timeout;
|
|
params->SC_Disconnect_Wait_Timeout_dirty =
|
|
params->SC_Disconnect_Wait_Timeout;
|
|
params->SC_Heartbeat_Timeout_dirty = params->SC_Heartbeat_Timeout;
|
|
#if BSC_CONF_HUB_FUNCTIONS_NUM != 0
|
|
memcpy(
|
|
params->SC_Primary_Hub_URI_dirty, params->SC_Primary_Hub_URI,
|
|
sizeof(params->SC_Primary_Hub_URI_dirty));
|
|
memcpy(
|
|
params->SC_Failover_Hub_URI_dirty, params->SC_Failover_Hub_URI,
|
|
sizeof(params->SC_Failover_Hub_URI_dirty));
|
|
|
|
params->SC_Hub_Function_Enable_dirty = params->SC_Hub_Function_Enable;
|
|
|
|
memcpy(
|
|
params->SC_Hub_Function_Accept_URIs_dirty,
|
|
params->SC_Hub_Function_Accept_URIs,
|
|
sizeof(params->SC_Hub_Function_Accept_URIs));
|
|
|
|
Network_Port_SC_Hub_Function_Binding_get(object_instance, &port, &ifname);
|
|
snprintf(
|
|
params->SC_Hub_Function_Binding_dirty,
|
|
sizeof(params->SC_Hub_Function_Binding_dirty), "%s:%d", ifname, port);
|
|
#else
|
|
(void)port;
|
|
(void)ifname;
|
|
#endif /* BSC_CONF_HUB_FUNCTIONS_NUM!=0 */
|
|
|
|
#if BSC_CONF_HUB_CONNECTORS_NUM != 0
|
|
params->SC_Direct_Connect_Initiate_Enable_dirty =
|
|
params->SC_Direct_Connect_Initiate_Enable;
|
|
params->SC_Direct_Connect_Accept_Enable_dirty =
|
|
params->SC_Direct_Connect_Accept_Enable;
|
|
|
|
memcpy(
|
|
params->SC_Direct_Connect_Accept_URIs_dirty,
|
|
params->SC_Direct_Connect_Accept_URIs,
|
|
sizeof(params->SC_Direct_Connect_Accept_URIs));
|
|
|
|
Network_Port_SC_Direct_Connect_Binding_get(object_instance, &port, &ifname);
|
|
snprintf(
|
|
params->SC_Direct_Connect_Binding_dirty,
|
|
sizeof(params->SC_Direct_Connect_Binding_dirty), "%s:%d", ifname, port);
|
|
#endif /* BSC_CONF_HUB_CONNECTORS_NUM!=0 */
|
|
}
|