Issue 2 move folders and use deep path include file names to prevent collisions (#4)

* moving folders and files and adjust server demo build

* Fix Makefile for apps/server on Linux

* fix unit test source file folders

* fix datetime convert UTC functions. Add Code::Blocks project for datetime testing

* added some ignore extensions

* disable parallel make option

* fix build for abort, dcc, and epics apps

* fix build for dcc, epics, error, and getevent apps.

* Fixed building of all apps

* fix the ipv4 to ipv6 router app build

* Change indent style from Google to Webkit

* make pretty to re-format style

* removed common Makefile since we already had one and two was too many

* remove scripts from root folder that are no longer maintained or used

* remove mercurial EOL and ignore files for git repo

* remove .vscodeconfig files from repo

* tweak clang-format style

* clang-format src and apps with tweaked style

* added clang-tidy to fix readability if braces in src

* result of make tidy for src and apps

* fix clang-tidy mangling

* Added code::blocks project for BACnet server simulation

* added code::blocks linux project for WhoIs app

* update text files for EOL

* fix EOL in some files

* fixed make win32 apps for older gcc

* Removed Borland C++ Makefile in apps. Unable to maintain support for Borland C++ compiler.

* created codeblocks project for apps/epics for Windows

* fixing ports/xplained to work with new data structure.

* fix ports/xplained example for Atmel Studio compile

* fix ports/stm32f10x example for gcc Makefile compile

* fix ports/stm32f10x example for IAR EWARM compile

* fix ports/xplained timer callback

* fix ports/bdk_atxx_mspt build with subdirs

* fix ports/bdk_atxx_mspt build with subdirs

* updated git ignore for IAR build artifacts

* updated gitignore for non-tracked files and folders

* fixed bdk-atxx4-mstp port for Rowley Crossworks project file

* fixed bdk-atxx4-mstp port for GCC AVR Makefile

* fixed atmega168 port for IAR AVR and GCC AVR Makefile

* fixed at91sam7s port for IAR ARM and GCC ARM Makefile

* removed unmaintainable DOS, RTOS32, and atmega8 ports.  Updated rx62n (untested).

* changed arm7 to uip port
This commit is contained in:
Steve Karg
2019-12-13 15:19:10 -06:00
committed by GitHub
parent 8a38dbe2cf
commit d50c190957
912 changed files with 36206 additions and 52502 deletions
+110
View File
@@ -0,0 +1,110 @@
/**************************************************************************
*
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacdef.h"
#include "bacnet/bacdcode.h"
#include "bacnet/bacint.h"
#include "bacnet/bacenum.h"
#include "bacnet/bits.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/basic/services.h"
#if PRINT_ENABLED
#include <stdio.h>
#endif
/** @file h_npdu.c Handles messages at the NPDU level of the BACnet stack. */
/** Handler for the NPDU portion of a received packet.
* Aside from error-checking, if the NPDU doesn't contain routing info,
* this handler doesn't do much besides stepping over the NPDU header
* and passing the remaining bytes to the apdu_handler.
* @note The routing (except src) and NCPI information, including
* npdu_data->data_expecting_reply, are discarded.
* @see routing_npdu_handler
*
* @ingroup MISCHNDLR
*
* @param src [out] Returned with routing source information if the NPDU
* has any and if this points to non-null storage for it.
* If src->net and src->len are 0 on return, there is no
* routing source information.
* This src describes the original source of the message when
* it had to be routed to reach this BACnet Device, and this
* is passed down into the apdu_handler; however, I don't
* think this project's code has any use for the src info
* on return from this handler, since the response has
* already been sent via the apdu_handler.
* @param pdu [in] Buffer containing the NPDU and APDU of the received packet.
* @param pdu_len [in] The size of the received message in the pdu[] buffer.
*/
void npdu_handler(BACNET_ADDRESS *src, /* source address */
uint8_t *pdu, /* PDU data */
uint16_t pdu_len)
{ /* length PDU */
int apdu_offset = 0;
BACNET_ADDRESS dest = { 0 };
BACNET_NPDU_DATA npdu_data = { 0 };
/* only handle the version that we know how to handle */
if (pdu[0] == BACNET_PROTOCOL_VERSION) {
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
if (npdu_data.network_layer_message) {
/*FIXME: network layer message received! Handle it! */
#if PRINT_ENABLED
fprintf(stderr, "NPDU: Network Layer Message discarded!\n");
#endif
} else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
/* only handle the version that we know how to handle */
/* and we are not a router, so ignore messages with
routing information cause they are not for us */
if ((dest.net == BACNET_BROADCAST_NETWORK) &&
((pdu[apdu_offset] & 0xF0) ==
PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
/* hack for 5.4.5.1 - IDLE */
/* ConfirmedBroadcastReceived */
/* then enter IDLE - ignore the PDU */
} else {
apdu_handler(src, &pdu[apdu_offset],
(uint16_t)(pdu_len - apdu_offset));
}
} else {
#if PRINT_ENABLED
printf("NPDU: DNET=%u. Discarded!\n", (unsigned)dest.net);
#endif
}
}
} else {
#if PRINT_ENABLED
printf("NPDU: BACnet Protocol Version=%u. Discarded!\n",
(unsigned)pdu[0]);
#endif
}
return;
}
+70
View File
@@ -0,0 +1,70 @@
/**
* @file
* @author Steve Karg
* @date October 2019
* @brief Header file for a basic NPDU handler
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NPDU_HANDLER_H
#define NPDU_HANDLER_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacdef.h"
#include "bacnet/bacenum.h"
#include "bacnet/apdu.h"
#include "bacnet/npdu.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void npdu_handler(
BACNET_ADDRESS * src,
uint8_t * pdu,
uint16_t pdu_len);
void npdu_handler_cleanup(void);
void npdu_handler_init(
uint16_t bip_net,
uint16_t mstp_net);
void npdu_router_handler(
uint16_t snet,
BACNET_ADDRESS * src,
uint8_t * pdu,
uint16_t pdu_len);
int npdu_router_send_pdu(
uint16_t dnet,
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * npdu_data,
uint8_t * pdu,
unsigned int pdu_len);
void npdu_router_get_my_address(
uint16_t dnet,
BACNET_ADDRESS * my_address);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+302
View File
@@ -0,0 +1,302 @@
/**************************************************************************
*
* Copyright (C) 2010 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Acknowledging the contribution of code and ideas used here that
* came from Paul Chapman's vmac demo project. */
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacdef.h"
#include "bacnet/bacdcode.h"
#include "bacnet/bacint.h"
#include "bacnet/bacenum.h"
#include "bacnet/bits.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/bactext.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/services.h"
#if PRINT_ENABLED
#include <stdio.h>
#endif
#if defined(BACDL_BIP)
#include "bacnet/datalink/bvlc.h"
#endif
/** @file h_routed_npdu.c Handles messages at the NPDU level of the BACnet
* stack, including routing and network control messages. */
/** Handler to manage the Network Layer Control Messages received in a packet.
* This handler is called if the NCPI bit 7 indicates that this packet is a
* network layer message and there is no further DNET to pass it to.
* The NCPI has already been decoded into the npdu_data structure.
* @ingroup MISCHNDLR
*
* @param src [in] The routing source information, if any.
* 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. 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
* bytes that have already been decoded.
* @param npdu_len [in] The length of the remaining NPDU message in npdu[].
*/
static void network_control_handler(BACNET_ADDRESS *src,
int *DNET_list,
BACNET_NPDU_DATA *npdu_data,
uint8_t *npdu,
uint16_t npdu_len)
{
uint16_t npdu_offset = 0;
uint16_t dnet = 0;
uint16_t len = 0;
switch (npdu_data->network_message_type) {
case NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK:
/* Send I-am-router-to-network with our one-network list if
* our specific network is requested, or no specific
* network is requested. Silently drop other DNET requests.
*/
if (npdu_len >= 2) {
uint16_t network;
len += decode_unsigned16(&npdu[len], &network);
if (network == DNET_list[0]) {
Send_I_Am_Router_To_Network(DNET_list);
}
} else {
Send_I_Am_Router_To_Network(DNET_list);
}
break;
case NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK:
/* Per the standard, we are supposed to process this message and
* add its DNETs to our routing table.
* However, since we only have one upstream port that these
* messages can come from and replies go to, it doesn't seem
* to provide us any value to do this; when we need to send to
* some remote device, we will start by pushing it out the
* upstream port and let the attached router(s) take it from there.
* Consequently, we'll do nothing interesting here.
* -- Unless we act upon NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK
* later for congestion control - then it could matter.
*/
debug_printf("%s for Networks: ",
bactext_network_layer_msg_name(
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK));
while (npdu_len >= 2) {
len = decode_unsigned16(&npdu[npdu_offset], &dnet);
debug_printf("%hu", dnet);
npdu_len -= len;
npdu_offset += len;
if (npdu_len >= 2) {
debug_printf(", ");
}
}
debug_printf("\n");
break;
case NETWORK_MESSAGE_I_COULD_BE_ROUTER_TO_NETWORK:
/* Do nothing, same as previous case. */
break;
case NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK:
if (npdu_len >= 3) {
decode_unsigned16(&npdu[1], &dnet);
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]);
}
break;
case NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK:
case NETWORK_MESSAGE_ROUTER_AVAILABLE_TO_NETWORK:
/* Do nothing - don't support upstream traffic congestion control */
break;
case NETWORK_MESSAGE_INIT_RT_TABLE:
/* If sent with Number of Ports == 0, we respond with
* NETWORK_MESSAGE_INIT_RT_TABLE_ACK and a list of all our
* reachable networks.
*/
if (npdu_len > 0) {
/* If Number of Ports is 0, broadcast our "full" table */
if (npdu[0] == 0) {
Send_Initialize_Routing_Table_Ack(NULL, DNET_list);
} else {
/* If they sent us a list, just politely ACK it
* with no routing list of our own. But we don't DO
* anything with the info, either.
*/
int listTerminator = -1;
Send_Initialize_Routing_Table_Ack(src, &listTerminator);
}
break;
}
/* Else, fall through to do nothing. */
case NETWORK_MESSAGE_INIT_RT_TABLE_ACK:
/* Do nothing with the routing table info, since don't support
* upstream traffic congestion control */
break;
case NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK:
case NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK:
/* Do nothing - don't support PTP half-router control */
break;
default:
/* An unrecognized message is bad; send an error response. */
Send_Reject_Message_To_Network(
src, NETWORK_REJECT_UNKNOWN_MESSAGE_TYPE, DNET_list[0]);
/* Sending our DNET doesn't make a lot of sense, does it? */
break;
}
}
/** An APDU pre-handler that makes sure that the subsequent APDU handler call
* operates on the right Device Object(s), as addressed by the destination
* (routing) information.
*
* @note Even when the destination is "routed" to our virtual BACnet network,
* the src information does not need to change to reflect that (as it normally
* would for a routed message) because the reply will be sent from the level
* of the gateway Device.
*
* @param src [in] The BACNET_ADDRESS of the message's source.
* @param dest [in] The BACNET_ADDRESS of the message's destination.
* @param DNET_list [in] List of our reachable downstream BACnet Network
* numbers. Normally just one valid entry; terminated with a -1 value.
* @param apdu [in] The apdu portion of the request, to be processed.
* @param apdu_len [in] The total (remaining) length of the apdu.
*/
static void routed_apdu_handler(BACNET_ADDRESS *src,
BACNET_ADDRESS *dest,
int *DNET_list,
uint8_t *apdu,
uint16_t apdu_len)
{
int cursor = 0; /* Starting hint */
bool bGotOne = false;
if (!Routed_Device_Is_Valid_Network(dest->net, DNET_list)) {
/* We don't know how to reach this one.
* The protocol doesn't specifically state this, but if this message
* was broadcast to us, we should assume "someone else" is handling
* it and not get involved (ie, send a Reject-Message).
* Since we can't reach other routers that src couldn't already reach,
* we don't try the standard path of asking Who-Is-Router-to-Network. */
#if defined(BACDL_BIP)
/* If wasn't unicast to us, must have been one of the bcast types.
* Drop it. */
if (bvlc_get_function_code() != BVLC_ORIGINAL_UNICAST_NPDU) {
return;
}
#endif
/* Upper level handlers knew that this was sent as a bcast,
* but our only other way to guess at that here is if the dest->adr
* is absent, then we know this is some sort of bcast.
*/
if (dest->len > 0) {
Send_Reject_Message_To_Network(
src, NETWORK_REJECT_NO_ROUTE, dest->net);
} /* else, silently drop it */
return;
}
while (Routed_Device_GetNext(dest, DNET_list, &cursor)) {
apdu_handler(src, apdu, apdu_len);
bGotOne = true;
if (cursor < 0) { /* If no more matches, */
break; /* We don't need to keep looking */
}
}
if (!bGotOne) {
/* Just silently drop this packet. */
}
}
/** Handler for the NPDU portion of a received packet, which may have routing.
* This is a fuller handler than the regular npdu_handler, as it manages
* - Decoding of the NCPI byte
* - Further processing by network_control_handler() if this is a network
* layer message.
* - Further processing by routed_apdu_handler() if it contains an APDU
* - Normally (no routing) by apdu_handler()
* - With Routing (a further destination was indicated) by the decoded
* destination.
* - Errors in decoding.
* @note The npdu_data->data_expecting_reply status is discarded.
* @see npdu_handler
* @ingroup NMRC
*
* @param src [out] Returned with routing source information if the NPDU
* has any and if this points to non-null storage for it.
* If src->net and src->len are 0 on return, there is no
* routing source information.
* This src describes the original source of the message when
* it had to be routed to reach this BACnet Device, and this
* is passed down into the apdu_handler; however, I don't
* think this project's code has any use for the src info
* on return from this handler, since the response has
* already been sent via the apdu_handler.
* @param DNET_list [in] List of our reachable downstream BACnet Network
* numbers. Normally just one valid entry; terminated with a -1 value.
* @param pdu [in] Buffer containing the NPDU and APDU of the received packet.
* @param pdu_len [in] The size of the received message in the pdu[] buffer.
*/
void routing_npdu_handler(
BACNET_ADDRESS *src, int *DNET_list, uint8_t *pdu, uint16_t pdu_len)
{
int apdu_offset = 0;
BACNET_ADDRESS dest = { 0 };
BACNET_NPDU_DATA npdu_data = { 0 };
/* only handle the version that we know how to handle */
if (pdu[0] == BACNET_PROTOCOL_VERSION) {
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
if (apdu_offset <= 0) {
debug_printf("NPDU: Decoding failed; Discarded!\n");
} else if (npdu_data.network_layer_message) {
if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
network_control_handler(src, DNET_list, &npdu_data,
&pdu[apdu_offset], (uint16_t)(pdu_len - apdu_offset));
} else {
/* The DNET is set, but we don't support downstream routers,
* so we just silently drop this network layer message,
* since only routers can handle it (even if for our DNET) */
}
} else if (apdu_offset <= pdu_len) {
if ((dest.net == 0) || (npdu_data.hop_count > 1)) {
routed_apdu_handler(src, &dest, DNET_list, &pdu[apdu_offset],
(uint16_t)(pdu_len - apdu_offset));
}
/* Else, hop_count bottomed out and we discard this one. */
}
} else {
/* Should we send NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK? */
debug_printf(
"NPDU: Unsupported BACnet Protocol Version=%u. Discarded!\n",
(unsigned)pdu[0]);
}
return;
}
+52
View File
@@ -0,0 +1,52 @@
/**
* @file
* @author Steve Karg
* @date October 2019
* @brief Header file for a basic routing NPDU handler
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ROUTING_NPDU_HANDLER_H
#define ROUTING_NPDU_HANDLER_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacdef.h"
#include "bacnet/bacenum.h"
#include "bacnet/apdu.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void routing_npdu_handler(
BACNET_ADDRESS * src,
int *DNET_list,
uint8_t * pdu,
uint16_t pdu_len);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+320
View File
@@ -0,0 +1,320 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include "bacnet/config.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/bactext.h"
/* some demo stuff needed */
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/datalink/datalink.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/services.h"
/** @file s_router.c Methods to send various BACnet Router Network Layer
* Messages. */
/** Initialize an npdu_data structure with given parameters and good defaults,
* and add the Network Layer Message fields.
* The name is a misnomer, as it doesn't do any actual encoding here.
* @see npdu_encode_npdu_data for a simpler version to use when sending an
* APDU instead of a Network Layer Message.
*
* @param npdu_data [out] Returns a filled-out structure with information
* provided by the other arguments and
* good defaults.
* @param network_message_type [in] The type of Network Layer Message.
* @param data_expecting_reply [in] True if message should have a reply.
* @param priority [in] One of the 4 priorities defined in section 6.2.2,
* like B'11' = Life Safety message
*/
void npdu_encode_npdu_network(BACNET_NPDU_DATA *npdu_data,
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
bool data_expecting_reply,
BACNET_MESSAGE_PRIORITY priority)
{
if (npdu_data) {
npdu_data->data_expecting_reply = data_expecting_reply;
npdu_data->protocol_version = BACNET_PROTOCOL_VERSION;
npdu_data->network_layer_message = true; /* false if APDU */
npdu_data->network_message_type = network_message_type; /* optional */
npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */
npdu_data->priority = priority;
npdu_data->hop_count = HOP_COUNT_DEFAULT;
}
}
/** Function to encode and send any supported Network Layer Message.
* The payload for the message is encoded from information in the iArgs[] array.
* The contents of iArgs are are, per message type:
* - 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,
* 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 dst [in/out] If not NULL, contains the destination for the message.
* @param iArgs [in] An optional array of values whose meaning depends on
* the type of message.
* @return Number of bytes sent, or <=0 if no message was sent.
*/
int Send_Network_Layer_Message(BACNET_NETWORK_MESSAGE_TYPE network_message_type,
BACNET_ADDRESS *dst,
int *iArgs)
{
int len = 0;
int pdu_len = 0;
int bytes_sent = 0;
int *pVal = iArgs; /* Start with first value */
bool data_expecting_reply = false;
BACNET_NPDU_DATA npdu_data;
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 == NULL) {
datalink_get_broadcast_address(&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, network_message_type,
data_expecting_reply, MESSAGE_PRIORITY_NORMAL);
/* We don't need src information, since a message can't originate from
* our downstream BACnet network.
*/
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], dst, NULL, &npdu_data);
/* Now encode the optional payload bytes, per message type */
switch (network_message_type) {
case NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK:
if (*pVal >= 0) {
len = encode_unsigned16(
&Handler_Transmit_Buffer[pdu_len], (uint16_t)*pVal);
pdu_len += len;
}
/* else, don't encode a DNET */
break;
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) {
len = encode_unsigned16(
&Handler_Transmit_Buffer[pdu_len], (uint16_t)*pVal);
pdu_len += len;
pVal++;
}
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:
debug_printf("Not sent: %s message unsupported \n",
bactext_network_layer_msg_name(network_message_type));
return 0;
break; /* Will never reach this line */
}
if (dst != NULL) {
debug_printf("Sending %s message to BACnet network %u \n",
bactext_network_layer_msg_name(network_message_type), dst->net);
} else {
debug_printf("Sending %s message to local BACnet network \n",
bactext_network_layer_msg_name(network_message_type));
}
/* Now send the message */
bytes_sent = datalink_send_pdu(
dst, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0) {
int wasErrno = errno; /* preserve the errno */
debug_printf("Failed to send %s message (%s)!\n",
bactext_network_layer_msg_name(network_message_type),
strerror(wasErrno));
}
#endif
return bytes_sent;
}
/** Finds a specific router, or all reachable BACnet networks.
* The response(s) will come in I-am-router-to-network message(s).
* @ingroup NMRC
*
* @param dst [in] If NULL, request will be broadcast to the local BACnet
* network. Optionally may designate a particular router
* destination to respond.
* @param dnet [in] Which BACnet network to request for; if -1, no DNET
* will be sent and the receiving router(s) will send
* their full list of reachable BACnet networks.
*/
void Send_Who_Is_Router_To_Network(BACNET_ADDRESS *dst, int dnet)
{
Send_Network_Layer_Message(
NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK, dst, &dnet);
}
/** Broadcast an I-am-router-to-network message, giving the list of networks
* we can reach.
* The message will be sent to our normal DataLink Layer interface,
* not the routed backend.
* @ingroup NMRC
*
* @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(const int DNET_list[])
{
/* Use a NULL dst here since we want a broadcast MAC address. */
Send_Network_Layer_Message(
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, 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).
* @ingroup NMRC
*
* @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).
* @ingroup NMRC
*
* @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(BACNET_ADDRESS *dst, const int DNET_list[])
{
/* Use a NULL dst here since we want a broadcast MAC address. */
Send_Network_Layer_Message(
NETWORK_MESSAGE_INIT_RT_TABLE, dst, (int *)DNET_list);
}
/** 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).
* @ingroup NMRC
*
* @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(
BACNET_ADDRESS *dst, const int DNET_list[])
{
Send_Network_Layer_Message(
NETWORK_MESSAGE_INIT_RT_TABLE_ACK, dst, (int *)DNET_list);
}
+73
View File
@@ -0,0 +1,73 @@
/**
* @file
* @author Steve Karg
* @date October 2019
* @brief Header file for a basic WritePropertyMultiple service send
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SEND_ROUTER_H
#define SEND_ROUTER_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacapp.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacenum.h"
#include "bacnet/apdu.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void npdu_encode_npdu_network(
BACNET_NPDU_DATA *npdu_data,
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
bool data_expecting_reply,
BACNET_MESSAGE_PRIORITY priority);
int Send_Network_Layer_Message(
BACNET_NETWORK_MESSAGE_TYPE network_message_type,
BACNET_ADDRESS * dst,
int *iArgs);
void Send_Who_Is_Router_To_Network(
BACNET_ADDRESS * dst,
int dnet);
void Send_I_Am_Router_To_Network(
const int DNET_list[]);
void Send_Reject_Message_To_Network(
BACNET_ADDRESS * dst,
uint8_t reject_reason,
int dnet);
void Send_Initialize_Routing_Table(
BACNET_ADDRESS * dst,
const int DNET_list[]);
void Send_Initialize_Routing_Table_Ack(
BACNET_ADDRESS * dst,
const int DNET_list[]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif