Finished up the Network Layer Message handling (I hope).
Simplified the Router Table encoding (just based on DNETs).
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "bactext.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
@@ -51,17 +52,21 @@
|
|||||||
* network layer message and there is no further DNET to pass it to.
|
* network layer message and there is no further DNET to pass it to.
|
||||||
* The NCPI has already been decoded into the npdu_data structure.
|
* The NCPI has already been decoded into the npdu_data structure.
|
||||||
*
|
*
|
||||||
* @param npdu_data [in] Contains a filled-out structure with information
|
* @param src [in] The routing source information, if any.
|
||||||
* decoded from the NCPI and other NPDU bytes.
|
* If src->net and src->len are 0, there is no
|
||||||
|
* routing source information.
|
||||||
* @param DNET_list [in] List of our reachable downstream BACnet Network numbers.
|
* @param DNET_list [in] List of our reachable downstream BACnet Network numbers.
|
||||||
* Normally just one valid entry; terminated with a -1 value.
|
* Normally just one valid entry; terminated with a -1 value.
|
||||||
|
* @param npdu_data [in] Contains a filled-out structure with information
|
||||||
|
* decoded from the NCPI and other NPDU bytes.
|
||||||
* @param npdu [in] Buffer containing the rest of the NPDU, following the
|
* @param npdu [in] Buffer containing the rest of the NPDU, following the
|
||||||
* bytes that have already been decoded.
|
* bytes that have already been decoded.
|
||||||
* @param npdu_len [in] The length of the remaining NPDU message in npdu[].
|
* @param npdu_len [in] The length of the remaining NPDU message in npdu[].
|
||||||
*/
|
*/
|
||||||
static void network_control_handler(
|
static void network_control_handler(
|
||||||
BACNET_NPDU_DATA * npdu_data,
|
BACNET_ADDRESS * src,
|
||||||
int * DNET_list,
|
int * DNET_list,
|
||||||
|
BACNET_NPDU_DATA * npdu_data,
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
uint16_t npdu_len)
|
uint16_t npdu_len)
|
||||||
{
|
{
|
||||||
@@ -101,7 +106,9 @@ static void network_control_handler(
|
|||||||
* -- Unless we act upon NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK
|
* -- Unless we act upon NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK
|
||||||
* later for congestion control - then it could matter.
|
* later for congestion control - then it could matter.
|
||||||
*/
|
*/
|
||||||
debug_printf("I-Am Router to Network for Networks: ");
|
debug_printf("%s for Networks: ",
|
||||||
|
bactext_network_layer_msg_name(
|
||||||
|
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK ) );
|
||||||
while (npdu_len) {
|
while (npdu_len) {
|
||||||
len = decode_unsigned16(&npdu[npdu_offset], &dnet);
|
len = decode_unsigned16(&npdu[npdu_offset], &dnet);
|
||||||
debug_printf("%hu", dnet);
|
debug_printf("%hu", dnet);
|
||||||
@@ -119,7 +126,9 @@ static void network_control_handler(
|
|||||||
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
|
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
|
||||||
if ( npdu_len >= 3 ) {
|
if ( npdu_len >= 3 ) {
|
||||||
decode_unsigned16(&npdu[1], &dnet);
|
decode_unsigned16(&npdu[1], &dnet);
|
||||||
debug_printf("Received 'Reject Message to Network' for Network: ");
|
debug_printf("Received %s for Network: ",
|
||||||
|
bactext_network_layer_msg_name(
|
||||||
|
NETWORK_MESSAGE_I_COULD_BE_ROUTER_TO_NETWORK ) );
|
||||||
debug_printf("%hu, Reason code: %d \n", dnet, npdu[0] );
|
debug_printf("%hu, Reason code: %d \n", dnet, npdu[0] );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -133,22 +142,23 @@ static void network_control_handler(
|
|||||||
* reachable networks.
|
* reachable networks.
|
||||||
*/
|
*/
|
||||||
if ( npdu_len > 0) {
|
if ( npdu_len > 0) {
|
||||||
/* If Number of Ports is 0, send our "full" table */
|
/* If Number of Ports is 0, broadcast our "full" table */
|
||||||
if (npdu[0] == 0)
|
if (npdu[0] == 0)
|
||||||
Send_Initialize_Routing_Table_Ack( DNET_list );
|
Send_Initialize_Routing_Table_Ack( NULL, DNET_list );
|
||||||
else {
|
else {
|
||||||
/* If they sent us a list, just politely ACK it
|
/* If they sent us a list, just politely ACK it
|
||||||
* with no routing list of our own. But we don't DO
|
* with no routing list of our own. But we don't DO
|
||||||
* anything with the info, either.
|
* anything with the info, either.
|
||||||
*/
|
*/
|
||||||
int listTerminator = -1;
|
int listTerminator = -1;
|
||||||
Send_Initialize_Routing_Table_Ack( &listTerminator );
|
Send_Initialize_Routing_Table_Ack( src, &listTerminator );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Else, fall through to do nothing. */
|
/* Else, fall through to do nothing. */
|
||||||
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
|
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
|
||||||
/* Do nothing - don't support upstream traffic congestion control */
|
/* Do nothing with the routing table info, since don't support
|
||||||
|
* upstream traffic congestion control */
|
||||||
break;
|
break;
|
||||||
case NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK:
|
case NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK:
|
||||||
case NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK:
|
case NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK:
|
||||||
@@ -156,9 +166,9 @@ static void network_control_handler(
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* An unrecognized message is bad; send an error response. */
|
/* An unrecognized message is bad; send an error response. */
|
||||||
#if PRINT_ENABLED
|
Send_Reject_Message_To_Network( src,
|
||||||
fprintf(stderr, "NPDU: Network Layer Message discarded!\n");
|
NETWORK_REJECT_UNKNOWN_MESSAGE_TYPE, DNET_list[0] );
|
||||||
#endif
|
/* Sending our DNET doesn't make a lot of sense, does it? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,11 +180,14 @@ static void routed_apdu_handler(
|
|||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
uint16_t apdu_len)
|
uint16_t apdu_len)
|
||||||
{
|
{
|
||||||
/* Handle the normal, non-routed variety for right now in development */
|
int dnet = DNET_list[0];
|
||||||
apdu_handler(src, apdu, apdu_len);
|
if ((dest->net == dnet) || (dest->net == BACNET_BROADCAST_NETWORK)) {
|
||||||
#if PRINT_ENABLED
|
/* Handle the normal, non-routed variety for right now in development */
|
||||||
printf("NPDU: DNET=%u. Discarded!\n", (unsigned) dest->net);
|
apdu_handler(src, apdu, apdu_len);
|
||||||
#endif
|
} else {
|
||||||
|
/* We don't know how to reach this one */
|
||||||
|
Send_Reject_Message_To_Network( src, NETWORK_REJECT_NO_ROUTE, dest->net );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handler for the NPDU portion of a received packet, which may have routing.
|
/** Handler for the NPDU portion of a received packet, which may have routing.
|
||||||
@@ -217,13 +230,12 @@ void routing_npdu_handler(
|
|||||||
if (pdu[0] == BACNET_PROTOCOL_VERSION) {
|
if (pdu[0] == BACNET_PROTOCOL_VERSION) {
|
||||||
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
|
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
|
||||||
if ( apdu_offset <= 0 ) {
|
if ( apdu_offset <= 0 ) {
|
||||||
#if PRINT_ENABLED
|
debug_printf("NPDU: Decoding failed; Discarded!\n");
|
||||||
printf("NPDU: Decoding failed; Discarded!\n");
|
|
||||||
#endif
|
|
||||||
} else if (npdu_data.network_layer_message) {
|
} else if (npdu_data.network_layer_message) {
|
||||||
if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
|
if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
|
||||||
network_control_handler( &npdu_data, DNET_list, &pdu[apdu_offset],
|
network_control_handler( src, DNET_list, &npdu_data,
|
||||||
(uint16_t) (pdu_len - apdu_offset));
|
&pdu[apdu_offset],
|
||||||
|
(uint16_t) (pdu_len - apdu_offset));
|
||||||
} else {
|
} else {
|
||||||
/* The DNET is set, but we don't support downstream routers,
|
/* The DNET is set, but we don't support downstream routers,
|
||||||
* so we just silently drop this network layer message,
|
* so we just silently drop this network layer message,
|
||||||
@@ -242,10 +254,9 @@ void routing_npdu_handler(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Should we send NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK? */
|
/* Should we send NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK? */
|
||||||
#if PRINT_ENABLED
|
debug_printf(
|
||||||
printf("NPDU: Unsupported BACnet Protocol Version=%u. Discarded!\n",
|
"NPDU: Unsupported BACnet Protocol Version=%u. Discarded!\n",
|
||||||
(unsigned) pdu[0]);
|
(unsigned) pdu[0]);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
/** @file s_router.c Methods to send various BACnet Router Network Layer Messages. */
|
/** @file s_router.c Methods to send various BACnet Router Network Layer Messages. */
|
||||||
|
|
||||||
@@ -81,6 +82,14 @@ static void npdu_encode_npdu_network(
|
|||||||
* - NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK: Single int for DNET requested
|
* - NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK: Single int for DNET requested
|
||||||
* - NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: Array of DNET(s) to send,
|
* - NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: Array of DNET(s) to send,
|
||||||
* terminated with -1
|
* terminated with -1
|
||||||
|
* - NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK: array of 2 ints,
|
||||||
|
* first is reason, second is DNET of interest
|
||||||
|
* - NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK: same as I-Am-Router msg
|
||||||
|
* - NETWORK_MESSAGE_ROUTER_AVAILABLE_TO_NETWORK: same as I-Am-Router msg
|
||||||
|
* - NETWORK_MESSAGE_INIT_RT_TABLE and NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
|
||||||
|
* Array of DNET(s) to process as "Ports", terminated with -1. Each DNET
|
||||||
|
* will be expanded to a BACNET_ROUTER_PORT (with simple defaults for
|
||||||
|
* most fields) and encoded.
|
||||||
*
|
*
|
||||||
* @param network_message_type [in] The type of message to be sent.
|
* @param network_message_type [in] The type of message to be sent.
|
||||||
* @param dst [in/out] If not NULL, contains the destination for the message.
|
* @param dst [in/out] If not NULL, contains the destination for the message.
|
||||||
@@ -97,17 +106,23 @@ int Send_Network_Layer_Message(
|
|||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
int bytes_sent = 0;
|
int bytes_sent = 0;
|
||||||
int *pVal = iArgs; /* Start with first value */
|
int *pVal = iArgs; /* Start with first value */
|
||||||
|
bool data_expecting_reply = false;
|
||||||
BACNET_NPDU_DATA npdu_data;
|
BACNET_NPDU_DATA npdu_data;
|
||||||
BACNET_ADDRESS bcastDest;
|
BACNET_ADDRESS bcastDest;
|
||||||
|
|
||||||
|
if ( iArgs == NULL )
|
||||||
|
return 0; /* Can't do anything here */
|
||||||
|
|
||||||
/* If dst was NULL, get our (local net) broadcast MAC address. */
|
/* If dst was NULL, get our (local net) broadcast MAC address. */
|
||||||
if ( dst == NULL ) {
|
if ( dst == NULL ) {
|
||||||
datalink_get_broadcast_address(&bcastDest);
|
datalink_get_broadcast_address(&bcastDest);
|
||||||
dst = &bcastDest;
|
dst = &bcastDest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( network_message_type == NETWORK_MESSAGE_INIT_RT_TABLE )
|
||||||
|
data_expecting_reply = true; /* DER in this one case */
|
||||||
npdu_encode_npdu_network(&npdu_data,
|
npdu_encode_npdu_network(&npdu_data,
|
||||||
network_message_type, false,
|
network_message_type, data_expecting_reply,
|
||||||
MESSAGE_PRIORITY_NORMAL);
|
MESSAGE_PRIORITY_NORMAL);
|
||||||
|
|
||||||
/* We don't need src information, since a message can't originate from
|
/* We don't need src information, since a message can't originate from
|
||||||
@@ -130,6 +145,8 @@ int Send_Network_Layer_Message(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK:
|
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK:
|
||||||
|
case NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK:
|
||||||
|
case NETWORK_MESSAGE_ROUTER_AVAILABLE_TO_NETWORK:
|
||||||
while ( *pVal >= 0 ) {
|
while ( *pVal >= 0 ) {
|
||||||
len =
|
len =
|
||||||
encode_unsigned16(&Handler_Transmit_Buffer[pdu_len],
|
encode_unsigned16(&Handler_Transmit_Buffer[pdu_len],
|
||||||
@@ -139,24 +156,60 @@ int Send_Network_Layer_Message(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
|
||||||
|
/* Encode the Reason byte, then the DNET */
|
||||||
|
Handler_Transmit_Buffer[pdu_len++] = (uint8_t) *pVal;
|
||||||
|
pVal++;
|
||||||
|
len =
|
||||||
|
encode_unsigned16(&Handler_Transmit_Buffer[pdu_len],
|
||||||
|
(uint16_t) *pVal);
|
||||||
|
pdu_len += len;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETWORK_MESSAGE_INIT_RT_TABLE:
|
||||||
|
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
|
||||||
|
/* First, count the number of Ports we will encode */
|
||||||
|
len = 0; /* Re-purpose len as our counter here */
|
||||||
|
while ( *pVal >= 0 ) {
|
||||||
|
len++;
|
||||||
|
pVal++;
|
||||||
|
}
|
||||||
|
Handler_Transmit_Buffer[pdu_len++] = (uint8_t) len;
|
||||||
|
|
||||||
|
if ( len > 0 ) {
|
||||||
|
uint8_t portID = 1;
|
||||||
|
pVal = iArgs; /* Reset to beginning */
|
||||||
|
/* Now encode each (virtual) BACNET_ROUTER_PORT.
|
||||||
|
* We will simply use a positive index for PortID,
|
||||||
|
* and have no PortInfo.
|
||||||
|
*/
|
||||||
|
while ( *pVal >= 0 ) {
|
||||||
|
len =
|
||||||
|
encode_unsigned16(&Handler_Transmit_Buffer[pdu_len],
|
||||||
|
(uint16_t) *pVal);
|
||||||
|
pdu_len += len;
|
||||||
|
Handler_Transmit_Buffer[pdu_len++] = portID++;
|
||||||
|
Handler_Transmit_Buffer[pdu_len++] = 0;
|
||||||
|
debug_printf( " Sending Routing Table entry for %u \n", *pVal );
|
||||||
|
pVal++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#if PRINT_ENABLED
|
debug_printf("Not sent: %s message unsupported \n",
|
||||||
fprintf(stderr, "Not sent: %s message unsupported \n",
|
|
||||||
bactext_network_layer_msg_name( network_message_type ) );
|
bactext_network_layer_msg_name( network_message_type ) );
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
break; /* Will never reach this line */
|
break; /* Will never reach this line */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PRINT_ENABLED
|
|
||||||
if ( dst != NULL )
|
if ( dst != NULL )
|
||||||
fprintf(stderr, "Sending %s message to BACnet network %u \n",
|
debug_printf("Sending %s message to BACnet network %u \n",
|
||||||
bactext_network_layer_msg_name( network_message_type ),
|
bactext_network_layer_msg_name( network_message_type ),
|
||||||
dst->net );
|
dst->net );
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Sending %s message to local BACnet network \n",
|
debug_printf("Sending %s message to local BACnet network \n",
|
||||||
bactext_network_layer_msg_name( network_message_type ) );
|
bactext_network_layer_msg_name( network_message_type ) );
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Now send the message */
|
/* Now send the message */
|
||||||
bytes_sent =
|
bytes_sent =
|
||||||
@@ -165,8 +218,7 @@ int Send_Network_Layer_Message(
|
|||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
if (bytes_sent <= 0) {
|
if (bytes_sent <= 0) {
|
||||||
int wasErrno = errno; /* preserve the errno */
|
int wasErrno = errno; /* preserve the errno */
|
||||||
fprintf(stderr,
|
debug_printf("Failed to send %s message (%s)!\n",
|
||||||
"Failed to send %s message (%s)!\n",
|
|
||||||
bactext_network_layer_msg_name( network_message_type ),
|
bactext_network_layer_msg_name( network_message_type ),
|
||||||
strerror(wasErrno));
|
strerror(wasErrno));
|
||||||
}
|
}
|
||||||
@@ -193,9 +245,12 @@ void Send_Who_Is_Router_To_Network(
|
|||||||
dst, &dnet );
|
dst, &dnet );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Broadcast an I-am-router-to-network message, giving the list of networks we can reach.
|
/** Broadcast an I-am-router-to-network message, giving the list of networks
|
||||||
* The message will be sent to our normal DataLink Layer interface, not the routed backend.
|
* we can reach.
|
||||||
* @param DNET_list [in] list of BACnet network numbers for which I am a router, terminated with -1
|
* The message will be sent to our normal DataLink Layer interface,
|
||||||
|
* not the routed backend.
|
||||||
|
* @param DNET_list [in] List of BACnet network numbers for which I am a router,
|
||||||
|
* terminated with -1
|
||||||
*/
|
*/
|
||||||
void Send_I_Am_Router_To_Network(
|
void Send_I_Am_Router_To_Network(
|
||||||
const int DNET_list[])
|
const int DNET_list[])
|
||||||
@@ -205,85 +260,74 @@ void Send_I_Am_Router_To_Network(
|
|||||||
NULL, (int *) DNET_list );
|
NULL, (int *) DNET_list );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/** Finds a specific router, or all reachable BACnet networks.
|
||||||
|
* The response(s) will come in I-am-router-to-network message(s).
|
||||||
|
*
|
||||||
|
* @param dst [in] If NULL, request will be broadcast to the local BACnet
|
||||||
|
* network. Otherwise, designates a particular router
|
||||||
|
* destination.
|
||||||
|
* @param reject_reason [in] One of the BACNET_NETWORK_REJECT_REASONS codes.
|
||||||
|
* @param dnet [in] Which BACnet network orginated the message.
|
||||||
|
*/
|
||||||
|
void Send_Reject_Message_To_Network(
|
||||||
|
BACNET_ADDRESS * dst,
|
||||||
|
uint8_t reject_reason,
|
||||||
|
int dnet)
|
||||||
|
{
|
||||||
|
int iArgs[2];
|
||||||
|
iArgs[0] = reject_reason;
|
||||||
|
iArgs[1] = dnet;
|
||||||
|
Send_Network_Layer_Message( NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK,
|
||||||
|
dst, iArgs );
|
||||||
|
debug_printf(" Reject Reason=%d, DNET=%u\n", reject_reason, dnet );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Send an Initialize Routing Table message, built from an optional DNET[]
|
||||||
|
* array.
|
||||||
|
* There are two cases here:
|
||||||
|
* 1) We are requesting a destination router's Routing Table.
|
||||||
|
* In that case, DNET[] should just have one entry of -1 (no routing table
|
||||||
|
* is sent).
|
||||||
|
* 2) We are sending out our Routing Table for some reason (normally bcast it).
|
||||||
|
*
|
||||||
|
* @param dst [in] If NULL, msg will be broadcast to the local BACnet network.
|
||||||
|
* Optionally may designate a particular router destination,
|
||||||
|
* especially when requesting a Routing Table.
|
||||||
|
* @param DNET_list [in] List of BACnet network numbers for which I am a router,
|
||||||
|
* terminated with -1. Will be just -1 when we are
|
||||||
|
* requesting a routing table.
|
||||||
|
*/
|
||||||
void Send_Initialize_Routing_Table(
|
void Send_Initialize_Routing_Table(
|
||||||
BACNET_ADDRESS * dst,
|
BACNET_ADDRESS * dst,
|
||||||
BACNET_ROUTER_PORT * router_port_list)
|
const int DNET_list[])
|
||||||
{
|
{
|
||||||
int len = 0;
|
/* Use a NULL dst here since we want a broadcast MAC address. */
|
||||||
int pdu_len = 0;
|
Send_Network_Layer_Message( NETWORK_MESSAGE_INIT_RT_TABLE,
|
||||||
int bytes_sent = 0;
|
dst, (int *) DNET_list );
|
||||||
BACNET_NPDU_DATA npdu_data;
|
|
||||||
uint8_t number_of_ports = 0;
|
|
||||||
BACNET_ROUTER_PORT *router_port;
|
|
||||||
uint8_t i = 0; /* counter */
|
|
||||||
|
|
||||||
npdu_encode_npdu_network(&npdu_data, NETWORK_MESSAGE_INIT_RT_TABLE, true,
|
|
||||||
MESSAGE_PRIORITY_NORMAL);
|
|
||||||
pdu_len =
|
|
||||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data);
|
|
||||||
/* encode the optional port_info list portion of the packet */
|
|
||||||
router_port = router_port_list;
|
|
||||||
while (router_port) {
|
|
||||||
number_of_ports++;
|
|
||||||
router_port = router_port->next;
|
|
||||||
}
|
|
||||||
Handler_Transmit_Buffer[pdu_len++] = number_of_ports;
|
|
||||||
if (number_of_ports) {
|
|
||||||
router_port = router_port_list;
|
|
||||||
while (router_port) {
|
|
||||||
len =
|
|
||||||
encode_unsigned16(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
router_port->dnet);
|
|
||||||
pdu_len += len;
|
|
||||||
Handler_Transmit_Buffer[pdu_len++] = router_port->id;
|
|
||||||
Handler_Transmit_Buffer[pdu_len++] = router_port->info_len;
|
|
||||||
for (i = 0; i < router_port->info_len; i++) {
|
|
||||||
Handler_Transmit_Buffer[pdu_len++] = router_port->info[i];
|
|
||||||
}
|
|
||||||
router_port = router_port->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if PRINT_ENABLED
|
|
||||||
fprintf(stderr, "Send Initialize-Routing-Table message\n");
|
|
||||||
#endif
|
|
||||||
bytes_sent =
|
|
||||||
datalink_send_pdu(dst, &npdu_data, &Handler_Transmit_Buffer[0],
|
|
||||||
pdu_len);
|
|
||||||
#if PRINT_ENABLED
|
|
||||||
if (bytes_sent <= 0)
|
|
||||||
fprintf(stderr,
|
|
||||||
"Failed to send Initialize-Routing-Table message (%s)!\n",
|
|
||||||
strerror(errno));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
|
||||||
|
/** Sends our Routing Table, built from our DNET[] array, as an ACK.
|
||||||
|
* There are two cases here:
|
||||||
|
* 1) We are responding to a NETWORK_MESSAGE_INIT_RT_TABLE requesting our table.
|
||||||
|
* We will normally broadcast that response.
|
||||||
|
* 2) We are ACKing the receipt of a NETWORK_MESSAGE_INIT_RT_TABLE containing a
|
||||||
|
* routing table, and then we will want to respond to that dst router.
|
||||||
|
* In that case, DNET[] should just have one entry of -1 (no routing table
|
||||||
|
* is sent).
|
||||||
|
*
|
||||||
|
* @param dst [in] If NULL, Ack will be broadcast to the local BACnet network.
|
||||||
|
* Optionally may designate a particular router destination,
|
||||||
|
* especially when ACKing receipt of this message type.
|
||||||
|
* @param DNET_list [in] List of BACnet network numbers for which I am a router,
|
||||||
|
* terminated with -1. May be just -1 when no table
|
||||||
|
* should be sent.
|
||||||
|
*/
|
||||||
void Send_Initialize_Routing_Table_Ack(
|
void Send_Initialize_Routing_Table_Ack(
|
||||||
const int DNET_list[] )
|
BACNET_ADDRESS * dst,
|
||||||
|
const int DNET_list[])
|
||||||
{
|
{
|
||||||
int pdu_len = 0;
|
Send_Network_Layer_Message( NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
|
||||||
BACNET_ADDRESS dest;
|
dst, (int *) DNET_list );
|
||||||
int bytes_sent = 0;
|
|
||||||
BACNET_NPDU_DATA npdu_data;
|
|
||||||
// BACNET_ROUTER_PORT * router_port_list;
|
|
||||||
|
|
||||||
/* FIXME: is this parameter needed? */
|
|
||||||
// router_port_list = router_port_list;
|
|
||||||
/* setup packet for sending */
|
|
||||||
npdu_encode_npdu_network(&npdu_data, NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
|
|
||||||
false, MESSAGE_PRIORITY_NORMAL);
|
|
||||||
pdu_len =
|
|
||||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data);
|
|
||||||
/* encode the optional DNET list portion of the packet */
|
|
||||||
datalink_get_broadcast_address(&dest);
|
|
||||||
bytes_sent =
|
|
||||||
datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0],
|
|
||||||
pdu_len);
|
|
||||||
#if PRINT_ENABLED
|
|
||||||
if (bytes_sent <= 0)
|
|
||||||
fprintf(stderr,
|
|
||||||
"Failed to Send Initialize-Routing-Table-Ack message (%s)!\n",
|
|
||||||
strerror(errno));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1463,4 +1463,16 @@ typedef enum BACnetEventTransitionBits {
|
|||||||
MAX_BACNET_EVENT_TRANSITION = 3
|
MAX_BACNET_EVENT_TRANSITION = 3
|
||||||
} BACNET_EVENT_TRANSITION_BITS;
|
} BACNET_EVENT_TRANSITION_BITS;
|
||||||
|
|
||||||
|
/* The Network Reject Reasons for NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK */
|
||||||
|
typedef enum {
|
||||||
|
NETWORK_REJECT_UNKNOWN_ERROR = 0,
|
||||||
|
NETWORK_REJECT_NO_ROUTE = 1,
|
||||||
|
NETWORK_REJECT_ROUTER_BUSY = 2,
|
||||||
|
NETWORK_REJECT_UNKNOWN_MESSAGE_TYPE = 3,
|
||||||
|
NETWORK_REJECT_MESSAGE_TOO_LONG = 4,
|
||||||
|
/* Reasons this value or above we don't know about */
|
||||||
|
NETWORK_REJECT_REASON_INVALID
|
||||||
|
} BACNET_NETWORK_REJECT_REASONS;
|
||||||
|
|
||||||
|
|
||||||
#endif /* end of BACENUM_H */
|
#endif /* end of BACENUM_H */
|
||||||
|
|||||||
@@ -194,10 +194,15 @@ extern "C" {
|
|||||||
int dnet);
|
int dnet);
|
||||||
void Send_I_Am_Router_To_Network(
|
void Send_I_Am_Router_To_Network(
|
||||||
const int DNET_list[]);
|
const int DNET_list[]);
|
||||||
|
void Send_Reject_Message_To_Network(
|
||||||
|
BACNET_ADDRESS * dst,
|
||||||
|
uint8_t reject_reason,
|
||||||
|
int dnet);
|
||||||
void Send_Initialize_Routing_Table(
|
void Send_Initialize_Routing_Table(
|
||||||
BACNET_ADDRESS * dst,
|
BACNET_ADDRESS * dst,
|
||||||
BACNET_ROUTER_PORT * router_port_list);
|
const int DNET_list[]);
|
||||||
void Send_Initialize_Routing_Table_Ack(
|
void Send_Initialize_Routing_Table_Ack(
|
||||||
|
BACNET_ADDRESS * dst,
|
||||||
const int DNET_list[]);
|
const int DNET_list[]);
|
||||||
|
|
||||||
uint8_t Send_Life_Safety_Operation_Data(
|
uint8_t Send_Life_Safety_Operation_Data(
|
||||||
|
|||||||
Reference in New Issue
Block a user