diff --git a/bacnet-stack/Makefile b/bacnet-stack/Makefile index 7749fd5c..2b2b43d4 100644 --- a/bacnet-stack/Makefile +++ b/bacnet-stack/Makefile @@ -12,7 +12,8 @@ CFLAGS = -Wall -I. -Iports/linux -g -DBACDL_BIP=1 SRCS = ports/linux/main.c \ ports/linux/ethernet.c \ - ports/linux/bip.c \ + ports/linux/bip-init.c \ + bip.c \ dlmstp.c \ handlers.c \ bacdcode.c \ diff --git a/bacnet-stack/ports/linux/bip.c b/bacnet-stack/bip.c similarity index 85% rename from bacnet-stack/ports/linux/bip.c rename to bacnet-stack/bip.c index 6469b4ed..6cd3b70f 100644 --- a/bacnet-stack/ports/linux/bip.c +++ b/bacnet-stack/bip.c @@ -36,7 +36,7 @@ #include // for the standard bool type. #include "bacdcode.h" #include "bip.h" -#include "net.h" +#include "net.h" // custom per port static int BIP_Socket = -1; /* port to use - stored in network byte order */ @@ -46,6 +46,11 @@ static struct in_addr BIP_Address; /* Broadcast Address */ static struct in_addr BIP_Broadcast_Address; +void bip_set_socket(int sock_fd) +{ + BIP_Socket = sock_fd; +} + bool bip_valid(void) { return (BIP_Socket != -1); @@ -57,7 +62,7 @@ void bip_cleanup(void) close(BIP_Socket); BIP_Socket = -1; - return; + return; } static void set_network_address(struct in_addr *net_address, @@ -72,80 +77,49 @@ static void set_network_address(struct in_addr *net_address, long_data.byte[1] = octet2; long_data.byte[2] = octet3; long_data.byte[3] = octet4; - + net_address->s_addr = long_data.value; } void bip_set_address( - uint8_t octet1, - uint8_t octet2, - uint8_t octet3, + uint8_t octet1, + uint8_t octet2, + uint8_t octet3, uint8_t octet4) { set_network_address(&BIP_Address, octet1, octet2, octet3, octet4); } +// Win32 shortcut +void bip_set_addr(struct in_addr *net_address) +{ + BIP_Address.s_addr = htonl(net_address->s_addr); +} + void bip_set_broadcast_address( - uint8_t octet1, - uint8_t octet2, - uint8_t octet3, + uint8_t octet1, + uint8_t octet2, + uint8_t octet3, uint8_t octet4) { set_network_address(&BIP_Broadcast_Address, octet1, octet2, octet3, octet4); } +// Win32 shortcut +void bip_set_ipv4_broadcast_s_addr( + unsigned long address) +{ + BIP_Broadcast_Address.s_addr = address; +} + void bip_set_port(uint16_t port) { BIP_Port = htons(port); } -bool bip_init(void) +uint16_t bip_get_port(void) { - int status = 0; // return from socket lib calls - struct sockaddr_in sin; - int sockopt = 0; - - /* configure standard BACnet/IP receive port */ - bip_set_port(0xBAC0); - - // assumes that the driver has already been initialized - BIP_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (BIP_Socket < 0) - return false; - // Allow us to use the same socket for sending and receiving - // This makes sure that the src port is correct when sending - sockopt = 1; - status = setsockopt(BIP_Socket, SOL_SOCKET, SO_REUSEADDR, - &sockopt, sizeof(sockopt)); - if (status < 0) - { - close(BIP_Socket); - return status; - } - // allow us to send a broadcast - status = setsockopt(BIP_Socket, SOL_SOCKET, SO_BROADCAST, - &sockopt, sizeof(sockopt)); - if (status < 0) - { - close(BIP_Socket); - return status; - } - - // bind the socket to the local port number and IP address - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); - sin.sin_port = BIP_Port; - memset(&(sin.sin_zero), '\0', 8); - status = bind(BIP_Socket, - (const struct sockaddr*)&sin, sizeof(struct sockaddr)); - if (status < 0) - { - close(BIP_Socket); - BIP_Socket = -1; - return false; - } - - return true; + return BIP_Port; } /* function to send a packet out the 802.2 socket */ diff --git a/bacnet-stack/bip.h b/bacnet-stack/bip.h index 3b5b42a7..1a1b42c9 100644 --- a/bacnet-stack/bip.h +++ b/bacnet-stack/bip.h @@ -43,9 +43,13 @@ #define MAX_HEADER (1 + 1 + 2) #define MAX_MPDU (MAX_HEADER+MAX_PDU) -bool bip_valid(void); -void bip_cleanup(void); +// note: define init and cleanup in your ports section bool bip_init(void); + +// normal functions... +void bip_cleanup(void); +void bip_set_socket(int sock_fd); +bool bip_valid(void); void bip_get_broadcast_address( BACNET_ADDRESS *dest); // destination address void bip_get_my_address(BACNET_ADDRESS *my_address); @@ -71,6 +75,7 @@ void bip_set_broadcast_address(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4); void bip_set_port(uint16_t port); +uint16_t bip_get_port(void); void bip_set_interface_name(char *ifname); #endif diff --git a/bacnet-stack/handlers.c b/bacnet-stack/handlers.c index b3022250..d28bddcd 100644 --- a/bacnet-stack/handlers.c +++ b/bacnet-stack/handlers.c @@ -258,7 +258,6 @@ void ReadPropertyHandler( BACNET_READ_PROPERTY_DATA data; int len = 0; int pdu_len = 0; - uint32_t object_instance; BACNET_ADDRESS my_address; bool send = false; bool error = false; @@ -399,7 +398,7 @@ void ReadPropertyHandler( error = true; break; case OBJECT_FILE: - if (bacfile_valid_instance(object_instance)) + if (bacfile_valid_instance(data.object_instance)) { len = bacfile_encode_property_apdu( &Temp_Buf[0], diff --git a/bacnet-stack/iam.h b/bacnet-stack/iam.h index 7425834d..1cadf969 100644 --- a/bacnet-stack/iam.h +++ b/bacnet-stack/iam.h @@ -36,6 +36,7 @@ #include #include +#include "bacdef.h" int iam_encode_apdu( uint8_t *apdu, diff --git a/bacnet-stack/ports/linux/bip-init.c b/bacnet-stack/ports/linux/bip-init.c new file mode 100644 index 00000000..51bc21de --- /dev/null +++ b/bacnet-stack/ports/linux/bip-init.c @@ -0,0 +1,91 @@ +/*####COPYRIGHTBEGIN#### + ------------------------------------------- + Copyright (C) 2005 Steve Karg + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + The Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA. + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile + this file and link it with other works to produce a work based + on this file, this file does not by itself cause the resulting + work to be covered by the GNU General Public License. However + the source code for this file must still be made available in + accordance with section (3) of the GNU General Public License. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + ------------------------------------------- +####COPYRIGHTEND####*/ + +#include // for standard integer types uint8_t etc. +#include // for the standard bool type. +#include "bacdcode.h" +#include "bip.h" +#include "net.h" + +bool bip_init(void) +{ + int status = 0; // return from socket lib calls + struct sockaddr_in sin; + int sockopt = 0; + int sock_fd = -1; + + // assumes that the driver has already been initialized + sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + bip_set_socket(sock_fd); + if (sock_fd < 0) + return false; + // Allow us to use the same socket for sending and receiving + // This makes sure that the src port is correct when sending + sockopt = 1; + status = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, + &sockopt, sizeof(sockopt)); + if (status < 0) + { + close(sock_fd); + bip_set_socket(-1); + return status; + } + // allow us to send a broadcast + status = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, + &sockopt, sizeof(sockopt)); + if (status < 0) + { + close(sock_fd); + bip_set_socket(-1); + return status; + } + + // bind the socket to the local port number and IP address + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = bip_get_port(); + memset(&(sin.sin_zero), '\0', 8); + status = bind(sock_fd, + (const struct sockaddr*)&sin, sizeof(struct sockaddr)); + if (status < 0) + { + close(sock_fd); + bip_set_socket(-1); + return false; + } + + return true; +} + + diff --git a/bacnet-stack/ports/linux/main.c b/bacnet-stack/ports/linux/main.c index f1c87148..459d599b 100644 --- a/bacnet-stack/ports/linux/main.c +++ b/bacnet-stack/ports/linux/main.c @@ -314,6 +314,7 @@ int main(int argc, char *argv[]) #endif #ifdef BACDL_BIP Init_Network("eth0"); + bip_set_port(0xBAC0); if (!bip_init()) return 1; #endif diff --git a/bacnet-stack/ports/rtos32/bip.c b/bacnet-stack/ports/rtos32/bip-init.c similarity index 100% rename from bacnet-stack/ports/rtos32/bip.c rename to bacnet-stack/ports/rtos32/bip-init.c diff --git a/bacnet-stack/ports/rtos32/makefile.mak b/bacnet-stack/ports/rtos32/makefile.mak index 777604da..f5ac8906 100644 --- a/bacnet-stack/ports/rtos32/makefile.mak +++ b/bacnet-stack/ports/rtos32/makefile.mak @@ -26,8 +26,9 @@ DEFINES = -DDOC;BACDL_BIP=1 #DEFINES = -DDOC;BACDL_ETHERNET=1 #DEFINES = -DDOC;BACDL_MSTP=1 -SRCS = init.c main.c ethernet.c bip.c \ +SRCS = init.c main.c ethernet.c bip-init.c \ rs485.c \ + ..\..\bip.c \ ..\..\mstp.c \ ..\..\crc.c \ ..\..\handlers.c \ diff --git a/bacnet-stack/ports/win32/bacnet.ide b/bacnet-stack/ports/win32/bacnet.ide index 1c93f152..5eda6d06 100644 Binary files a/bacnet-stack/ports/win32/bacnet.ide and b/bacnet-stack/ports/win32/bacnet.ide differ diff --git a/bacnet-stack/ports/win32/bip-init.c b/bacnet-stack/ports/win32/bip-init.c new file mode 100644 index 00000000..2ac9aed6 --- /dev/null +++ b/bacnet-stack/ports/win32/bip-init.c @@ -0,0 +1,95 @@ +/*####COPYRIGHTBEGIN#### + ------------------------------------------- + Copyright (C) 2005 Steve Karg + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + The Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA. + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile + this file and link it with other works to produce a work based + on this file, this file does not by itself cause the resulting + work to be covered by the GNU General Public License. However + the source code for this file must still be made available in + accordance with section (3) of the GNU General Public License. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + ------------------------------------------- +####COPYRIGHTEND####*/ + +#define WIN32_LEAN_AND_MEAN +#define STRICT + +#include +#include +#include // for standard integer types uint8_t etc. +#include // for the standard bool type. +#include "bacdcode.h" +#include "bip.h" +#include "net.h" + +bool bip_init(void) +{ + int rv = 0; // return from socket lib calls + struct sockaddr_in sin = {-1}; + int value = 1; + int sock_fd = -1; + + // assumes that the driver has already been initialized + sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + bip_set_socket(sock_fd); + if (sock_fd < 0) + return false; + + // Allow us to use the same socket for sending and receiving + // This makes sure that the src port is correct when sending + rv = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, + (char *)&value, sizeof(value)); + if (rv < 0) + { + close(sock_fd); + bip_set_socket(-1); + return false; + } + // allow us to send a broadcast + rv = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, + (char *)&value, sizeof(value)); + if (rv < 0) + { + close(sock_fd); + bip_set_socket(-1); + return false; + } + + // bind the socket to the local port number and IP address + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = bip_get_port(); + memset(&(sin.sin_zero), '\0', 8); + rv = bind(sock_fd, + (const struct sockaddr*)&sin, sizeof(struct sockaddr)); + if (rv < 0) + { + close(sock_fd); + bip_set_socket(-1); + return false; + } + + return true; +} + diff --git a/bacnet-stack/ports/win32/bip.c b/bacnet-stack/ports/win32/bip.c deleted file mode 100644 index ec2658ce..00000000 --- a/bacnet-stack/ports/win32/bip.c +++ /dev/null @@ -1,373 +0,0 @@ -/*####COPYRIGHTBEGIN#### - ------------------------------------------- - Copyright (C) 2005 Steve Karg - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - The Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA. - - As a special exception, if other files instantiate templates or - use macros or inline functions from this file, or you compile - this file and link it with other works to produce a work based - on this file, this file does not by itself cause the resulting - work to be covered by the GNU General Public License. However - the source code for this file must still be made available in - accordance with section (3) of the GNU General Public License. - - This exception does not invalidate any other reasons why a work - based on this file might be covered by the GNU General Public - License. - ------------------------------------------- -####COPYRIGHTEND####*/ - -#define WIN32_LEAN_AND_MEAN -#define STRICT - -#include -#include -#include -#include // for standard integer types uint8_t etc. -#include // for the standard bool type. -#include "bacdcode.h" -#include "bip.h" - -#define close closesocket - -static int BIP_Socket = -1; -/* port to use - stored in network byte order */ -static uint16_t BIP_Port = 0; -/* IP Address - stored in network byte order */ -static struct in_addr BIP_Address; -/* Broadcast Address */ -static struct in_addr BIP_Broadcast_Address; -/* Subnet Mask */ -static struct in_addr BIP_Subnet_Mask; - -bool bip_valid(void) -{ - return (BIP_Socket != -1); -} - -void bip_cleanup(void) -{ - if (bip_valid()) - close(BIP_Socket); - BIP_Socket = -1; - - return; -} - -static void set_network_address(struct in_addr *net_address, - uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) -{ - union { - uint8_t byte[4]; - uint32_t value; - } long_data = {{0}}; - - long_data.byte[0] = octet1; - long_data.byte[1] = octet2; - long_data.byte[2] = octet3; - long_data.byte[3] = octet4; - - net_address->s_addr = htonl(long_data.value); -} - -void bip_set_address(uint8_t octet1, uint8_t octet2, - uint8_t octet3, uint8_t octet4) -{ - set_network_address(&BIP_Address, octet1, octet2, octet3, octet4); -} - -void bip_set_addr(struct in_addr *net_address) -{ - BIP_Address.s_addr = htonl(net_address->s_addr); -} - -void bip_set_broadcast_address(uint8_t octet1, uint8_t octet2, - uint8_t octet3, uint8_t octet4) -{ - set_network_address(&BIP_Broadcast_Address, - octet1, octet2, octet3, octet4); -} - -void bip_set_subnet_mask(uint8_t octet1, uint8_t octet2, - uint8_t octet3, uint8_t octet4) -{ - set_network_address(&BIP_Subnet_Mask, - octet1, octet2, octet3, octet4); -} - -void bip_set_port(uint16_t port) -{ - BIP_Port = htons(port); -} - -bool bip_init(void) -{ - int rv = 0; // return from socket lib calls - struct sockaddr_in sin = {-1}; - int value = 1; - - /* local broadcast address */ - BIP_Broadcast_Address.s_addr = INADDR_BROADCAST; - /* configure standard BACnet/IP port */ - bip_set_port(0xBAC0); - - // assumes that the driver has already been initialized - BIP_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (BIP_Socket < 0) - return false; - - // Allow us to use the same socket for sending and receiving - // This makes sure that the src port is correct when sending - rv = setsockopt(BIP_Socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&value, sizeof(value)); - if (rv < 0) - { - close(BIP_Socket); - BIP_Socket = -1; - return false; - } - // allow us to send a broadcast - rv = setsockopt(BIP_Socket, SOL_SOCKET, SO_BROADCAST, - (char *)&value, sizeof(value)); - if (rv < 0) - { - close(BIP_Socket); - BIP_Socket = -1; - return false; - } - - // bind the socket to the local port number and IP address - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); - sin.sin_port = BIP_Port; - memset(&(sin.sin_zero), '\0', 8); - rv = bind(BIP_Socket, - (const struct sockaddr*)&sin, sizeof(struct sockaddr)); - if (rv < 0) - { - close(BIP_Socket); - BIP_Socket = -1; - return false; - } - - return true; -} - -/* function to send a packet out the BACnet/IP socket (Annex J) */ -/* returns number of bytes sent on success, negative number on failure */ -static int bip_send( - struct sockaddr_in *bip_dest, - uint8_t *pdu, // any data to be sent - may be null - unsigned pdu_len) // number of bytes of data -{ - int bytes = 0; - uint8_t mtu[MAX_MPDU] = { 0 }; - int mtu_len = 0; - int i = 0; - - // assumes that the driver has already been initialized - if (BIP_Socket < 0) - return BIP_Socket; - - mtu[0] = 0x81; /* BVLL for BACnet/IP */ - if (bip_dest->sin_addr.s_addr == BIP_Broadcast_Address.s_addr) - mtu[1] = 0x0B; /* Original-Broadcast-NPDU */ - else - mtu[1] = 0x0A; /* Original-Unicast-NPDU */ - mtu_len = 2; - mtu_len += encode_unsigned16(&mtu[mtu_len], pdu_len + 4 /*inclusive*/); - memcpy(&mtu[mtu_len], pdu, pdu_len); - mtu_len += pdu_len; - - /* Send the packet */ - bytes = sendto(BIP_Socket, (char *)mtu, mtu_len, 0, - (struct sockaddr *)bip_dest, - sizeof(struct sockaddr)); - - return bytes; -} - -/* function to send a packet out the BACnet/IP socket (Annex J) */ -/* returns number of bytes sent on success, negative number on failure */ -int bip_send_pdu( - BACNET_ADDRESS *dest, // destination address - uint8_t *pdu, // any data to be sent - may be null - unsigned pdu_len) // number of bytes of data -{ - int i = 0; // counter - struct sockaddr_in bip_dest; - uint32_t network_address = 0; - uint16_t network_port = 0; - - /* load destination IP address */ - bip_dest.sin_family = AF_INET; - if (dest->mac_len == 6) - { - (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); - } - /* broadcast */ - else if (dest->mac_len == 0) - { - bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr; - bip_dest.sin_port = BIP_Port; - memset(&(bip_dest.sin_zero), '\0', 8); - } - else - return -1; - - /* function to send a packet out the BACnet/IP socket */ - /* returns 1 on success, 0 on failure */ - return bip_send(&bip_dest, // destination address - pdu, // any data to be sent - may be null - pdu_len); // number of bytes of data -} - -// receives a BACnet/IP packet -// returns the number of octets in the PDU, or zero on failure -uint16_t bip_receive( - BACNET_ADDRESS *src, // source address - uint8_t *pdu, // PDU data - uint16_t max_pdu, // amount of space available in the PDU - unsigned timeout) // number of milliseconds to wait for a packet -{ - int received_bytes; - uint8_t buf[MAX_MPDU] = {0}; // data - uint16_t pdu_len = 0; // return value - fd_set read_fds; - int max; - struct timeval select_timeout; - struct sockaddr_in sin = {-1}; - int sin_len = sizeof(sin); - - /* Make sure the socket is open */ - if (BIP_Socket < 0) - return 0; - - /* we could just use a non-blocking socket, but that consumes all - the CPU time. We can use a timeout; it is only supported as - a select. */ - if (timeout >= 1000) - { - select_timeout.tv_sec = timeout / 1000; - select_timeout.tv_usec = - 1000 * (timeout - select_timeout.tv_sec * 1000); - } - else - { - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 1000 * timeout; - } - FD_ZERO(&read_fds); - FD_SET(BIP_Socket, &read_fds); - max = BIP_Socket; - /* see if there is a packet for us */ - if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) - received_bytes = recvfrom(BIP_Socket, - (char *)&buf[0], MAX_MPDU, 0, - (struct sockaddr *)&sin, &sin_len); - else - return 0; - - /* See if there is a problem */ - if (received_bytes < 0) { - return 0; - } - - /* no problem, just no bytes */ - if (received_bytes == 0) - return 0; - - /* the signature of a BACnet/IP packet */ - if (buf[0] != 0x81) - return 0; - /* Original-Broadcast-NPDU or Original-Unicast-NPDU */ - if ((buf[1] == 0x0B) || (buf[1] == 0x0A)) - { - if (sin.sin_addr.s_addr == BIP_Address.s_addr) - pdu_len = 0; - else - { - // copy the source address - src->mac_len = 6; - (void)encode_unsigned32(&src->mac[0], - sin.sin_addr.s_addr); - (void)encode_unsigned16(&src->mac[4], - sin.sin_port); - // FIXME: check destination address - // see if it is broadcast or for us - /* decode the length of the PDU - length is inclusive of BVLC */ - (void)decode_unsigned16(&buf[2],&pdu_len); - /* copy the buffer into the PDU */ - pdu_len -= 4; /* BVLC header */ - if (pdu_len < max_pdu) - memmove(&pdu[0],&buf[4],pdu_len); - // ignore packets that are too large - // clients should check my max-apdu first - else - pdu_len = 0; - } - } - - return pdu_len; -} - -void bip_get_my_address(BACNET_ADDRESS *my_address) -{ - int i = 0; - - my_address->mac_len = 6; - (void)encode_unsigned32(&my_address->mac[0], - BIP_Address.s_addr); - (void)encode_unsigned16(&my_address->mac[4], - BIP_Port); - my_address->net = 0; /* local only, no routing */ - my_address->len = 0; /* no SLEN */ - for (i = 0; i < MAX_MAC_LEN; i++) - { - /* no SADR */ - my_address->adr[i] = 0; - } - - return; -} - -void bip_get_broadcast_address( - BACNET_ADDRESS *dest) // destination address -{ - int i = 0; // counter - - if (dest) - { - dest->mac_len = 6; - (void)encode_unsigned32(&dest->mac[0], - BIP_Broadcast_Address.s_addr); - (void)encode_unsigned16(&dest->mac[4], - BIP_Port); - dest->net = BACNET_BROADCAST_NETWORK; - dest->len = 0; /* no SLEN */ - for (i = 0; i < MAX_MAC_LEN; i++) - { - /* no SADR */ - dest->adr[i] = 0; - } - } - - return; -} diff --git a/bacnet-stack/ports/win32/main.c b/bacnet-stack/ports/win32/main.c index 502dcd7d..9b68d41c 100644 --- a/bacnet-stack/ports/win32/main.c +++ b/bacnet-stack/ports/win32/main.c @@ -29,6 +29,8 @@ #include #include #include +#include "iam.h" +#include "address.h" #include "config.h" #include "bacdef.h" #include "npdu.h" @@ -40,6 +42,89 @@ // buffer used for receive static uint8_t Rx_Buf[MAX_MPDU] = {0}; +static void Read_Properties(void) +{ + uint32_t device_id = 0; + unsigned max_apdu = 0; + BACNET_ADDRESS src; + bool next_device = false; + static unsigned index = 0; + static unsigned property = 0; + // list of required (and some optional) properties in the + // Device Object + const int object_props[] = + { + 75,77,79,112,121,120,70,44,12,98,95,97,96, + 62,107,57,56,119,24,10,11,73,116,64,63,30, + 514,515, + // note: 76 is missing cause we get it special below + -1 + }; + + if (address_count()) + { + if (address_get_by_index(index, &device_id, &max_apdu, &src)) + { + if (object_props[property] < 0) + next_device = true; + else + { + (void)Send_Read_Property_Request( + device_id, // destination device + OBJECT_DEVICE, + device_id, + object_props[property], + BACNET_ARRAY_ALL); + property++; + } + } + else + next_device = true; + if (next_device) + { + index++; + if (index >= MAX_ADDRESS_CACHE) + index = 0; + property = 0; + } + } + + return; +} + +static void LocalIAmHandler( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src) +{ + int len = 0; + uint32_t device_id = 0; + unsigned max_apdu = 0; + int segmentation = 0; + uint16_t vendor_id = 0; + + (void)src; + (void)service_len; + len = iam_decode_service_request( + service_request, + &device_id, + &max_apdu, + &segmentation, + &vendor_id); + fprintf(stderr,"Received I-Am Request"); + if (len != -1) + { + fprintf(stderr," from %u!\n",device_id); + address_add(device_id, + max_apdu, + src); + } + else + fprintf(stderr,"!\n"); + + return; +} + static void Init_Device_Parameters(void) { // configure my initial values @@ -53,13 +138,17 @@ static void Init_Device_Parameters(void) return; } - + static void Init_Service_Handlers(void) { // we need to handle who-is to support dynamic device binding apdu_set_unconfirmed_handler( SERVICE_UNCONFIRMED_WHO_IS, WhoIsHandler); + apdu_set_unconfirmed_handler( + SERVICE_UNCONFIRMED_I_AM, + LocalIAmHandler); + // set the handler for all the services we don't implement // It is required to send the proper reject message... apdu_set_unrecognized_service_handler_handler( @@ -71,25 +160,32 @@ static void Init_Service_Handlers(void) apdu_set_confirmed_handler( SERVICE_CONFIRMED_WRITE_PROPERTY, WritePropertyHandler); + // handle the data coming back from confirmed requests + apdu_set_confirmed_ack_handler( + SERVICE_CONFIRMED_READ_PROPERTY, + ReadPropertyAckHandler); } /* To fill a need, we invent the gethostaddr() function. */ -long gethostaddr(void) +long gethostaddr(void) { struct hostent *host_ent; char host_name[255]; - - if (gethostname(host_name, sizeof(host_name)) == 0) + + if (gethostname(host_name, sizeof(host_name)) == 0) return -1; if ((host_ent = gethostbyname(host_name)) == NULL) return -1; - + return *(long *)host_ent->h_addr; } extern void bip_set_addr(struct in_addr *net_address); +extern void bip_set_ipv4_broadcast_s_addr( + unsigned long address); + static void NetInitialize(void) // initialize the TCP/IP stack { @@ -104,12 +200,16 @@ static void NetInitialize(void) if (Result != 0) { Code = WSAGetLastError(); - printf("TCP/IP stack initialization failed, error code: %i\n", + printf("TCP/IP stack initialization failed, error code: %i\n", Code); exit(1); } address.s_addr = gethostaddr(); bip_set_addr(&address); + /* local broadcast address */ + bip_set_ipv4_broadcast_s_addr(INADDR_BROADCAST); + /* configure standard BACnet/IP port */ + bip_set_port(0xBAC0); } int main(int argc, char *argv[]) @@ -132,6 +232,7 @@ int main(int argc, char *argv[]) for (;;) { // input + //Read_Properties(); // returns 0 bytes on timeout pdu_len = bip_receive( @@ -153,6 +254,10 @@ int main(int argc, char *argv[]) { I_Am_Request = false; Send_IAm(); + } else if (Who_Is_Request) + { + Who_Is_Request = false; + Send_WhoIs(); } // output diff --git a/bacnet-stack/ports/win32/net.h b/bacnet-stack/ports/win32/net.h new file mode 100644 index 00000000..09e589c2 --- /dev/null +++ b/bacnet-stack/ports/win32/net.h @@ -0,0 +1,33 @@ +/************************************************************************** +* +* Copyright (C) 2005 Steve Karg +* +* 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 NET_H +#define NET_H + +#include + +#define close closesocket + +#endif