refactored the BACnet/IP for each of the ports

This commit is contained in:
skarg
2005-08-12 15:44:42 +00:00
parent 81ce0fef85
commit bc21625461
14 changed files with 373 additions and 440 deletions
+2 -1
View File
@@ -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 \
@@ -36,7 +36,7 @@
#include <stdbool.h> // 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 */
+7 -2
View File
@@ -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
+1 -2
View File
@@ -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],
+1
View File
@@ -36,6 +36,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "bacdef.h"
int iam_encode_apdu(
uint8_t *apdu,
+91
View File
@@ -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 <stdint.h> // for standard integer types uint8_t etc.
#include <stdbool.h> // 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;
}
+1
View File
@@ -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
+2 -1
View File
@@ -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 \
Binary file not shown.
+95
View File
@@ -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 <stdio.h>
#include <stdlib.h>
#include <stdint.h> // for standard integer types uint8_t etc.
#include <stdbool.h> // 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;
}
-373
View File
@@ -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 <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <stdint.h> // for standard integer types uint8_t etc.
#include <stdbool.h> // 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;
}
+111 -6
View File
@@ -29,6 +29,8 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#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
+33
View File
@@ -0,0 +1,33 @@
/**************************************************************************
*
* 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.
*
*********************************************************************/
#ifndef NET_H
#define NET_H
#include <winsock2.h>
#define close closesocket
#endif