Modified the WhoIs demo to use BBMD if configured for BACnet/IP. Corrected the BVLC code.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<CodeBlocks_workspace_file>
|
<CodeBlocks_workspace_file>
|
||||||
<Workspace title="Workspace">
|
<Workspace title="Workspace">
|
||||||
<Project filename="epics\bacepics.cbp" />
|
<Project filename="epics\bacepics.cbp" />
|
||||||
<Project filename="..\lib\bacnet.cbp" />
|
<Project filename="..\lib\bacnet.cbp" active="1" />
|
||||||
<Project filename="server\bacserv.cbp" active="1" />
|
<Project filename="server\bacserv.cbp" />
|
||||||
</Workspace>
|
</Workspace>
|
||||||
</CodeBlocks_workspace_file>
|
</CodeBlocks_workspace_file>
|
||||||
|
|||||||
@@ -14,9 +14,6 @@
|
|||||||
<Compiler>
|
<Compiler>
|
||||||
<Add option="-g" />
|
<Add option="-g" />
|
||||||
</Compiler>
|
</Compiler>
|
||||||
<Linker>
|
|
||||||
<Add library="ws2_32" />
|
|
||||||
</Linker>
|
|
||||||
</Target>
|
</Target>
|
||||||
<Target title="Release">
|
<Target title="Release">
|
||||||
<Option output="bin\Release\bacrp" prefix_auto="1" extension_auto="1" />
|
<Option output="bin\Release\bacrp" prefix_auto="1" extension_auto="1" />
|
||||||
@@ -43,6 +40,7 @@
|
|||||||
</Compiler>
|
</Compiler>
|
||||||
<Linker>
|
<Linker>
|
||||||
<Add library="..\..\lib\libbacnet.a" />
|
<Add library="..\..\lib\libbacnet.a" />
|
||||||
|
<Add library="ws2_32" />
|
||||||
</Linker>
|
</Linker>
|
||||||
<Unit filename="main.c">
|
<Unit filename="main.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ int main(
|
|||||||
if (pEnv) {
|
if (pEnv) {
|
||||||
datalink_set(pEnv));
|
datalink_set(pEnv));
|
||||||
} else {
|
} else {
|
||||||
datalink_set("bip");
|
datalink_set(NULL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACDL_BIP)
|
#if defined(BACDL_BIP)
|
||||||
pEnv = getenv("BACNET_IP_PORT");
|
pEnv = getenv("BACNET_IP_PORT");
|
||||||
@@ -183,6 +184,7 @@ int main(
|
|||||||
if (elapsed_seconds) {
|
if (elapsed_seconds) {
|
||||||
last_seconds = current_seconds;
|
last_seconds = current_seconds;
|
||||||
dcc_timer_seconds(elapsed_seconds);
|
dcc_timer_seconds(elapsed_seconds);
|
||||||
|
bvlc_maintenance_timer(elapsed_seconds);
|
||||||
Load_Control_State_Machine_Handler();
|
Load_Control_State_Machine_Handler();
|
||||||
elapsed_milliseconds = elapsed_seconds * 1000;
|
elapsed_milliseconds = elapsed_seconds * 1000;
|
||||||
handler_cov_task(elapsed_seconds);
|
handler_cov_task(elapsed_seconds);
|
||||||
|
|||||||
@@ -146,10 +146,17 @@ int main(
|
|||||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
unsigned timeout = 100; /* milliseconds */
|
unsigned timeout = 100; /* milliseconds */
|
||||||
|
time_t total_seconds = 0;
|
||||||
time_t elapsed_seconds = 0;
|
time_t elapsed_seconds = 0;
|
||||||
time_t last_seconds = 0;
|
time_t last_seconds = 0;
|
||||||
time_t current_seconds = 0;
|
time_t current_seconds = 0;
|
||||||
time_t timeout_seconds = 0;
|
time_t timeout_seconds = 0;
|
||||||
|
char *pEnv = NULL;
|
||||||
|
#if defined(BACDL_BIP) && BBMD_ENABLED
|
||||||
|
long bbmd_port = 0xBAC0;
|
||||||
|
long bbmd_address = 0;
|
||||||
|
long bbmd_timetolive_seconds = 60000;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf
|
printf
|
||||||
@@ -189,8 +196,47 @@ int main(
|
|||||||
/* setup my info */
|
/* setup my info */
|
||||||
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||||
Init_Service_Handlers();
|
Init_Service_Handlers();
|
||||||
if (!datalink_init(getenv("BACNET_IFACE")))
|
#if defined(BACDL_BIP)
|
||||||
|
pEnv = getenv("BACNET_IP_PORT");
|
||||||
|
if (pEnv) {
|
||||||
|
bip_set_port(strtol(pEnv, NULL, 0));
|
||||||
|
} else {
|
||||||
|
bip_set_port(0xBAC0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!datalink_init(getenv("BACNET_IFACE"))) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
#if defined(BACDL_BIP) && BBMD_ENABLED
|
||||||
|
pEnv = getenv("BACNET_BBMD_PORT");
|
||||||
|
if (pEnv) {
|
||||||
|
bbmd_port = strtol(pEnv, NULL, 0);
|
||||||
|
if (bbmd_port > 0xFFFF) {
|
||||||
|
bbmd_port = 0xBAC0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pEnv = getenv("BACNET_BBMD_TIMETOLIVE");
|
||||||
|
if (pEnv) {
|
||||||
|
bbmd_timetolive_seconds = strtol(pEnv, NULL, 0);
|
||||||
|
if (bbmd_timetolive_seconds > 0xFFFF) {
|
||||||
|
bbmd_timetolive_seconds = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pEnv = getenv("BACNET_BBMD_ADDRESS");
|
||||||
|
if (pEnv) {
|
||||||
|
bbmd_address = bip_getaddrbyname(pEnv);
|
||||||
|
if (bbmd_address) {
|
||||||
|
struct in_addr addr;
|
||||||
|
addr.s_addr = bbmd_address;
|
||||||
|
printf("WhoIs: Registering with BBMD at %s:%ld\n",
|
||||||
|
inet_ntoa(addr),bbmd_port);
|
||||||
|
bvlc_register_with_bbmd(
|
||||||
|
bbmd_address,
|
||||||
|
bbmd_port,
|
||||||
|
bbmd_timetolive_seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* configure the timeout values */
|
/* configure the timeout values */
|
||||||
last_seconds = time(NULL);
|
last_seconds = time(NULL);
|
||||||
timeout_seconds = Device_APDU_Timeout() / 1000;
|
timeout_seconds = Device_APDU_Timeout() / 1000;
|
||||||
@@ -209,8 +255,12 @@ int main(
|
|||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
elapsed_seconds += (current_seconds - last_seconds);
|
elapsed_seconds = current_seconds - last_seconds;
|
||||||
if (elapsed_seconds > timeout_seconds)
|
if (elapsed_seconds) {
|
||||||
|
bvlc_maintenance_timer(elapsed_seconds);
|
||||||
|
}
|
||||||
|
total_seconds += elapsed_seconds;
|
||||||
|
if (total_seconds > timeout_seconds)
|
||||||
break;
|
break;
|
||||||
/* keep track of time for next check */
|
/* keep track of time for next check */
|
||||||
last_seconds = current_seconds;
|
last_seconds = current_seconds;
|
||||||
|
|||||||
@@ -110,6 +110,14 @@ extern "C" {
|
|||||||
uint32_t bip_get_broadcast_addr(
|
uint32_t bip_get_broadcast_addr(
|
||||||
void);
|
void);
|
||||||
|
|
||||||
|
/* gets an IP address by name, where name can be a
|
||||||
|
string that is an IP address in dotted form, or
|
||||||
|
a name that is a domain name
|
||||||
|
returns 0 if not found, or
|
||||||
|
an IP address in network byte order */
|
||||||
|
long bip_getaddrbyname(const char *host_name);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -45,6 +45,18 @@ extern "C" {
|
|||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#if BBMD_ENABLED
|
||||||
|
void bvlc_maintenance_timer(
|
||||||
|
unsigned seconds);
|
||||||
|
#else
|
||||||
|
#define bvlc_maintenance_timer(x)
|
||||||
|
#endif
|
||||||
|
/* registers with a bbmd as a foreign device */
|
||||||
|
void bvlc_register_with_bbmd(
|
||||||
|
long bbmd_address, /* in network byte order */
|
||||||
|
uint16_t bbmd_port,
|
||||||
|
uint16_t time_to_live_seconds);
|
||||||
|
|
||||||
uint16_t bvlc_receive(
|
uint16_t bvlc_receive(
|
||||||
BACNET_ADDRESS * src, /* returns the source address */
|
BACNET_ADDRESS * src, /* returns the source address */
|
||||||
uint8_t * npdu, /* returns the NPDU */
|
uint8_t * npdu, /* returns the NPDU */
|
||||||
|
|||||||
@@ -68,9 +68,7 @@
|
|||||||
|
|
||||||
#elif defined(BACDL_BIP)
|
#elif defined(BACDL_BIP)
|
||||||
#include "bip.h"
|
#include "bip.h"
|
||||||
#ifdef BBMD_ENABLED
|
|
||||||
#include "bvlc.h"
|
#include "bvlc.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#define datalink_init bip_init
|
#define datalink_init bip_init
|
||||||
#ifdef BBMD_ENABLED
|
#ifdef BBMD_ENABLED
|
||||||
|
|||||||
@@ -40,6 +40,21 @@
|
|||||||
|
|
||||||
bool BIP_Debug = false;
|
bool BIP_Debug = false;
|
||||||
|
|
||||||
|
/* gets an IP address by name, where name can be a
|
||||||
|
string that is an IP address in dotted form, or
|
||||||
|
a name that is a domain name
|
||||||
|
returns 0 if not found, or
|
||||||
|
an IP address in network byte order */
|
||||||
|
long bip_getaddrbyname(const char *host_name)
|
||||||
|
{
|
||||||
|
struct hostent *host_ent;
|
||||||
|
|
||||||
|
if ((host_ent = gethostbyname(host_name)) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return *(long *) host_ent->h_addr;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_local_ifr_ioctl(
|
static int get_local_ifr_ioctl(
|
||||||
char *ifname,
|
char *ifname,
|
||||||
struct ifreq *ifr,
|
struct ifreq *ifr,
|
||||||
|
|||||||
@@ -41,6 +41,22 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
bool BIP_Debug = false;
|
bool BIP_Debug = false;
|
||||||
|
|
||||||
|
/* gets an IP address by name, where name can be a
|
||||||
|
string that is an IP address in dotted form, or
|
||||||
|
a name that is a domain name
|
||||||
|
returns 0 if not found, or
|
||||||
|
an IP address in network byte order */
|
||||||
|
long bip_getaddrbyname(const char *host_name)
|
||||||
|
{
|
||||||
|
struct hostent *host_ent;
|
||||||
|
|
||||||
|
if ((host_ent = gethostbyname(host_name)) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return *(long *) host_ent->h_addr;
|
||||||
|
}
|
||||||
|
|
||||||
/* To fill a need, we invent the gethostaddr() function. */
|
/* To fill a need, we invent the gethostaddr() function. */
|
||||||
static long gethostaddr(
|
static long gethostaddr(
|
||||||
void)
|
void)
|
||||||
|
|||||||
+31
-13
@@ -119,6 +119,24 @@ uint16_t bip_get_port(
|
|||||||
return BIP_Port;
|
return BIP_Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bip_decode_bip_address(
|
||||||
|
uint8_t * pdu, /* buffer to extract encoded address */
|
||||||
|
struct in_addr *address, /* in host format */
|
||||||
|
uint16_t * port)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
uint32_t raw_address = 0;
|
||||||
|
|
||||||
|
if (pdu) {
|
||||||
|
(void) decode_unsigned32(&pdu[0], &raw_address);
|
||||||
|
address->s_addr = raw_address;
|
||||||
|
(void) decode_unsigned16(&pdu[4], port);
|
||||||
|
len = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/* function to send a packet out the BACnet/IP socket (Annex J) */
|
/* function to send a packet out the BACnet/IP socket (Annex J) */
|
||||||
/* returns number of bytes sent on success, negative number on failure */
|
/* returns number of bytes sent on success, negative number on failure */
|
||||||
int bip_send_pdu(
|
int bip_send_pdu(
|
||||||
@@ -131,6 +149,10 @@ int bip_send_pdu(
|
|||||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
int bytes_sent = 0;
|
int bytes_sent = 0;
|
||||||
|
/* addr and port in host format */
|
||||||
|
struct in_addr address;
|
||||||
|
uint16_t port = 0;
|
||||||
|
|
||||||
|
|
||||||
(void) npdu_data;
|
(void) npdu_data;
|
||||||
/* assumes that the driver has already been initialized */
|
/* assumes that the driver has already been initialized */
|
||||||
@@ -141,22 +163,19 @@ int bip_send_pdu(
|
|||||||
bip_dest.sin_family = AF_INET;
|
bip_dest.sin_family = AF_INET;
|
||||||
if (dest->net == BACNET_BROADCAST_NETWORK) {
|
if (dest->net == BACNET_BROADCAST_NETWORK) {
|
||||||
/* broadcast */
|
/* broadcast */
|
||||||
bip_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr);
|
address.s_addr = BIP_Broadcast_Address.s_addr;
|
||||||
bip_dest.sin_port = htons(BIP_Port);
|
port = BIP_Port;
|
||||||
memset(&(bip_dest.sin_zero), '\0', 8);
|
|
||||||
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||||
} else if (dest->mac_len == 6) {
|
} else if (dest->mac_len == 6) {
|
||||||
/* valid unicast */
|
bip_decode_bip_address(&dest->mac[0], &address, &port);
|
||||||
(void) decode_unsigned32(&dest->mac[0],
|
|
||||||
(uint32_t *) & (bip_dest.sin_addr.s_addr));
|
|
||||||
(void) decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
|
|
||||||
memset(&(bip_dest.sin_zero), '\0', 8);
|
|
||||||
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
||||||
} else {
|
} else {
|
||||||
/* invalid address */
|
/* invalid address */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
bip_dest.sin_addr.s_addr = htonl(address.s_addr);
|
||||||
|
bip_dest.sin_port = htons(port);
|
||||||
|
memset(&(bip_dest.sin_zero), '\0', 8);
|
||||||
mtu_len = 2;
|
mtu_len = 2;
|
||||||
mtu_len +=
|
mtu_len +=
|
||||||
encode_unsigned16(&mtu[mtu_len],
|
encode_unsigned16(&mtu[mtu_len],
|
||||||
@@ -237,11 +256,10 @@ uint16_t bip_receive(
|
|||||||
fprintf(stderr,"BIP: src is me. Discarded!\n");
|
fprintf(stderr,"BIP: src is me. Discarded!\n");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* copy the source address
|
/* copy the source address - into host format */
|
||||||
FIXME: IPv6? */
|
|
||||||
src->mac_len = 6;
|
src->mac_len = 6;
|
||||||
(void) encode_unsigned32(&src->mac[0], sin.sin_addr.s_addr);
|
(void) encode_unsigned32(&src->mac[0], htonl(sin.sin_addr.s_addr));
|
||||||
(void) encode_unsigned16(&src->mac[4], sin.sin_port);
|
(void) encode_unsigned16(&src->mac[4], htons(sin.sin_port));
|
||||||
/* FIXME: check destination address */
|
/* FIXME: check destination address */
|
||||||
/* see if it is broadcast or for us */
|
/* see if it is broadcast or for us */
|
||||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||||
|
|||||||
+50
-33
@@ -44,7 +44,6 @@
|
|||||||
BACnet Broadcast Management Device,
|
BACnet Broadcast Management Device,
|
||||||
Broadcast Distribution Table, and
|
Broadcast Distribution Table, and
|
||||||
Foreign Device Registration */
|
Foreign Device Registration */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* true if valid entry - false if not */
|
/* true if valid entry - false if not */
|
||||||
bool valid;
|
bool valid;
|
||||||
@@ -107,6 +106,12 @@ void bvlc_maintenance_timer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Addressing within B/IP Networks
|
||||||
|
In the case of B/IP networks, six octets consisting of the four-octet
|
||||||
|
IP address followed by a two-octet UDP port number (both of
|
||||||
|
which shall be transmitted most significant octet first).
|
||||||
|
Note: for local storage, the storage order is host byte order.
|
||||||
|
Note: BACnet unsigned is encoded as most significant octet. */
|
||||||
int bvlc_encode_bip_address(
|
int bvlc_encode_bip_address(
|
||||||
uint8_t * pdu, /* buffer to store encoding */
|
uint8_t * pdu, /* buffer to store encoding */
|
||||||
struct in_addr *address, /* in host format */
|
struct in_addr *address, /* in host format */
|
||||||
@@ -264,14 +269,15 @@ int bvlc_encode_read_bdt_ack(
|
|||||||
return pdu_len;
|
return pdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int bvlc_encode_forwarded_npdu(
|
int bvlc_encode_forwarded_npdu(
|
||||||
uint8_t * pdu,
|
uint8_t * pdu,
|
||||||
BACNET_ADDRESS * src,
|
struct sockaddr_in *sin, /* the source address */
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
unsigned npdu_length)
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
struct in_addr address;
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
unsigned i; /* for loop counter */
|
unsigned i; /* for loop counter */
|
||||||
|
|
||||||
@@ -283,10 +289,11 @@ int bvlc_encode_forwarded_npdu(
|
|||||||
length field itself, most significant octet first. */
|
length field itself, most significant octet first. */
|
||||||
encode_unsigned16(&pdu[2], 4 + 6 + npdu_length);
|
encode_unsigned16(&pdu[2], 4 + 6 + npdu_length);
|
||||||
len = 4;
|
len = 4;
|
||||||
for (i = 0; i < 6; i++) {
|
address.s_addr = ntohl(sin->sin_addr.s_addr);
|
||||||
pdu[len] = src->adr[i];
|
port = ntohs(sin->sin_port);
|
||||||
len++;
|
len += bvlc_encode_bip_address(&pdu[len],
|
||||||
}
|
&address,
|
||||||
|
port);
|
||||||
for (i = 0; i < npdu_length; i++) {
|
for (i = 0; i < npdu_length; i++) {
|
||||||
pdu[len] = npdu[i];
|
pdu[len] = npdu[i];
|
||||||
len++;
|
len++;
|
||||||
@@ -390,7 +397,6 @@ int bvlc_encode_read_fdt_ack(
|
|||||||
return pdu_len;
|
return pdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int bvlc_encode_delete_fdt_entry(
|
int bvlc_encode_delete_fdt_entry(
|
||||||
uint8_t * pdu,
|
uint8_t * pdu,
|
||||||
struct in_addr *address,
|
struct in_addr *address,
|
||||||
@@ -462,7 +468,6 @@ int bvlc_encode_original_unicast_npdu(
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int bvlc_encode_original_broadcast_npdu(
|
int bvlc_encode_original_broadcast_npdu(
|
||||||
uint8_t * pdu,
|
uint8_t * pdu,
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
@@ -640,14 +645,12 @@ void bvlc_bdt_forward_npdu(
|
|||||||
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;
|
||||||
BACNET_ADDRESS src;
|
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
/* assumes that the driver has already been initialized */
|
||||||
if (bip_socket() < 0) {
|
if (bip_socket() < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bvlc_internet_to_bacnet_address(&src, sin);
|
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, npdu_length);
|
||||||
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], &src, 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 */
|
||||||
@@ -699,14 +702,12 @@ void bvlc_fdt_forward_npdu(
|
|||||||
int bytes_sent = 0;
|
int bytes_sent = 0;
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
struct sockaddr_in bvlc_dest;
|
struct sockaddr_in bvlc_dest;
|
||||||
BACNET_ADDRESS src;
|
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
/* assumes that the driver has already been initialized */
|
||||||
if (bip_socket() < 0) {
|
if (bip_socket() < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bvlc_internet_to_bacnet_address(&src, sin);
|
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, max_npdu);
|
||||||
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], &src, npdu, max_npdu);
|
|
||||||
/* load destination IP address */
|
/* load destination IP address */
|
||||||
bvlc_dest.sin_family = AF_INET;
|
bvlc_dest.sin_family = AF_INET;
|
||||||
/* loop through the FDT and send one to each entry */
|
/* loop through the FDT and send one to each entry */
|
||||||
@@ -748,6 +749,23 @@ void bvlc_send_mpdu(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bvlc_register_with_bbmd(
|
||||||
|
long bbmd_address, /* in network byte order */
|
||||||
|
uint16_t bbmd_port, /* in host byte order */
|
||||||
|
uint16_t time_to_live_seconds)
|
||||||
|
{
|
||||||
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
|
int mtu_len = 0;
|
||||||
|
struct sockaddr_in dest;
|
||||||
|
|
||||||
|
dest.sin_addr.s_addr = bbmd_address;
|
||||||
|
dest.sin_port = htons(bbmd_port);
|
||||||
|
mtu_len = bvlc_encode_register_foreign_device(
|
||||||
|
&mtu[0],
|
||||||
|
time_to_live_seconds);
|
||||||
|
bvlc_send_mpdu(&dest, &mtu[0], mtu_len);
|
||||||
|
}
|
||||||
|
|
||||||
void bvlc_send_result(
|
void bvlc_send_result(
|
||||||
struct sockaddr_in *dest, /* the destination address */
|
struct sockaddr_in *dest, /* the destination address */
|
||||||
BACNET_BVLC_RESULT result_code)
|
BACNET_BVLC_RESULT result_code)
|
||||||
@@ -789,12 +807,12 @@ int bvlc_send_fdt(
|
|||||||
return mtu_len;
|
return mtu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bvlc_broadcast_address_same(
|
static bool bvlc_address_same(
|
||||||
struct sockaddr_in * sin)
|
struct sockaddr_in * sin) /* network order address */
|
||||||
{ /* network order address */
|
{
|
||||||
bool same = false;
|
bool same = false;
|
||||||
|
|
||||||
if ((sin->sin_addr.s_addr == htonl(bip_get_broadcast_addr())) &&
|
if ((sin->sin_addr.s_addr == htonl(bip_get_addr())) &&
|
||||||
(sin->sin_port == htons(bip_get_port()))) {
|
(sin->sin_port == htons(bip_get_port()))) {
|
||||||
same = true;
|
same = true;
|
||||||
}
|
}
|
||||||
@@ -815,6 +833,7 @@ uint16_t bvlc_receive(
|
|||||||
int max = 0;
|
int max = 0;
|
||||||
struct timeval select_timeout;
|
struct timeval select_timeout;
|
||||||
struct sockaddr_in sin = { -1 };
|
struct sockaddr_in sin = { -1 };
|
||||||
|
struct sockaddr_in original_sin = { -1 };
|
||||||
struct sockaddr_in dest = { -1 };
|
struct sockaddr_in dest = { -1 };
|
||||||
socklen_t sin_len = sizeof(sin);
|
socklen_t sin_len = sizeof(sin);
|
||||||
int function_type = 0;
|
int function_type = 0;
|
||||||
@@ -933,26 +952,24 @@ uint16_t bvlc_receive(
|
|||||||
BACnet devices may omit the broadcast using the B/IP
|
BACnet devices may omit the broadcast using the B/IP
|
||||||
broadcast address. The method by which a BBMD determines whether
|
broadcast address. The method by which a BBMD determines whether
|
||||||
or not other BACnet devices are present is a local matter. */
|
or not other BACnet devices are present is a local matter. */
|
||||||
/* if this was received via Broadcast, don't broadcast it */
|
/* decode the 4 byte original address and 2 byte port */
|
||||||
/* FIXME: how do I know if I received a unicast or broadcast? */
|
bvlc_decode_bip_address(&npdu[4],
|
||||||
npdu_len -= 6; /* FIXME: very ugly */
|
&original_sin.sin_addr,
|
||||||
if (!bvlc_broadcast_address_same(&sin)) {
|
&original_sin.sin_port);
|
||||||
|
npdu_len =- 6;
|
||||||
|
/* Broadcast it if this was received via unicast */
|
||||||
|
if (bvlc_address_same(&sin)) {
|
||||||
dest.sin_addr.s_addr = htonl(bip_get_broadcast_addr());
|
dest.sin_addr.s_addr = htonl(bip_get_broadcast_addr());
|
||||||
dest.sin_port = htons(bip_get_port());
|
dest.sin_port = htons(bip_get_port());
|
||||||
bvlc_send_mpdu(&dest, &npdu[4], npdu_len);
|
bvlc_send_mpdu(&dest, &npdu[4+6], npdu_len);
|
||||||
}
|
}
|
||||||
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
|
bvlc_fdt_forward_npdu(&sin, &npdu[4+6], npdu_len);
|
||||||
/* Extract the "real" source from the BVLC header */
|
/* use the original source from the BVLC header */
|
||||||
for (i = 0; i < 6; i++) {
|
bvlc_internet_to_bacnet_address(src, &original_sin);
|
||||||
src->mac[i] = npdu[4 + i];
|
|
||||||
}
|
|
||||||
src->mac_len = 6;
|
|
||||||
src->net = 0;
|
|
||||||
src->len = 0;
|
|
||||||
if (npdu_len < max_npdu) {
|
if (npdu_len < max_npdu) {
|
||||||
/* shift the buffer to return a valid PDU */
|
/* shift the buffer to return a valid PDU */
|
||||||
for (i = 0; i < npdu_len; i++) {
|
for (i = 0; i < npdu_len; i++) {
|
||||||
npdu[i] = npdu[10 + i];
|
npdu[i] = npdu[4+6+i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* ignore packets that are too large */
|
/* ignore packets that are too large */
|
||||||
|
|||||||
Reference in New Issue
Block a user