Added more functionality to BVLC (untested and uncompiled), and corrected BIP.
This commit is contained in:
@@ -215,9 +215,10 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
if ((pdu[1] == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
||||
(pdu[1] == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
||||
/* ignore messages from me */
|
||||
if (sin.sin_addr.s_addr == htonl(BIP_Address.s_addr))
|
||||
if ((sin.sin_addr.s_addr == htonl(BIP_Address.s_addr)) &&
|
||||
(sin.sin_port == htonl(BIP_Port))) {
|
||||
pdu_len = 0;
|
||||
else {
|
||||
} else {
|
||||
/* copy the source address
|
||||
FIXME: IPv6? */
|
||||
src->mac_len = 6;
|
||||
|
||||
+380
-38
@@ -85,6 +85,9 @@ typedef struct
|
||||
#define MAX_FD_ENTRIES 128
|
||||
static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
|
||||
|
||||
/* result from a client request */
|
||||
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
||||
|
||||
void bvlc_maintenance_timer(unsigned seconds)
|
||||
{
|
||||
unsigned i = 0;
|
||||
@@ -225,6 +228,42 @@ int bvlc_encode_read_bdt_ack_init(
|
||||
return len;
|
||||
}
|
||||
|
||||
int bvlc_encode_read_bdt_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t max_pdu)
|
||||
{
|
||||
int pdu_len = 0; /* return value */
|
||||
int len = 0;
|
||||
unsigned count = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
||||
if (BBMD_Table[i].valid) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
len = bvlc_encode_read_bdt_ack_init(&pdu[0],count);
|
||||
pdu_len += len;
|
||||
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
||||
if (BBMD_Table[i].valid) {
|
||||
/* too much to send */
|
||||
if ((pdu_len+10) > max_pdu) {
|
||||
pdu_len = 0;
|
||||
break;
|
||||
}
|
||||
len = bvlc_encode_address_entry(
|
||||
&pdu[pdu_len],
|
||||
&BBMD_Table[i].dest_address,
|
||||
BBMD_Table[i].dest_port,
|
||||
&BBMD_Table[i].broadcast_mask);
|
||||
pdu_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
|
||||
int bvlc_encode_forwarded_npdu(uint8_t * pdu,
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * npdu,
|
||||
@@ -255,7 +294,6 @@ int bvlc_encode_forwarded_npdu(uint8_t * pdu,
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int bvlc_encode_register_foreign_device(uint8_t * pdu,
|
||||
uint16_t time_to_live_seconds)
|
||||
{
|
||||
@@ -268,7 +306,7 @@ int bvlc_encode_register_foreign_device(uint8_t * pdu,
|
||||
of the entire BVLL message, including the two octets of the
|
||||
length field itself, most significant octet first. */
|
||||
encode_unsigned16(&pdu[2], 6);
|
||||
encode_unsigned16(&pdu[2], time_to_live_seconds);
|
||||
encode_unsigned16(&pdu[4], time_to_live_seconds);
|
||||
len = 6;
|
||||
}
|
||||
|
||||
@@ -312,6 +350,45 @@ int bvlc_encode_read_fdt_ack_init(
|
||||
return len;
|
||||
}
|
||||
|
||||
int bvlc_encode_read_fdt_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t max_pdu)
|
||||
{
|
||||
int pdu_len = 0; /* return value */
|
||||
int len = 0;
|
||||
unsigned count = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||
if (FD_Table[i].valid) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
len = bvlc_encode_read_fdt_ack_init(&pdu[0],count);
|
||||
pdu_len += len;
|
||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||
if (FD_Table[i].valid) {
|
||||
/* too much to send */
|
||||
if ((pdu_len+10) > max_pdu) {
|
||||
pdu_len = 0;
|
||||
break;
|
||||
}
|
||||
len = bvlc_encode_bip_address(
|
||||
&pdu[pdu_len],
|
||||
&FD_Table[i].dest_address,
|
||||
FD_Table[i].dest_port);
|
||||
pdu_len += len;
|
||||
encode_unsigned16(&pdu[pdu_len], FD_Table[i].time_to_live);
|
||||
pdu_len += len;
|
||||
encode_unsigned16(&pdu[pdu_len], FD_Table[i].seconds_remaining);
|
||||
pdu_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
|
||||
int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
|
||||
struct in_addr *address,
|
||||
uint16_t port)
|
||||
@@ -326,8 +403,8 @@ int bvlc_encode_delete_fdt_entry(uint8_t * pdu,
|
||||
length field itself, most significant octet first. */
|
||||
encode_unsigned16(&pdu[2], 10);
|
||||
/* FDT Entry */
|
||||
encode_unsigned32(&pdu[0], address->s_addr);
|
||||
encode_unsigned16(&pdu[4], port);
|
||||
encode_unsigned32(&pdu[4], address->s_addr);
|
||||
encode_unsigned16(&pdu[8], port);
|
||||
len = 10;
|
||||
}
|
||||
|
||||
@@ -450,6 +527,95 @@ void bvlc_bacnet_to_internet_address(
|
||||
return;
|
||||
}
|
||||
|
||||
bool bvlc_create_bdt(
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_length)
|
||||
{
|
||||
bool status = false;
|
||||
struct in_addr dest_address;
|
||||
uint16_t dest_port;
|
||||
unsigned i = 0;
|
||||
|
||||
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
||||
if (npdu_length >= 10) {
|
||||
BBMD_Table[i].valid = true;
|
||||
decode_unsigned32(&pdu[0], &dest_address.s_addr);
|
||||
BBMD_Table[i].dest_address.s_addr = ntohl(dest_address.s_addr);
|
||||
decode_unsigned16(&pdu[4], &dest_port);
|
||||
BBMD_Table[i].dest_port = ntohs(dest_port);
|
||||
decode_unsigned32(&pdu[6], &dest_address.s_addr);
|
||||
BBMD_Table[i].broadcast_mask.s_addr = ntohl(dest_address.s_addr);
|
||||
npdu_length -= 10;
|
||||
} else {
|
||||
BBMD_Table[i].valid = false;
|
||||
BBMD_Table[i].dest_address.s_addr = 0;
|
||||
BBMD_Table[i].dest_port = 0;
|
||||
BBMD_Table[i].broadcast_mask = 0;
|
||||
}
|
||||
}
|
||||
/* did they all fit? */
|
||||
if (npdu_length < 10) {
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool bvlc_register_foreign_device(
|
||||
struct sockaddr_in *sin, /* the source address */
|
||||
uint16_t time_to_live) /* time in seconds */
|
||||
{
|
||||
unsigned i = 0;
|
||||
bool status = false;
|
||||
|
||||
/* am I here already? If so, update my time to live... */
|
||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||
if (FD_Table[i].valid) {
|
||||
if ((FD_Table[i].dest_address.s_addr == ntohl(sin->sin_addr.s_addr)) &&
|
||||
(FD_Table[i].dest_port == ntohs(sin->sin_port))) {
|
||||
status = true;
|
||||
FD_Table[i].time_to_live = time_to_live;
|
||||
FD_Table[i].seconds_remaining = time_to_live + 30;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||
if (!FD_Table[i].valid) {
|
||||
FD_Table[i].dest_address.s_addr = ntohl(sin->sin_addr.s_addr);
|
||||
FD_Table[i].dest_port = ntohs(sin->sin_port);
|
||||
FD_Table[i].time_to_live = time_to_live;
|
||||
FD_Table[i].seconds_remaining = time_to_live + 30;
|
||||
FD_Table[i].valid = true;
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool bvlc_delete_foreign_device(uint8_t * pdu)
|
||||
{
|
||||
struct sockaddr_in sin; /* the ip address */
|
||||
uint16_t port; /* the decoded port */
|
||||
bool status = false; /* return value */
|
||||
|
||||
bvlc_decode_bip_address(pdu, &sin, &port);
|
||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||
if (FD_Table[i].valid) {
|
||||
if ((FD_Table[i].dest_address.s_addr == sin.sin_addr.s_addr) &&
|
||||
(FD_Table[i].dest_port == sin.sin_port)) {
|
||||
FD_Table[i].valid = false;
|
||||
FD_Table[i].seconds_remaining = 0;
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void bvlc_bdt_forward_npdu(
|
||||
struct sockaddr_in *sin, /* the source address */
|
||||
uint8_t * npdu, /* the NPDU */
|
||||
@@ -547,6 +713,85 @@ void bvlc_fdt_forward_npdu(
|
||||
return;
|
||||
}
|
||||
|
||||
void bvlc_send_mpdu(
|
||||
struct sockaddr_in *dest, /* the destination address */
|
||||
uint8_t * mtu, /* the data */
|
||||
uint16_t mtu_len) /* amount of data to send */
|
||||
{
|
||||
int bytes_sent = 0;
|
||||
unsigned i = 0; /* loop counter */
|
||||
struct sockaddr_in bvlc_dest;
|
||||
BACNET_ADDRESS src;
|
||||
|
||||
/* assumes that the driver has already been initialized */
|
||||
if (bip_socket() < 0) {
|
||||
return;
|
||||
}
|
||||
/* load destination IP address */
|
||||
bvlc_dest.sin_family = AF_INET;
|
||||
bvlc_dest.sin_addr.s_addr = dest->sin_addr.s_addr;
|
||||
bvlc_dest.sin_port = dest->sin_port;
|
||||
/* Send the packet */
|
||||
bytes_sent =
|
||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &bvlc_dest,
|
||||
sizeof(struct sockaddr));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void bvlc_send_result(
|
||||
struct sockaddr_in *dest, /* the destination address */
|
||||
BACNET_BVLC_RESULT result_code)
|
||||
{
|
||||
uint8_t mtu[MAX_MPDU] = {0};
|
||||
int mtu_len = 0;
|
||||
|
||||
mtu_len = bvlc_encode_bvlc_result(&mtu[0], result_code);
|
||||
bvlc_send_mpdu(dest, mtu, mtu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int bvlc_send_bdt(struct sockaddr_in *dest)
|
||||
{
|
||||
uint8_t mtu[MAX_MPDU] = {0};
|
||||
int mtu_len = 0;
|
||||
|
||||
mtu_len = bvlc_encode_read_bdt_ack(&mtu[0], sizeof(mtu));
|
||||
if (mtu_len) {
|
||||
bvlc_send_mpdu(&sin, &mtu[0], mtu_len);
|
||||
}
|
||||
|
||||
return mtu_len;
|
||||
}
|
||||
|
||||
int bvlc_send_fdt(struct sockaddr_in *dest)
|
||||
{
|
||||
uint8_t mtu[MAX_MPDU] = {0};
|
||||
int mtu_len = 0;
|
||||
|
||||
mtu_len = bvlc_encode_read_fdt_ack(&mtu[0], sizeof(mtu));
|
||||
if (mtu_len) {
|
||||
bvlc_send_mpdu(dest, &mtu[0], mtu_len);
|
||||
}
|
||||
|
||||
return mtu_len;
|
||||
}
|
||||
|
||||
bool bvlc_broadcast_address_same(
|
||||
struct sockaddr_in *sin) /* network order address */
|
||||
{
|
||||
bool same = false;
|
||||
|
||||
if ((sin->sin_addr.s_addr == htonl(bip_get_broadcast_addr())) &&
|
||||
(sin->sin_port == htons(bip_get_port()))) {
|
||||
same = true;
|
||||
}
|
||||
|
||||
return same;
|
||||
}
|
||||
|
||||
/* returns:
|
||||
Number of bytes received, or 0 if none or timeout. */
|
||||
uint16_t bvlc_receive(
|
||||
@@ -560,10 +805,14 @@ uint16_t bvlc_receive(
|
||||
int max = 0;
|
||||
struct timeval select_timeout;
|
||||
struct sockaddr_in sin = { -1 };
|
||||
struct sockaddr_in dest = { -1 };
|
||||
socklen_t sin_len = sizeof(sin);
|
||||
int function_type = 0;
|
||||
int received_bytes = 0;
|
||||
uint16_t result_code = 0;
|
||||
unsigned i =0;
|
||||
bool status = false;
|
||||
uint16_t time_to_live = 0;
|
||||
|
||||
/* Make sure the socket is open */
|
||||
if (bip_socket() < 0) {
|
||||
@@ -613,58 +862,151 @@ uint16_t bvlc_receive(
|
||||
npdu_len -= 4;
|
||||
switch (function_type) {
|
||||
case BVLC_RESULT:
|
||||
/* Upon receipt of a BVLC-Result message containing a result code
|
||||
of X'0000' indicating the successful completion of the
|
||||
registration, a foreign device shall start a timer with a value
|
||||
equal to the Time-to-Live parameter of the preceding Register-
|
||||
Foreign-Device message. At the expiration of the timer, the
|
||||
foreign device shall re-register with the BBMD by sending a BVLL
|
||||
Register-Foreign-Device message */
|
||||
/* FIXME: clients may need this result */
|
||||
(void) decode_unsigned16(&npdu[4], &result_code);
|
||||
BVLC_Result_Code = result_code;
|
||||
break;
|
||||
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
|
||||
/* Upon receipt of a BVLL Write-Broadcast-Distribution-Table
|
||||
message, a BBMD shall attempt to create or replace its BDT,
|
||||
depending on whether or not a BDT has previously existed.
|
||||
If the creation or replacement of the BDT is successful, the BBMD
|
||||
shall return a BVLC-Result message to the originating device with
|
||||
a result code of X'0000'. Otherwise, the BBMD shall return a
|
||||
BVLC-Result message to the originating device with a result code
|
||||
of X'0010' indicating that the write attempt has failed. */
|
||||
message, a BBMD shall attempt to create or replace its BDT,
|
||||
depending on whether or not a BDT has previously existed.
|
||||
If the creation or replacement of the BDT is successful, the BBMD
|
||||
shall return a BVLC-Result message to the originating device with
|
||||
a result code of X'0000'. Otherwise, the BBMD shall return a
|
||||
BVLC-Result message to the originating device with a result code
|
||||
of X'0010' indicating that the write attempt has failed. */
|
||||
status = bvlc_create_bdt(&npdu[4],npdu_len);
|
||||
if (status) {
|
||||
bvlc_send_result(&sin, BVLC_RESULT_SUCCESSFUL_COMPLETION);
|
||||
} else {
|
||||
bvlc_send_result(&sin, BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
}
|
||||
break;
|
||||
case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE:
|
||||
/* Upon receipt of a BVLL Read-Broadcast-Distribution-Table
|
||||
message, a BBMD shall load the contents of its BDT into a BVLL
|
||||
Read-Broadcast-Distribution-Table-Ack message and send it to the
|
||||
originating device. If the BBMD is unable to perform the
|
||||
read of its BDT, it shall return a BVLC-Result message to the
|
||||
originating device with a result code of X'0020' indicating that
|
||||
the read attempt has failed.*/
|
||||
if (bvlc_send_bdt(&sin) <= 0) {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
}
|
||||
break;
|
||||
case BVLC_READ_BROADCAST_DISTRIBUTION_TABLE_ACK:
|
||||
/* FIXME: complete the code for client side read */
|
||||
break;
|
||||
case BVLC_FORWARDED_NPDU:
|
||||
/* Upon receipt of a BVLL Forwarded-NPDU message, a BBMD shall
|
||||
process it according to whether it was received from a peer
|
||||
BBMD as the result of a directed broadcast or a unicast
|
||||
transmission. A BBMD may ascertain the method by which Forwarded-
|
||||
NPDU messages will arrive by inspecting the broadcast distribution
|
||||
mask field in its own BDT entry since all BDTs are required
|
||||
to be identical. If the message arrived via directed broadcast,
|
||||
it was also received by the other devices on the BBMD's subnet. In
|
||||
this case the BBMD merely retransmits the message directly to each
|
||||
foreign device currently in the BBMD's FDT. If the
|
||||
message arrived via a unicast transmission it has not yet been
|
||||
received by the other devices on the BBMD's subnet. In this case,
|
||||
the message is sent to the devices on the BBMD's subnet using the
|
||||
B/IP broadcast address as well as to each foreign device
|
||||
currently in the BBMD's FDT. A BBMD on a subnet with no other
|
||||
BACnet devices may omit the broadcast using the B/IP
|
||||
broadcast address. The method by which a BBMD determines whether
|
||||
or not other BACnet devices are present is a local matter. */
|
||||
bvlc_broadcast_npdu(&sin, &npdu[4], npdu_len);
|
||||
process it according to whether it was received from a peer
|
||||
BBMD as the result of a directed broadcast or a unicast
|
||||
transmission. A BBMD may ascertain the method by which Forwarded-
|
||||
NPDU messages will arrive by inspecting the broadcast distribution
|
||||
mask field in its own BDT entry since all BDTs are required
|
||||
to be identical. If the message arrived via directed broadcast,
|
||||
it was also received by the other devices on the BBMD's subnet. In
|
||||
this case the BBMD merely retransmits the message directly to each
|
||||
foreign device currently in the BBMD's FDT. If the
|
||||
message arrived via a unicast transmission it has not yet been
|
||||
received by the other devices on the BBMD's subnet. In this case,
|
||||
the message is sent to the devices on the BBMD's subnet using the
|
||||
B/IP broadcast address as well as to each foreign device
|
||||
currently in the BBMD's FDT. A BBMD on a subnet with no other
|
||||
BACnet devices may omit the broadcast using the B/IP
|
||||
broadcast address. The method by which a BBMD determines whether
|
||||
or not other BACnet devices are present is a local matter. */
|
||||
/* if this was received via Broadcast, don't broadcast it */
|
||||
|
||||
/* FIXME: how do I know if I received a unicast or broadcast? */
|
||||
if (!bvlc_broadcast_address_same(&sin)) {
|
||||
dest.sin_addr.s_addr = htonl(bip_get_broadcast_addr());
|
||||
dest.sin_port == htons(bip_get_port());
|
||||
bvlc_send_mpdu(&dest, &npdu[4], npdu_len);
|
||||
}
|
||||
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
|
||||
break;
|
||||
case BVLC_REGISTER_FOREIGN_DEVICE:
|
||||
/* Upon receipt of a BVLL Register-Foreign-Device message, a BBMD
|
||||
shall start a timer with a value equal to the Time-to-Live
|
||||
parameter supplied plus a fixed grace period of 30 seconds. If,
|
||||
within the period during which the timer is active, another BVLL
|
||||
Register-Foreign-Device message from the same device is received,
|
||||
the timer shall be reset and restarted. If the time expires
|
||||
without the receipt of another BVLL Register-Foreign-Device
|
||||
message from the same foreign device, the FDT entry for this
|
||||
device shall be cleared.*/
|
||||
(void) decode_unsigned16(&npdu[4], &time_to_live);
|
||||
if (bvlc_register_foreign_device(&sin, time_to_live)) {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_SUCCESSFUL_COMPLETION);
|
||||
} else {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK);
|
||||
}
|
||||
break;
|
||||
case BVLC_READ_FOREIGN_DEVICE_TABLE:
|
||||
/* Upon receipt of a BVLL Read-Foreign-Device-Table message, a
|
||||
BBMD shall load the contents of its FDT into a BVLL Read-
|
||||
Foreign-Device-Table-Ack message and send it to the originating
|
||||
device. If the BBMD is unable to perform the read of its FDT,
|
||||
it shall return a BVLC-Result message to the originating device
|
||||
with a result code of X'0040' indicating that the read attempt has
|
||||
failed.*/
|
||||
if (bvlc_send_fdt(&sin) <= 0) {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
|
||||
}
|
||||
break;
|
||||
case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK:
|
||||
/* FIXME: complete the code for client side read */
|
||||
break;
|
||||
case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
|
||||
/* Upon receipt of a BVLL Delete-Foreign-Device-Table-Entry
|
||||
message, a BBMD shall search its foreign device table for an entry
|
||||
corresponding to the B/IP address supplied in the message. If an
|
||||
entry is found, it shall be deleted and the BBMD shall return a
|
||||
BVLC-Result message to the originating device with a result code
|
||||
of X'0000'. Otherwise, the BBMD shall return a BVLCResult
|
||||
message to the originating device with a result code of X'0050'
|
||||
indicating that the deletion attempt has failed.*/
|
||||
if (bvlc_delete_foreign_device(&npdu[4])) {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_SUCCESSFUL_COMPLETION);
|
||||
} else {
|
||||
bvlc_send_result(&sin,
|
||||
BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
|
||||
}
|
||||
break;
|
||||
case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
|
||||
/* Upon receipt of a BVLL Distribute-Broadcast-To-Network message
|
||||
from a foreign device, the receiving BBMD shall transmit a
|
||||
BVLL Forwarded-NPDU message on its local IP subnet using the
|
||||
local B/IP broadcast address as the destination address. In
|
||||
addition, a Forwarded-NPDU message shall be sent to each entry
|
||||
in its BDT as described above in the case of the receipt of a
|
||||
BVLL Original-Broadcast-NPDU as well as directly to each foreign
|
||||
device currently in the BBMD's FDT except the originating
|
||||
node. If the BBMD is unable to perform the forwarding function,
|
||||
it shall return a BVLC-Result message to the foreign device
|
||||
with a result code of X'0060' indicating that the forwarding
|
||||
attempt was unsuccessful*/
|
||||
/* FIXME: complete the function code */
|
||||
bvlc_broadcast_forward_npdu(&sin, &npdu[4], npdu_len);
|
||||
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
|
||||
break;
|
||||
case BVLC_ORIGINAL_UNICAST_NPDU:
|
||||
/* ignore messages from me */
|
||||
if (sin.sin_addr.s_addr == htonl(bip_get_addr())) {
|
||||
if ((sin.sin_addr.s_addr == htonl(bip_get_addr())) &&
|
||||
(sin.sin_port == htons(bip_get_port()))) {
|
||||
npdu_len = 0;
|
||||
} else {
|
||||
bvlc_internet_to_bacnet_address(src, &sin);
|
||||
@@ -734,19 +1076,19 @@ int bvlc_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
return BIP_Socket;
|
||||
|
||||
mtu[0] = BVLL_TYPE_BACNET_IP;
|
||||
bip_dest.sin_family = AF_INET;
|
||||
bvlc_dest.sin_family = AF_INET;
|
||||
if (dest->net == BACNET_BROADCAST_NETWORK) {
|
||||
/* broadcast */
|
||||
bip_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr);
|
||||
bip_dest.sin_port = htons(BIP_Port);
|
||||
memset(&(bip_dest.sin_zero), '\0', 8);
|
||||
bvlc_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr);
|
||||
bvlc_dest.sin_port = htons(BIP_Port);
|
||||
memset(&(bvlc_dest.sin_zero), '\0', 8);
|
||||
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||
} else if (dest->mac_len == 6) {
|
||||
/* valid unicast */
|
||||
(void) decode_unsigned32(&dest->mac[0],
|
||||
&(bip_dest.sin_addr.s_addr));
|
||||
(void) decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
|
||||
memset(&(bip_dest.sin_zero), '\0', 8);
|
||||
&(bvlc_dest.sin_addr.s_addr));
|
||||
(void) decode_unsigned16(&dest->mac[4], &(bvlc_dest.sin_port));
|
||||
memset(&(bvlc_dest.sin_zero), '\0', 8);
|
||||
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
||||
} else {
|
||||
/* invalid address */
|
||||
@@ -762,7 +1104,7 @@ int bvlc_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
|
||||
/* Send the packet */
|
||||
bytes_sent = sendto(BIP_Socket, (char *) mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &bip_dest, sizeof(struct sockaddr));
|
||||
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
|
||||
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user