refactor BACnet Address utility functions (#390)

* refactor BACnet Address utility functions

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-02-04 08:46:31 -06:00
committed by GitHub
parent 85976ee1f8
commit 236c2d1003
17 changed files with 490 additions and 221 deletions
+188 -27
View File
@@ -34,12 +34,20 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "bacnet/config.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacint.h"
#include "bacnet/bacaddr.h"
/** @file bacaddr.c BACnet Address structure utilities */
/**
* @brief Copy a #BACNET_ADDRESS value to another
* @param dest - #BACNET_ADDRESS to be copied into
* @param src - #BACNET_ADDRESS to be copied from
*/
void bacnet_address_copy(BACNET_ADDRESS *dest, BACNET_ADDRESS *src)
{
int i = 0;
@@ -57,45 +65,198 @@ void bacnet_address_copy(BACNET_ADDRESS *dest, BACNET_ADDRESS *src)
}
}
/**
* @brief Compare two #BACNET_ADDRESS values
* @param dest - #BACNET_ADDRESS to be compared
* @param src - #BACNET_ADDRESS to be compared
* @return true if the same values
*/
bool bacnet_address_same(BACNET_ADDRESS *dest, BACNET_ADDRESS *src)
{
uint8_t i = 0; /* loop counter */
uint8_t max_len = 0; /* used for dynamic max */
if (dest == src) { /* same ? */
if (!dest || !src) {
return false;
}
if (dest == src) {
return true;
}
if (dest->net != src->net) {
if (dest->mac_len != src->mac_len) {
return false;
}
if (dest->len != src->len) {
return false;
}
max_len = dest->len;
if (max_len > MAX_MAC_LEN) {
max_len = MAX_MAC_LEN;
}
for (i = 0; i < max_len; i++) {
if (dest->adr[i] != src->adr[i]) {
return false;
}
}
if (dest->net == 0) {
if (dest->mac_len != src->mac_len) {
return false;
}
max_len = dest->mac_len;
if (max_len > MAX_MAC_LEN) {
max_len = MAX_MAC_LEN;
}
for (i = 0; i < max_len; i++) {
for (i = 0; i < MAX_MAC_LEN; i++) {
if (i < dest->mac_len) {
if (dest->mac[i] != src->mac[i]) {
return false;
}
}
}
if (dest->net != src->net) {
return false;
}
/* if local, ignore remaining fields */
if (dest->net == 0) {
return true;
}
if (dest->len != src->len) {
return false;
}
for (i = 0; i < MAX_MAC_LEN; i++) {
if (i < dest->len) {
if (dest->adr[i] != src->adr[i]) {
return false;
}
}
}
return true;
}
/**
* @brief Configure a #BACNET_ADDRESS from mac, dnet, and adr
* @param dest - #BACNET_ADDRESS to be configured
* @param mac - #BACNET_MAC_ADDRESS used in configuration
* @param dnet - remote network number 0..65535 (0=local, 65535=broadcast)
* @param adr - #BACNET_MAC_ADDRESS behind the remote network
* @return true if configured
*/
bool bacnet_address_init(BACNET_ADDRESS *dest,
BACNET_MAC_ADDRESS *mac,
uint16_t dnet,
BACNET_MAC_ADDRESS *adr)
{
uint8_t i = 0; /* loop counter */
if (!dest) {
return false;
}
if (adr && adr->len && mac && mac->len) {
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->mac[i] = mac->adr[i];
}
dest->mac_len = mac->len;
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = adr->adr[i];
}
dest->len = adr->len;
dest->net = dnet;
} else if (mac && mac->len) {
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->mac[i] = mac->adr[i];
}
dest->mac_len = mac->len;
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
dest->len = 0;
dest->net = dnet;
} else {
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->mac[i] = 0;
}
dest->mac_len = mac->len;
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
dest->len = 0;
dest->net = dnet;
}
return true;
}
/**
* @brief Compare two #BACNET_MAC_ADDRESS values
* @param dest - #BACNET_MAC_ADDRESS to be compared
* @param src - #BACNET_MAC_ADDRESS to be compared
* @return true if the same values
*/
bool bacnet_address_mac_same(BACNET_MAC_ADDRESS *dest, BACNET_MAC_ADDRESS *src)
{
uint8_t i = 0; /* loop counter */
if (!dest || !src) {
return false;
}
if (dest->len != src->len) {
return false;
}
for (i = 0; i < MAX_MAC_LEN; i++) {
if (i < dest->len) {
if (dest->adr[i] != src->adr[i]) {
return false;
}
}
}
return true;
}
/**
* @brief Initialize a BACNET_MAC_ADDRESS
* @param mac [out] BACNET_MAC_ADDRESS structure
* @param adr [in] address to initialize, null if empty
* @param len [in] length of address in bytes
*/
void bacnet_address_mac_init(BACNET_MAC_ADDRESS *mac, uint8_t *adr, uint8_t len)
{
uint8_t i = 0;
if (mac) {
if (adr && (len <= sizeof(mac->adr))) {
for (i = 0; i < len; i++) {
mac->adr[i] = adr[i];
}
mac->len = len;
} else {
mac->len = 0;
}
}
}
/**
* @brief Parse an ASCII string for a bacnet-address
* @param mac [out] BACNET_MAC_ADDRESS structure to store the results
* @param arg [in] nul terminated ASCII string to parse
* @return true if the address was parsed
*/
bool bacnet_address_mac_from_ascii(BACNET_MAC_ADDRESS *mac, const char *arg)
{
unsigned a[6] = { 0 }, p = 0;
uint16_t port = 0;
int c, i;
bool status = false;
if (!(mac && arg)) {
return false;
}
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0], &a[1], &a[2], &a[3], &p);
if ((c == 4) || (c == 5)) {
mac->adr[0] = a[0];
mac->adr[1] = a[1];
mac->adr[2] = a[2];
mac->adr[3] = a[3];
if (c == 4) {
port = 0xBAC0U;
} else {
port = (uint16_t)p;
}
encode_unsigned16(&mac->adr[4], port);
mac->len = 6;
status = true;
} else {
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x", &a[0], &a[1], &a[2], &a[3],
&a[4], &a[5]);
if (c > 0) {
for (i = 0; i < c; i++) {
mac->adr[i] = a[i];
}
mac->len = c;
status = true;
}
}
return status;
}
+40 -30
View File
@@ -1,26 +1,26 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef BACADDR_H
#define BACADDR_H
@@ -34,14 +34,24 @@
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
void bacnet_address_copy(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src);
BACNET_STACK_EXPORT
bool bacnet_address_same(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src);
BACNET_STACK_EXPORT
void bacnet_address_copy(BACNET_ADDRESS *dest, BACNET_ADDRESS *src);
BACNET_STACK_EXPORT
bool bacnet_address_same(BACNET_ADDRESS *dest, BACNET_ADDRESS *src);
BACNET_STACK_EXPORT
bool bacnet_address_init(BACNET_ADDRESS *dest,
BACNET_MAC_ADDRESS *mac,
uint16_t dnet,
BACNET_MAC_ADDRESS *adr);
BACNET_STACK_EXPORT
bool bacnet_address_mac_same(
BACNET_MAC_ADDRESS *dest, BACNET_MAC_ADDRESS *src);
BACNET_STACK_EXPORT
void bacnet_address_mac_init(
BACNET_MAC_ADDRESS *mac, uint8_t *adr, uint8_t len);
BACNET_STACK_EXPORT
bool bacnet_address_mac_from_ascii(BACNET_MAC_ADDRESS *mac, const char *arg);
#ifdef __cplusplus
}
+2 -126
View File
@@ -120,60 +120,6 @@ void address_own_device_id_set(uint32_t own_id)
Own_Device_ID = own_id;
}
/**
* @brief Check if the given source and destination address can be matched
* by checking the length, net and MAC address.
*
* @param dest Destination address
* @param src Source address
*
* @return true for a match, false otherwise
*/
bool address_match(BACNET_ADDRESS *dest, BACNET_ADDRESS *src)
{
uint8_t i = 0;
uint8_t max_len = 0;
if (dest == src) {
return (true);
}
if (dest->mac_len != src->mac_len) {
return false;
}
max_len = dest->mac_len;
if (max_len > MAX_MAC_LEN) {
max_len = MAX_MAC_LEN;
}
for (i = 0; i < max_len; i++) {
if (dest->mac[i] != src->mac[i]) {
return false;
}
}
if (dest->net != src->net) {
return false;
}
/* if local, ignore remaining fields */
if (dest->net == 0) {
return true;
}
if (dest->len != src->len) {
return false;
}
max_len = dest->len;
if (max_len > MAX_MAC_LEN) {
max_len = MAX_MAC_LEN;
}
for (i = 0; i < max_len; i++) {
if (dest->adr[i] != src->adr[i]) {
return false;
}
}
return true;
}
/**
* @brief Remove a device from the address list.
*
@@ -268,76 +214,6 @@ static struct Address_Cache_Entry *address_remove_oldest(void)
return (pCandidate);
}
/**
* Initialize a BACNET_MAC_ADDRESS
*
* @param mac [out] BACNET_MAC_ADDRESS structure
* @param adr [in] address to initialize, null if empty
* @param len [in] length of address in bytes
*/
void address_mac_init(BACNET_MAC_ADDRESS *mac, uint8_t *adr, uint8_t len)
{
uint8_t i = 0;
if (mac) {
if (adr && (len <= sizeof(mac->adr))) {
for (i = 0; i < len; i++) {
mac->adr[i] = adr[i];
}
mac->len = len;
} else {
mac->len = 0;
}
}
}
/** Parse an ASCII string for a bacnet-address
*
* @param mac [out] BACNET_MAC_ADDRESS structure to store the results
* @param arg [in] nul terminated ASCII string to parse
*
* @return true if the address was parsed
*/
bool address_mac_from_ascii(BACNET_MAC_ADDRESS *mac, const char *arg)
{
unsigned a[6] = { 0 }, p = 0;
uint16_t port = 0;
int c, i;
bool status = false;
if (!(mac && arg)) {
return false;
}
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0], &a[1], &a[2], &a[3], &p);
if ((c == 4) || (c == 5)) {
mac->adr[0] = a[0];
mac->adr[1] = a[1];
mac->adr[2] = a[2];
mac->adr[3] = a[3];
if (c == 4) {
port = 0xBAC0U;
} else {
port = (uint16_t)p;
}
encode_unsigned16(&mac->adr[4], port);
mac->len = 6;
status = true;
} else {
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x", &a[0], &a[1], &a[2], &a[3],
&a[4], &a[5]);
if (c > 0) {
for (i = 0; i < c; i++) {
mac->adr[i] = a[i];
}
mac->len = c;
status = true;
}
}
return status;
}
#ifdef BACNET_ADDRESS_CACHE_FILE
/* File format:
DeviceID MAC SNET SADR MAX-APDU
@@ -367,7 +243,7 @@ static void address_file_init(const char *pFilename)
if (sscanf(line, "%7ld %79s %5u %79s %4u", &device_id,
&mac_string[0], &snet, &sadr_string[0],
&max_apdu) == 5) {
if (address_mac_from_ascii(&mac, mac_string)) {
if (bacnet_address_mac_from_ascii(&mac, mac_string)) {
src.mac_len = mac.len;
for (index = 0; index < MAX_MAC_LEN; index++) {
src.mac[index] = mac.adr[index];
@@ -375,7 +251,7 @@ static void address_file_init(const char *pFilename)
}
src.net = (uint16_t)snet;
if (snet) {
if (address_mac_from_ascii(&mac, sadr_string)) {
if (bacnet_address_mac_from_ascii(&mac, sadr_string)) {
src.len = mac.len;
for (index = 0; index < MAX_MAC_LEN; index++) {
src.adr[index] = mac.adr[index];
+6 -16
View File
@@ -29,8 +29,14 @@
#include <stdbool.h>
#include "bacnet/bacnet_stack_exports.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacaddr.h"
#include "bacnet/readrange.h"
/* refactored utility functions - see bacaddr.c module */
#define address_mac_init(m,a,l) bacnet_address_mac_init(m,a,l)
#define address_mac_from_ascii(m,a) bacnet_address_mac_from_ascii(m,a)
#define address_match(d,s) bacnet_address_same(d,s)
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -83,11 +89,6 @@ extern "C" {
unsigned address_count(
void);
BACNET_STACK_EXPORT
bool address_match(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src);
BACNET_STACK_EXPORT
bool address_bind_request(
uint32_t device_id,
@@ -127,17 +128,6 @@ extern "C" {
void address_cache_timer(
uint16_t uSeconds);
BACNET_STACK_EXPORT
void address_mac_init(
BACNET_MAC_ADDRESS *mac,
uint8_t *adr,
uint8_t len);
BACNET_STACK_EXPORT
bool address_mac_from_ascii(
BACNET_MAC_ADDRESS *mac,
const char *arg);
BACNET_STACK_EXPORT
void address_protected_entry_index_set(uint32_t top_protected_entry_index);
BACNET_STACK_EXPORT