Cleaned up format of source code.
This commit is contained in:
+180
-114
@@ -43,15 +43,15 @@
|
|||||||
BACnet Broadcast Management Device,
|
BACnet Broadcast Management Device,
|
||||||
Broadcast Distribution Table, and
|
Broadcast Distribution Table, and
|
||||||
Foreign Device Registration */
|
Foreign Device Registration */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
/* true if valid entry - false if not */
|
/* true if valid entry - false if not */
|
||||||
bool valid;
|
bool valid;
|
||||||
/* true if valid entry - false if not */
|
|
||||||
/* BACnet/IP address */
|
/* BACnet/IP address */
|
||||||
struct in_addr dest_address;
|
struct in_addr dest_address;
|
||||||
|
/* BACnet/IP port number - not always 47808=BAC0h */
|
||||||
uint16_t dest_port;
|
uint16_t dest_port;
|
||||||
struct in_addr dest_address;
|
|
||||||
/* Broadcast Distribution Mask - stored in host byte order */
|
/* Broadcast Distribution Mask - stored in host byte order */
|
||||||
struct in_addr broadcast_mask;
|
struct in_addr broadcast_mask;
|
||||||
} BBMD_TABLE_ENTRY;
|
} BBMD_TABLE_ENTRY;
|
||||||
@@ -68,136 +68,174 @@ seconds remaining before the BBMD will purge the registrant's FDT
|
|||||||
entry if no re-registration occurs. This value will be initialized
|
entry if no re-registration occurs. This value will be initialized
|
||||||
to the 2-octet Time-to-Live value supplied at the time of
|
to the 2-octet Time-to-Live value supplied at the time of
|
||||||
registration.*/
|
registration.*/
|
||||||
seconds remaining before the BBMD will purge the registrant's FDT
|
typedef struct
|
||||||
|
{
|
||||||
bool valid;
|
bool valid;
|
||||||
to the 2-octet Time-to-Live value supplied at the time of
|
|
||||||
/* BACnet/IP address */
|
/* BACnet/IP address */
|
||||||
struct in_addr dest_address;
|
struct in_addr dest_address;
|
||||||
|
/* BACnet/IP port number - not always 47808=BAC0h */
|
||||||
uint16_t dest_port;
|
uint16_t dest_port;
|
||||||
|
|
||||||
/* seconds for valid entry lifetime */
|
/* seconds for valid entry lifetime */
|
||||||
uint16_t time_to_live;
|
uint16_t time_to_live;
|
||||||
|
/* our counter */
|
||||||
time_t seconds_remaining; /* includes 30 second grace period */
|
time_t seconds_remaining; /* includes 30 second grace period */
|
||||||
} FD_TABLE_ENTRY;
|
} FD_TABLE_ENTRY;
|
||||||
|
|
||||||
#define MAX_FD_ENTRIES 128
|
#define MAX_FD_ENTRIES 128
|
||||||
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
|
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
|
||||||
|
|
||||||
void bvlc_maintenance_timer(unsigned seconds)
|
void bvlc_maintenance_timer(unsigned seconds)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
time_t seconds_remaining; /* includes 30 second grace period */
|
|
||||||
|
|
||||||
} FD_TABLE_ENTRY;
|
|
||||||
|
|
||||||
#define MAX_FD_ENTRIES 128
|
|
||||||
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
|
|
||||||
|
|
||||||
|
|
||||||
void bvlc_maintenance_timer(unsigned seconds)
|
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||||
|
if (FD_Table[i].valid) {
|
||||||
|
if (FD_Table[i].seconds_remaining) {
|
||||||
|
if (FD_Table[i].seconds_remaining < seconds) {
|
||||||
|
FD_Table[i].seconds_remaining = 0;
|
||||||
|
} else {
|
||||||
FD_Table[i].seconds_remaining -= seconds;
|
FD_Table[i].seconds_remaining -= seconds;
|
||||||
|
}
|
||||||
unsigned i = 0;
|
if (FD_Table[i].seconds_remaining == 0) {
|
||||||
FD_Table[i].valid = false;
|
FD_Table[i].valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
|
||||||
|
int bvlc_encode_bip_address(
|
||||||
|
uint8_t * pdu, /* buffer to store encoding */
|
||||||
|
struct in_addr *address, /* in host format */
|
||||||
uint16_t port)
|
uint16_t port)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
len = encode_unsigned32(&pdu[0], address->s_addr);
|
len = encode_unsigned32(&pdu[0], address->s_addr);
|
||||||
len += encode_unsigned16(&pdu[len], port);
|
len += encode_unsigned16(&pdu[len], port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
int bvlc_decode_bip_address(
|
||||||
|
uint8_t * pdu, /* buffer to extract encoded address */
|
||||||
|
struct in_addr * address, /* in host format */
|
||||||
uint16_t * port)
|
uint16_t * port)
|
||||||
{
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (pdu) {
|
||||||
|
(void) decode_unsigned32(&pdu[0], &(address.s_addr));
|
||||||
|
(void) decode_unsigned16(&pdu[4], &port);
|
||||||
|
len = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* used for both read and write entries */
|
/* used for both read and write entries */
|
||||||
int bvlc_encode_address_entry(uint8_t * pdu,
|
int bvlc_encode_address_entry(uint8_t * pdu,
|
||||||
|
struct in_addr *address,
|
||||||
|
uint16_t port,
|
||||||
|
struct in_addr *mask)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
len = bvlc_encode_bip_address(pdu, address, port);
|
len = bvlc_encode_bip_address(pdu, address, port);
|
||||||
len += encode_unsigned32(&pdu[len], mask->s_addr);
|
len += encode_unsigned32(&pdu[len], mask->s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
int bvlc_encode_bvlc_result(
|
||||||
|
uint8_t * pdu,
|
||||||
BACNET_BVLC_RESULT result_code)
|
BACNET_BVLC_RESULT result_code)
|
||||||
{
|
{
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_RESULT;
|
pdu[1] = BVLC_RESULT;
|
||||||
uint8_t * pdu,
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 6);
|
encode_unsigned16(&pdu[2], 6);
|
||||||
encode_unsigned16(&pdu[4], result_code);
|
encode_unsigned16(&pdu[4], result_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bvlc_encode_write_bdt_init(
|
||||||
|
uint8_t * pdu,
|
||||||
|
unsigned entries)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE;
|
pdu[1] = BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE;
|
||||||
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
||||||
len = 4;
|
len = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
struct in_addr *address, /* in host format */
|
|
||||||
|
int bvlc_encode_read_bdt(
|
||||||
|
uint8_t * pdu)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE;
|
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE;
|
||||||
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4);
|
encode_unsigned16(&pdu[2], 4);
|
||||||
len = 4;
|
len = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bvlc_encode_read_bdt_ack_init(
|
||||||
|
uint8_t * pdu,
|
||||||
|
unsigned entries)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK;
|
pdu[1] = BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK;
|
||||||
len += encode_unsigned32(&pdu[len], mask->s_addr);
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
||||||
len = 4;
|
len = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bvlc_encode_forwarded_npdu(uint8_t * pdu,
|
int bvlc_encode_forwarded_npdu(uint8_t * pdu,
|
||||||
int bvlc_encode_bvlc_result(uint8_t * pdu,
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t * npdu,
|
||||||
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
unsigned i; /* for loop counter */
|
unsigned i; /* for loop counter */
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_FORWARDED_NPDU;
|
pdu[1] = BVLC_FORWARDED_NPDU;
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
@@ -212,16 +250,19 @@ int bvlc_encode_address_entry(uint8_t * pdu,
|
|||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int bvlc_encode_register_foreign_device(uint8_t * pdu,
|
int bvlc_encode_register_foreign_device(uint8_t * pdu,
|
||||||
uint16_t time_to_live_seconds)
|
uint16_t time_to_live_seconds)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE;
|
pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE;
|
||||||
int len = 0;
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
@@ -229,67 +270,79 @@ int bvlc_encode_address_entry(uint8_t * pdu,
|
|||||||
encode_unsigned16(&pdu[2], time_to_live_seconds);
|
encode_unsigned16(&pdu[2], time_to_live_seconds);
|
||||||
len = 6;
|
len = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
of the entire BVLL message, including the two octets of the
|
|
||||||
|
int bvlc_encode_read_fdt(
|
||||||
|
uint8_t * pdu)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
|
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
|
||||||
}
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4);
|
encode_unsigned16(&pdu[2], 4);
|
||||||
len = 4;
|
len = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
uint8_t * pdu)
|
|
||||||
|
int bvlc_encode_read_fdt_ack_init(
|
||||||
|
uint8_t * pdu,
|
||||||
|
unsigned entries)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
|
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
|
||||||
if (pdu) {
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
encode_unsigned16(&pdu[2], 4 + entries * 10);
|
||||||
len = 4;
|
len = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
encode_unsigned16(&pdu[2], 4);
|
|
||||||
|
int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
|
||||||
|
struct in_addr *address,
|
||||||
uint16_t port)
|
uint16_t port)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
|
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE;
|
||||||
return len;
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 10);
|
encode_unsigned16(&pdu[2], 10);
|
||||||
int bvlc_encode_read_bdt_ack_init(
|
|
||||||
/* FDT Entry */
|
/* FDT Entry */
|
||||||
encode_unsigned32(&pdu[0], address->s_addr);
|
encode_unsigned32(&pdu[0], address->s_addr);
|
||||||
encode_unsigned16(&pdu[4], port);
|
encode_unsigned16(&pdu[4], port);
|
||||||
len = 10;
|
len = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
|
int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
|
||||||
|
uint8_t * npdu,
|
||||||
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
int len = 0; /* return value */
|
int len = 0; /* return value */
|
||||||
unsigned i; /* for loop counter */
|
unsigned i; /* for loop counter */
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
|
pdu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
|
||||||
length field itself, most significant octet first. */
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
@@ -299,17 +352,20 @@ int bvlc_encode_address_entry(uint8_t * pdu,
|
|||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bvlc_encode_original_unicast_npdu(uint8_t * pdu,
|
||||||
|
uint8_t * npdu,
|
||||||
unsigned npdu_length)
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
int len = 0; /* return value */
|
int len = 0; /* return value */
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
pdu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
||||||
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
@@ -319,17 +375,21 @@ int bvlc_encode_address_entry(uint8_t * pdu,
|
|||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
length field itself, most significant octet first. */
|
|
||||||
|
|
||||||
|
int bvlc_encode_original_broadcast_npdu(uint8_t * pdu,
|
||||||
|
uint8_t * npdu,
|
||||||
unsigned npdu_length)
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
int len = 0; /* return value */
|
int len = 0; /* return value */
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
|
|
||||||
if (pdu) {
|
if (pdu) {
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
pdu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||||
|
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
/* The 2-octet BVLC Length field is the length, in octets,
|
||||||
of the entire BVLL message, including the two octets of the
|
of the entire BVLL message, including the two octets of the
|
||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
@@ -339,98 +399,110 @@ int bvlc_encode_address_entry(uint8_t * pdu,
|
|||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
/* copy the source internet address to the BACnet address */
|
/* copy the source internet address to the BACnet address */
|
||||||
/* FIXME: IPv6? */
|
/* FIXME: IPv6? */
|
||||||
/* FIXME: is sockaddr_in host or network order? */
|
/* FIXME: is sockaddr_in host or network order? */
|
||||||
|
void bvlc_internet_to_bacnet_address(
|
||||||
|
BACNET_ADDRESS * src, /* returns the BACnet source address */
|
||||||
struct sockaddr_in *sin)
|
struct sockaddr_in *sin)
|
||||||
{ /* source internet address */
|
{ /* source internet address */
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int bvlc_encode_register_foreign_device(uint8_t * pdu,
|
|
||||||
|
if (src && sin) {
|
||||||
len = encode_unsigned32(&src->mac[0], sin->sin_addr.s_addr);
|
len = encode_unsigned32(&src->mac[0], sin->sin_addr.s_addr);
|
||||||
len += encode_unsigned16(&src->mac[4], sin->sin_port);
|
len += encode_unsigned16(&src->mac[4], sin->sin_port);
|
||||||
src->mac_len = len;
|
src->mac_len = len;
|
||||||
src->net = 0;
|
src->net = 0;
|
||||||
src->len = 0;
|
src->len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* copy the source internet address to the BACnet address */
|
/* copy the source internet address to the BACnet address */
|
||||||
/* FIXME: IPv6? */
|
/* FIXME: IPv6? */
|
||||||
/* FIXME: is sockaddr_in host or network order? */
|
/* FIXME: is sockaddr_in host or network order? */
|
||||||
of the entire BVLL message, including the two octets of the
|
void bvlc_bacnet_to_internet_address(
|
||||||
length field itself, most significant octet first. */
|
struct sockaddr_in *sin, /* source internet address */
|
||||||
encode_unsigned16(&pdu[2], 6);
|
BACNET_ADDRESS * src) /* returns the BACnet source address */
|
||||||
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
encode_unsigned16(&pdu[2], time_to_live_seconds);
|
|
||||||
|
if (src && sin) {
|
||||||
len = 6;
|
if (src->mac_len == 6) {
|
||||||
|
|
||||||
len = decode_unsigned32(&src->mac[0], &sin->sin_addr.s_addr);
|
len = decode_unsigned32(&src->mac[0], &sin->sin_addr.s_addr);
|
||||||
len += decode_unsigned16(&src->mac[4], &sin->sin_port);
|
len += decode_unsigned16(&src->mac[4], &sin->sin_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bvlc_bdt_forward_npdu(
|
||||||
|
struct sockaddr_in *sin, /* the source address */
|
||||||
uint8_t * npdu, /* the NPDU */
|
uint8_t * npdu, /* the NPDU */
|
||||||
uint16_t npdu_length)
|
uint16_t npdu_length)
|
||||||
{ /* length of the NPDU */
|
{ /* length of the NPDU */
|
||||||
{
|
uint8_t mtu[MAX_MPDU] = {0};
|
||||||
|
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
int bytes_sent = 0;
|
int bytes_sent = 0;
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
struct sockaddr_in bip_dest;
|
struct sockaddr_in bip_dest;
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
/* assumes that the driver has already been initialized */
|
||||||
|
if (bip_socket() < 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
mtu_len = bvlc_encode_forwarded_npdu(
|
||||||
of the entire BVLL message, including the two octets of the
|
&mtu[0],
|
||||||
|
sin,
|
||||||
|
npdu,
|
||||||
|
npdu_length);
|
||||||
/* load destination IP address */
|
/* load destination IP address */
|
||||||
bip_dest.sin_family = AF_INET;
|
bip_dest.sin_family = AF_INET;
|
||||||
|
|
||||||
/* loop through the BDT and send one to each entry, except us */
|
/* loop through the BDT and send one to each entry, except us */
|
||||||
|
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
||||||
}
|
if (BBMD_Table[i].valid) {
|
||||||
|
|
||||||
|
|
||||||
return len;
|
|
||||||
/* The B/IP address to which the Forwarded-NPDU message is
|
/* The B/IP address to which the Forwarded-NPDU message is
|
||||||
sent is formed by inverting the broadcast distribution
|
sent is formed by inverting the broadcast distribution
|
||||||
mask in the BDT entry and logically ORing it with the
|
mask in the BDT entry and logically ORing it with the
|
||||||
BBMD address of the same entry. */
|
BBMD address of the same entry. */
|
||||||
bip_dest.sin_addr.s_addr =
|
bip_dest.sin_addr.s_addr =
|
||||||
uint8_t * pdu,
|
htonl(((~BBMD_Table[i].broadcast_mask.s_addr) |
|
||||||
unsigned entries)
|
BBMD_Table[i].dest_address.s_addr));
|
||||||
bip_dest.sin_port = htons(BBMD_Table[i].dest_port);
|
bip_dest.sin_port = htons(BBMD_Table[i].dest_port);
|
||||||
|
|
||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
bytes_sent =
|
bytes_sent =
|
||||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
||||||
if (pdu) {
|
(struct sockaddr *) bip_dest,
|
||||||
|
sizeof(struct sockaddr));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bytes_sent;
|
return bytes_sent;
|
||||||
}
|
}
|
||||||
pdu[1] = BVLC_READ_FOREIGN_DEVICE_TABLE_ACK;
|
|
||||||
|
void bvlc_fdt_forward_npdu(
|
||||||
|
struct sockaddr_in *sin, /* the source address */
|
||||||
uint8_t * npdu, /* returns the NPDU */
|
uint8_t * npdu, /* returns the NPDU */
|
||||||
/* The 2-octet BVLC Length field is the length, in octets,
|
uint16_t max_npdu) /* amount of space available in the NPDU */
|
||||||
of the entire BVLL message, including the two octets of the
|
{
|
||||||
|
|
||||||
|
/* FIXME: add the code */
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bvlc_handler(
|
||||||
|
BACNET_ADDRESS * src, /* returns the source address */
|
||||||
uint8_t * npdu, /* returns the NPDU */
|
uint8_t * npdu, /* returns the NPDU */
|
||||||
uint16_t max_npdu, /* amount of space available in the NPDU */
|
uint16_t max_npdu, /* amount of space available in the NPDU */
|
||||||
|
unsigned timeout) /* number of milliseconds to wait for a packet */
|
||||||
int received_bytes;
|
int received_bytes;
|
||||||
|
{
|
||||||
}
|
uint8_t buf[MAX_MPDU] = {0}; /* data */
|
||||||
uint16_t pdu_len = 0; /* return value */
|
uint16_t pdu_len = 0; /* return value */
|
||||||
fd_set read_fds;
|
fd_set read_fds;
|
||||||
int max;
|
int max;
|
||||||
@@ -440,8 +512,9 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
int function_type = 0;
|
int function_type = 0;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
|
if (BIP_Socket < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* we could just use a non-blocking socket, but that consumes all
|
/* we could just use a non-blocking socket, but that consumes all
|
||||||
the CPU time. We can use a timeout; it is only supported as
|
the CPU time. We can use a timeout; it is only supported as
|
||||||
@@ -457,41 +530,37 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
FD_ZERO(&read_fds);
|
FD_ZERO(&read_fds);
|
||||||
FD_SET((unsigned int) BIP_Socket, &read_fds);
|
FD_SET((unsigned int) BIP_Socket, &read_fds);
|
||||||
max = BIP_Socket;
|
max = BIP_Socket;
|
||||||
|
|
||||||
/* see if there is a packet for us */
|
/* see if there is a packet for us */
|
||||||
encode_unsigned32(&pdu[0], address->s_addr);
|
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||||
|
received_bytes = recvfrom(
|
||||||
encode_unsigned16(&pdu[4], port);
|
BIP_Socket,
|
||||||
|
(char *) &buf[0],
|
||||||
|
MAX_MPDU, 0,
|
||||||
(struct sockaddr *) &sin, &sin_len);
|
(struct sockaddr *) &sin, &sin_len);
|
||||||
len = 10;
|
} else {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
/* See if there is a problem */
|
/* See if there is a problem */
|
||||||
if (received_bytes < 0) {
|
if (received_bytes < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no problem, just no bytes */
|
/* no problem, just no bytes */
|
||||||
int bvlc_encode_distribute_broadcast_to_network(uint8_t * pdu,
|
if (received_bytes == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
uint8_t * npdu,
|
}
|
||||||
/* the signature of a BACnet/IP packet */
|
/* the signature of a BACnet/IP packet */
|
||||||
{
|
if (buf[0] != BVLL_TYPE_BACNET_IP) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
function_type = buf[1];
|
function_type = buf[1];
|
||||||
|
|
||||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||||
(void) decode_unsigned16(&buf[2], &npdu_len);
|
(void) decode_unsigned16(&buf[2], &npdu_len);
|
||||||
|
|
||||||
/* subtract off the BVLC header */
|
/* subtract off the BVLC header */
|
||||||
npdu_len -= 4;
|
npdu_len -= 4;
|
||||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
switch (function_type) {
|
||||||
|
|
||||||
case BVLC_RESULT:
|
case BVLC_RESULT:
|
||||||
break;
|
break;
|
||||||
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
|
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
|
||||||
of the entire BVLL message, including the two octets of the
|
|
||||||
/* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
|
/* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
|
||||||
message, a BBMD shall attempt to create or replace its BDT,
|
message, a BBMD shall attempt to create or replace its BDT,
|
||||||
depending on whether or not a BDT has previously existed.
|
depending on whether or not a BDT has previously existed.
|
||||||
@@ -506,7 +575,6 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
|
case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
|
||||||
break;
|
break;
|
||||||
case BVLC_FORWARDED_NPDU:
|
case BVLC_FORWARDED_NPDU:
|
||||||
return len;
|
|
||||||
/* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
|
/* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
|
||||||
process it according to whether it was received from a peer
|
process it according to whether it was received from a peer
|
||||||
BBMD as the result of a directed broadcast or a unicast
|
BBMD as the result of a directed broadcast or a unicast
|
||||||
@@ -541,26 +609,22 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
|
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
|
||||||
break;
|
break;
|
||||||
case BVLC_ORIGINAL_UNICAST_NPDU:
|
case BVLC_ORIGINAL_UNICAST_NPDU:
|
||||||
}
|
|
||||||
/* ignore messages from me */
|
/* ignore messages from me */
|
||||||
|
if (sin.sin_addr.s_addr == BIP_Address.s_addr) {
|
||||||
npdu_len = 0;
|
npdu_len = 0;
|
||||||
|
} else {
|
||||||
}
|
|
||||||
bvlc_internet_to_bacnet_address(src, &sin);
|
bvlc_internet_to_bacnet_address(src, &sin);
|
||||||
|
if (npdu_len < max_npdu) {
|
||||||
/* copy the buffer into the PDU */
|
/* copy the buffer into the PDU */
|
||||||
uint8_t * npdu,
|
|
||||||
memmove(&npdu[0], &buf[4], npdu_len);
|
memmove(&npdu[0], &buf[4], npdu_len);
|
||||||
unsigned npdu_length)
|
} else {
|
||||||
/* ignore packets that are too large */
|
/* ignore packets that are too large */
|
||||||
/* clients should check my max-apdu first */
|
/* clients should check my max-apdu first */
|
||||||
int len = 0; /* return value */
|
|
||||||
npdu_len = 0;
|
npdu_len = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BVLC_ORIGINAL_BROADCAST_NPDU:
|
case BVLC_ORIGINAL_BROADCAST_NPDU:
|
||||||
if (pdu) {
|
|
||||||
/* Upon receipt of a BVLL Original-Broadcast-NPDU message,
|
/* Upon receipt of a BVLL Original-Broadcast-NPDU message,
|
||||||
a BBMD shall construct a BVLL Forwarded-NPDU message and
|
a BBMD shall construct a BVLL Forwarded-NPDU message and
|
||||||
send it to each IP subnet in its BDT with the exception
|
send it to each IP subnet in its BDT with the exception
|
||||||
@@ -575,16 +639,14 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
shall be sent directly to each foreign device currently in
|
shall be sent directly to each foreign device currently in
|
||||||
the BBMD's FDT also using the BVLL Forwarded-NPDU message. */
|
the BBMD's FDT also using the BVLL Forwarded-NPDU message. */
|
||||||
bvlc_internet_to_bacnet_address(src, &sin);
|
bvlc_internet_to_bacnet_address(src, &sin);
|
||||||
len++;
|
if (npdu_len < max_npdu) {
|
||||||
/* copy the buffer into the PDU */
|
/* copy the buffer into the PDU */
|
||||||
}
|
|
||||||
memmove(&npdu[0], &buf[4], npdu_len);
|
memmove(&npdu[0], &buf[4], npdu_len);
|
||||||
}
|
} else {
|
||||||
/* ignore packets that are too large */
|
/* ignore packets that are too large */
|
||||||
/* clients should check my max-apdu first */
|
/* clients should check my max-apdu first */
|
||||||
return len;
|
|
||||||
npdu_len = 0;
|
npdu_len = 0;
|
||||||
}
|
}
|
||||||
/* if BDT or FDT entries exist, Forward the NPDU */
|
/* if BDT or FDT entries exist, Forward the NPDU */
|
||||||
bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len);
|
bvlc_bdt_forward_npdu(&sin, &buf[4], npdu_len);
|
||||||
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
|
bvlc_fdt_forward_npdu(&sin, &buf[4], npdu_len);
|
||||||
@@ -592,6 +654,7 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return npdu_len;
|
return npdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,24 +662,27 @@ void bvlc_bacnet_to_internet_address(
struct sockaddr_in *sin, /* source intern
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
|
void testBVLC(Test * pTest)
|
||||||
|
{
|
||||||
(void) pTest;
|
(void) pTest;
|
||||||
}
|
}
|
||||||
#ifdef TEST_BBMD
|
#ifdef TEST_BBMD
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
Test * pTest;
|
Test * pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
src->mac_len = len;
|
|
||||||
|
|
||||||
|
pTest = ct_create("BACnet Virtual Link Control", NULL);
|
||||||
/* individual tests */
|
/* individual tests */
|
||||||
rc = ct_addTestFunction(pTest, testBVLC);
|
rc = ct_addTestFunction(pTest, testBVLC);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
|
|
||||||
/* configure output */
|
/* configure output */
|
||||||
ct_setStream(pTest, stdout);
|
ct_setStream(pTest, stdout);
|
||||||
ct_run(pTest);
|
ct_run(pTest);
|
||||||
(void) ct_report(pTest);
|
(void) ct_report(pTest);
|
||||||
ct_destroy(pTest);
|
ct_destroy(pTest);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user