示例#1
0
        public static void Convert(BacnetAddress addr, out System.Net.IPEndPoint ep)
        {
            long   ip_address = BitConverter.ToUInt32(addr.adr, 0);
            ushort port       = (ushort)((addr.adr[4] << 8) | (addr.adr[5] << 0));

            ep = new System.Net.IPEndPoint(ip_address, (int)port);
        }
        public int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission,
                        int timeout)
        {
            var frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA0;

            if (_sequenceCounter)
            {
                frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA1;
            }
            _sequenceCounter = !_sequenceCounter;

            //add header
            var fullLength = PTP.Encode(buffer, offset - PTP.PTP_HEADER_LENGTH, frameType, dataLength);

            //wait for send allowed
            if (!_maySend.WaitOne(timeout))
            {
                return(-BacnetMstpProtocolTransport.ETIMEDOUT);
            }

            //debug
            if (StateLogging)
            {
                Trace.WriteLine($"         {frameType}", null);
            }

            //send
            SendWithXonXoff(buffer, offset - HeaderLength, fullLength);
            return(dataLength);
        }
示例#3
0
        public int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, int timeout)
        {
            if (_exclusiveConn == null)
            {
                return(0);
            }

            //add header
            var fullLength = dataLength + HeaderLength;

            Bvlc.Encode(buffer, offset - BVLC.BVLC_HEADER_LENGTH, address.net == 0xFFFF
                ? BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU
                : BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU, fullLength);

            //create end point
            IPEndPoint ep;

            Convert(address, out ep);

            try
            {
                // broadcasts are transported from our local unicast socket also
                return(_exclusiveConn.Send(buffer, fullLength, ep));
            }
            catch
            {
                return(0);
            }
        }
示例#4
0
        public int Send(byte[] buffer, int offset, int data_length, BacnetAddress address, bool wait_for_transmission, int timeout)
        {
            int hdr_offset = 0;

            for (int i = 0; i < 6; i++)
            {
                buffer[hdr_offset++] = address.adr[i];
            }

            // write the source mac address bytes
            for (int i = 0; i < 6; i++)
            {
                buffer[hdr_offset++] = _deviceMac[i];
            }

            // the next 2 bytes are used for the packet length
            buffer[hdr_offset++] = (byte)(((data_length + 3) & 0xFF00) >> 8);
            buffer[hdr_offset++] = (byte)((data_length + 3) & 0xFF);

            // DSAP and SSAP
            buffer[hdr_offset++] = 0x82;
            buffer[hdr_offset++] = 0x82;

            // LLC control field
            buffer[hdr_offset] = 0x03;

            lock (_device)
            {
                _device.SendPacket(buffer, data_length + HeaderLength);
            }

            return(data_length + HeaderLength);
        }
示例#5
0
        public BVLCV6(BacnetIpV6UdpProtocolTransport Transport, int VMAC)
        {
            MyTransport  = Transport;
            BroadcastAdd = MyTransport.GetBroadcastAddress();

            if (VMAC == -1)
            {
                RandomVmac = true;
                new Random().NextBytes(this.VMAC);
                this.VMAC[0] = (byte)((this.VMAC[0] & 0x7F) | 0x40); // ensure 01xxxxxx on the High byte

                // Open with default interface specified, cannot send it or
                // it will generate an uncheckable continuous local loopback
                if (!MyTransport.LocalEndPoint.ToString().Contains("[::]"))
                {
                    SendAddressResolutionRequest(this.VMAC);
                }
                else
                {
                    RandomVmac = false; // back to false avoiding loop back
                }
            }
            else // Device Id is the Vmac Id
            {
                this.VMAC[0] = (byte)((VMAC >> 16) & 0x3F); // ensure the 2 high bits are 0 on the High byte
                this.VMAC[1] = (byte)((VMAC >> 8) & 0xFF);
                this.VMAC[2] = (byte)(VMAC & 0xFF);
                // unicity is guaranteed by the end user !
            }
        }
示例#6
0
        public static void Convert(BacnetAddress addr, out IPEndPoint ep)
        {
            long ipAddress = BitConverter.ToUInt32(addr.adr, 0);
            var  port      = (ushort)((addr.adr[4] << 8) | (addr.adr[5] << 0));

            ep = new IPEndPoint(ipAddress, port);
        }
        public static void Convert(BacnetAddress addr, out IPEndPoint ep)
        {
            var port = (ushort)((addr.adr[16] << 8) | (addr.adr[17] << 0));
            var ipv6 = new byte[16];

            Array.Copy(addr.adr, ipv6, 16);
            ep = new IPEndPoint(new IPAddress(ipv6), port);
        }
示例#8
0
        public static void Convert(BacnetAddress addr, out System.Net.IPEndPoint ep)
        {
            ushort port = (ushort)((addr.adr[16] << 8) | (addr.adr[17] << 0));

            byte[] Ipv6 = new byte[16];
            Array.Copy(addr.adr, Ipv6, 16);
            ep = new System.Net.IPEndPoint(new IPAddress(Ipv6), (int)port);
        }
示例#9
0
 public BacnetAddress GetBroadcastAddress()
 {
     if (BroadcastAddress == null)
     {
         BroadcastAddress = _GetBroadcastAddress();
     }
     return(BroadcastAddress);
 }
示例#10
0
        private StateChanges WaitForReply()
        {
            //fetch message
            var status = GetNextMessage(T_REPLY_TIMEOUT, out var frameType, out var destinationAddress,
                                        out var sourceAddress, out var msgLength);

            if (status == GetMessageStatus.Good)
            {
                try
                {
                    if (destinationAddress == (byte)SourceAddress &&
                        (frameType == BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE ||
                         frameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))
                    {
                        //signal upper layer
                        if (frameType != BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE)
                        {
                            var remoteAddress = new BacnetAddress(BacnetAddressTypes.MSTP, 0, new[] { sourceAddress });
                            try
                            {
                                InvokeMessageRecieved(_localBuffer, MSTP.MSTP_HEADER_LENGTH, msgLength, remoteAddress);
                            }
                            catch (Exception ex)
                            {
                                Log.Error("Exception in MessageRecieved event", ex);
                            }
                        }

                        /* ReceivedReply */
                        return(StateChanges.ReceivedReply);
                    }
                    else if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_REPLY_POSTPONED)
                    {
                        /* ReceivedPostpone */
                        return(StateChanges.ReceivedPostpone);
                    }
                    else
                    {
                        /* ReceivedUnexpectedFrame */
                        return(StateChanges.ReceivedUnexpectedFrame);
                    }
                }
                finally
                {
                    RemoveCurrentMessage(msgLength);
                }
            }

            if (status != GetMessageStatus.Timeout)
            {
                return(StateChanges.InvalidFrame);
            }

            /* ReplyTimeout */
            _frameCount = MaxInfoFrames;
            return(StateChanges.ReplyTimeOut);
            /* InvalidFrame */
        }
示例#11
0
        private void OnAbort(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte invokeId, byte reason, byte[] buffer, int offset, int length)
        {
            if (invokeId != _waitInvokeId)
            {
                return;
            }

            Error = new Exception("Abort from device: " + reason);
        }
示例#12
0
        private void OnSimpleAck(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] data, int dataOffset, int dataLength)
        {
            if (invokeId != _waitInvokeId)
            {
                return;
            }

            _waitHandle.Set();
        }
示例#13
0
        private void OnError(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetErrorClasses errorClass, BacnetErrorCodes errorCode, byte[] buffer, int offset, int length)
        {
            if (invokeId != _waitInvokeId)
            {
                return;
            }

            Error = new Exception("Error from device: " + errorClass + " - " + errorCode);
        }
示例#14
0
 public static void Convert(System.Net.IPEndPoint ep, out BacnetAddress addr)
 {
     byte[] tmp1 = ep.Address.GetAddressBytes();
     byte[] tmp2 = BitConverter.GetBytes((ushort)ep.Port);
     Array.Reverse(tmp2);
     Array.Resize <byte>(ref tmp1, tmp1.Length + tmp2.Length);
     Array.Copy(tmp2, 0, tmp1, tmp1.Length - tmp2.Length, tmp2.Length);
     addr = new BacnetAddress(BacnetAddressTypes.IPV6, 0, tmp1);
 }
        public static void Convert(IPEndPoint ep, out BacnetAddress address)
        {
            var tmp1 = ep.Address.GetAddressBytes();
            var tmp2 = BitConverter.GetBytes((ushort)ep.Port);

            Array.Reverse(tmp2);
            Array.Resize(ref tmp1, tmp1.Length + tmp2.Length);
            Array.Copy(tmp2, 0, tmp1, tmp1.Length - tmp2.Length, tmp2.Length);
            address = new BacnetAddress(BacnetAddressTypes.IP, 0, tmp1);
        }
示例#16
0
        private void OnSegment(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte sequenceNumber, bool first, bool moreFollows, byte[] buffer, int offset, int length)
        {
            if (invokeId != _waitInvokeId)
            {
                return;
            }

            Segmented = true;
            _waitHandle.Set();
        }
示例#17
0
 public DeviceReportingRecipient(BacnetBitString weekofDay, DateTime fromTime, DateTime toTime, BacnetAddress adr, uint processIdentifier, bool ackRequired, BacnetBitString evenType)
 {
     Id                     = new BacnetObjectId();
     WeekofDay              = weekofDay;
     this.toTime            = toTime;
     this.fromTime          = fromTime;
     this.adr               = adr;
     this.processIdentifier = processIdentifier;
     Ack_Required           = ackRequired;
     this.evenType          = evenType;
 }
示例#18
0
        void OnPacketArrival(RawCapture packet)
        {
            // don't process any packet too short to not be valid
            if (packet.Data.Length <= 17)
            {
                return;
            }

            byte[] buffer = packet.Data;
            int    offset = 0;

            int  length;
            byte dsap, ssap, control;

            // Got frames send by me, not for me, not broadcast
            byte[] dest = Mac(buffer, offset);
            if (!_isOutboundPacket(dest, 0) && (dest[0] != 255))
            {
                return;
            }

            offset += 6;

            // source address
            BacnetAddress Bac_source = new BacnetAddress(BacnetAddressTypes.Ethernet, 0, Mac(buffer, offset));

            offset += 6;

            // len
            length  = buffer[offset] * 256 + buffer[offset + 1];
            offset += 2;

            // 3 bytes LLC hearder
            dsap    = buffer[offset++];
            ssap    = buffer[offset++];
            control = buffer[offset++];

            length -= 3; // Bacnet content length eq. ethernet lenght minus LLC header length

            // don't process non-BACnet packets
            if (dsap != 0x82 || ssap != 0x82 || control != 0x03)
            {
                return;
            }

            if (MessageRecieved != null)
            {
                MessageRecieved(this, buffer, HeaderLength, length, Bac_source);
            }
        }
示例#19
0
        // checked if device is routed by curent equipement
        public bool IsMyRouter(BacnetAddress device)
        {
            if ((device.RoutedSource == null) || (RoutedSource != null))
            {
                return(false);
            }

            if (adr.Length != device.adr.Length)
            {
                return(false);
            }

            return(!adr.Where((t, i) => t != device.adr[i]).Any());
        }
示例#20
0
 public BacnetAsyncResult(BacnetClient comm, BacnetAddress adr, byte invokeId, byte[] transmitBuffer, int transmitLength, bool waitForTransmit, int transmitTimeout)
 {
     _transmitTimeout    = transmitTimeout;
     _addr               = adr;
     _waitForTransmit    = waitForTransmit;
     _transmitBuffer     = transmitBuffer;
     _transmitLength     = transmitLength;
     _comm               = comm;
     _waitInvokeId       = invokeId;
     _comm.OnComplexAck += OnComplexAck;
     _comm.OnError      += OnError;
     _comm.OnAbort      += OnAbort;
     _comm.OnSimpleAck  += OnSimpleAck;
     _comm.OnSegment    += OnSegment;
     _waitHandle         = new ManualResetEvent(false);
 }
示例#21
0
        private void OnPacketArrival(RawCapture packet)
        {
            // don't process any packet too short to not be valid
            if (packet.Data.Length <= 17)
            {
                return;
            }

            var buffer = packet.Data;
            var offset = 0;

            // Got frames send by me, not for me, not broadcast
            var dest = Mac(buffer, offset);

            if (!_isOutboundPacket(dest, 0) && dest[0] != 255)
            {
                return;
            }

            offset += 6;

            // source address
            var bacSource = new BacnetAddress(BacnetAddressTypes.Ethernet, 0, Mac(buffer, offset));

            offset += 6;

            // len
            var length = buffer[offset] * 256 + buffer[offset + 1];

            offset += 2;

            // 3 bytes LLC hearder
            var dsap    = buffer[offset++];
            var ssap    = buffer[offset++];
            var control = buffer[offset++];

            length -= 3; // Bacnet content length eq. ethernet lenght minus LLC header length

            // don't process non-BACnet packets
            if (dsap != 0x82 || ssap != 0x82 || control != 0x03)
            {
                return;
            }

            InvokeMessageRecieved(buffer, HeaderLength, length, bacSource);
        }
示例#22
0
        private void OnComplexAck(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length)
        {
            if (invokeId != _waitInvokeId)
            {
                return;
            }

            Segmented = false;
            Result    = new byte[length];

            if (length > 0)
            {
                Array.Copy(buffer, offset, Result, 0, length);
            }

            //notify waiter even if segmented
            _waitHandle.Set();
        }
        public int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission,
                        int timeout)
        {
            if (_exclusiveConn == null)
            {
                return(0);
            }

            //add header
            var fullLength = dataLength + HeaderLength;

            if (address.net == 0xFFFF)
            {
                var newBuffer = new byte[fullLength - 3];
                Array.Copy(buffer, 3, newBuffer, 0, fullLength - 3);
                fullLength -= 3;
                buffer      = newBuffer;
                Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH,
                            BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU, fullLength, address);
            }
            else
            {
                Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH, BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU,
                            fullLength, address);
            }

            // create end point
            IPEndPoint ep;

            Convert(address, out ep);

            try
            {
                // send
                // multicast are transported from our local unicast socket also
                return(_exclusiveConn.Send(buffer, fullLength, ep));
            }
            catch
            {
                return(0);
            }
        }
示例#24
0
        public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address,
                                 bool waitForTransmission, int timeout)
        {
            if (SourceAddress == -1)
            {
                throw new Exception("Source address must be set up before sending messages");
            }

            //add to queue
            var function  = NPDU.DecodeFunction(buffer, offset);
            var frameType = (function & BacnetNpduControls.ExpectingReply) == BacnetNpduControls.ExpectingReply
                                ? BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY
                                : BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
            var copy = new byte[dataLength + MSTP.MSTP_HEADER_LENGTH + 2];

            Array.Copy(buffer, offset, copy, MSTP.MSTP_HEADER_LENGTH, dataLength);
            var f = new MessageFrame(frameType, address.adr[0], copy, dataLength);

            lock (_sendQueue)
                _sendQueue.AddLast(f);
            if (_reply == null)
            {
                _reply = f;
                _replyMutex.Set();
            }

            if (!waitForTransmission)
            {
                return(dataLength);
            }

            //wait for message to be sent
            if (!f.SendMutex.WaitOne(timeout))
            {
                return(-ETIMEDOUT);
            }

            return(dataLength);
        }
示例#25
0
        public DeviceReportingRecipient(BacnetValue v0, BacnetValue v1, BacnetValue v2, BacnetValue v3, BacnetValue v4, BacnetValue v5, BacnetValue v6)
        {
            Id  = new BacnetObjectId();
            adr = null;

            WeekofDay = (BacnetBitString)v0.Value;
            fromTime  = (DateTime)v1.Value;
            toTime    = (DateTime)v2.Value;
            if (v3.Value is BacnetObjectId)
            {
                Id = (BacnetObjectId)v3.Value;
            }
            else
            {
                var netdescr = (BacnetValue[])v3.Value;
                var s        = (ushort)(uint)netdescr[0].Value;
                var b        = (byte[])netdescr[1].Value;
                adr = new BacnetAddress(BacnetAddressTypes.IP, s, b);
            }
            processIdentifier = (uint)v4.Value;
            Ack_Required      = (bool)v5.Value;
            evenType          = (BacnetBitString)v6.Value;
        }
示例#26
0
 public BacnetAddress GetBroadcastAddress()
 {
     return(_broadcastAddress ?? (_broadcastAddress = _GetBroadcastAddress()));
 }
示例#27
0
 protected void InvokeMessageRecieved(byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress)
 {
     MessageRecieved?.Invoke(this, buffer, offset, msgLength, remoteAddress);
 }
示例#28
0
        // Decode is called each time an Udp Frame is received
        public int Decode(byte[] buffer, int offset, out BacnetBvlcV6Functions function, out int msg_length, System.Net.IPEndPoint sender, BacnetAddress remote_address)
        {
            // offset always 0, we are the first after udp
            // and a previous test by the caller guaranteed at least 4 bytes into the buffer

            function   = (BacnetBvlcV6Functions)buffer[1];
            msg_length = (buffer[2] << 8) | (buffer[3] << 0);
            if ((buffer[0] != BVLL_TYPE_BACNET_IPV6) || (buffer.Length != msg_length))
            {
                return(-1);
            }

            Array.Copy(buffer, 4, remote_address.VMac, 0, 3);

            switch (function)
            {
            case BacnetBvlcV6Functions.BVLC_RESULT:
                return(9);      // only for the upper layers

            case BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU:
                return(10);      // only for the upper layers

            case BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU:
                // Send to FDs & BBMDs, not broadcast or it will be made twice !
                if (BBMD_FD_ServiceActivated == true)
                {
                    Forward_NPDU(buffer, msg_length, false, sender, remote_address);
                }
                return(7);      // also for the upper layers

            case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION:
                // need to verify that the VMAC is mine
                if ((VMAC[0] == buffer[7]) && (VMAC[1] == buffer[8]) && (VMAC[2] == buffer[9]))
                {
                    // coming from myself ? avoid loopback
                    if (!MyTransport.LocalEndPoint.Equals(sender))
                    {
                        SendAddressResolutionAck(sender, remote_address.VMac, BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK);
                    }
                }
                return(0);     // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_FORWARDED_ADDRESS_RESOLUTION:
                // no need to verify the target VMAC, should be OK
                SendAddressResolutionAck(sender, remote_address.VMac, BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK);
                return(0);                                          // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK: // adresse conflict
                if ((VMAC[0] == buffer[4]) && (VMAC[1] == buffer[5]) && (VMAC[2] == buffer[6]) && RandomVmac)
                {
                    new Random().NextBytes(this.VMAC);
                    this.VMAC[0] = (byte)((this.VMAC[0] & 0x7F) | 0x40);
                    SendAddressResolutionRequest(VMAC);
                }
                return(0);     // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION:
                SendAddressResolutionAck(sender, remote_address.VMac, BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK);
                return(0);     // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK:
                return(0);     // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU:
                if (MyTransport.LocalEndPoint.Equals(sender))
                {
                    return(0);
                }

                // certainly TODO the same code I've put in the IPV4 implementation
                if ((BBMD_FD_ServiceActivated == true) && (msg_length >= 25))
                {
                    bool ret;
                    lock (BBMDs)
                        ret = BBMDs.Exists(items => items.Equals(sender));  // verify sender presence in the table
                                                                            // avoid also loopback

                    if (ret)                                                // message from a know BBMD address, sent to all FDs and broadcast
                    {
                        SendToFDs(buffer, msg_length);                      // send without modification
                        // Assume all BVLC_FORWARDED_NPDU are directly sent to me in the
                        // unicast mode and not by the way of the multicast address
                        // If not, it's not really a big problem, devices on the local net will
                        // receive two times the message (after all it's just WhoIs, Iam, ...)
                        IPEndPoint ep;
                        BacnetIpV6UdpProtocolTransport.Convert(BroadcastAdd, out ep);
                        MyTransport.Send(buffer, msg_length, ep);
                    }
                }
                return(25);     // for the upper layers

            case BacnetBvlcV6Functions.BVLC_REGISTER_FOREIGN_DEVICE:
                if ((BBMD_FD_ServiceActivated == true) && (msg_length == 9))
                {
                    int TTL = (buffer[7] << 8) + buffer[8];                        // unit is second
                    RegisterForeignDevice(sender, TTL);
                    SendResult(sender, BacnetBvlcV6Results.SUCCESSFUL_COMPLETION); // ack
                }
                return(0);                                                         // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
                return(0);     // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_SECURE_BVLC:
                return(0);                                                   // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD
                if (BBMD_FD_ServiceActivated == true)
                {
                    // Send to FDs except the sender, BBMDs and broadcast
                    lock (ForeignDevices)
                    {
                        if (ForeignDevices.Exists(item => item.Key.Equals(sender)))     // verify previous registration
                        {
                            Forward_NPDU(buffer, msg_length, true, sender, remote_address);
                        }
                        else
                        {
                            SendResult(sender, BacnetBvlcV6Results.DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
                        }
                    }
                }
                return(0);     // not for the upper layers

            // error encoding function or experimental one
            default:
                return(-1);
            }
        }
示例#29
0
        // Encode is called by internal services if the BBMD is also an active device
        public int Encode(byte[] buffer, int offset, BacnetBvlcV6Functions function, int msg_length, BacnetAddress address)
        {
            // offset always 0, we are the first after udp

            First7BytesHeaderEncode(buffer, function, msg_length);

            // BBMD service
            if ((function == BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU) && (BBMD_FD_ServiceActivated == true))
            {
                Net.IPEndPoint me = MyTransport.LocalEndPoint;
                BacnetAddress  Bacme;
                BacnetIpV6UdpProtocolTransport.Convert(me, out Bacme);
                Array.Copy(VMAC, Bacme.VMac, 3);

                Forward_NPDU(buffer, msg_length, false, me, Bacme); // send to all BBMDs and FDs

                return(7);                                          // ready to send
            }
            if (function == BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU)
            {
                buffer[7] = address.VMac[0];
                buffer[8] = address.VMac[1];
                buffer[9] = address.VMac[2];
                return(10); // ready to send
            }

            return(0); // ?
        }
示例#30
0
        // Never tested
        private void Forward_NPDU(byte[] buffer, int msg_length, bool ToGlobalBroadcast, Net.IPEndPoint EPsender, BacnetAddress BacSender)
        {
            // Forms the forwarded NPDU from the original (broadcast npdu), and send it to all

            // copy, 18 bytes shifted (orignal bvlc header : 7 bytes, new one : 25 bytes)
            byte[] b = new byte[msg_length + 18];    // normaly only 'small' frames are present here, so no need to check if it's to big for Udp
            Array.Copy(buffer, 0, b, 18, msg_length);

            // 7 bytes for the BVLC Header, with the embedded 6 bytes IP:Port of the original sender
            First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU, msg_length + 18);
            // replace my Vmac by the orignal source vmac
            Array.Copy(BacSender.VMac, 0, b, 4, 3);
            // Add IpV6 endpoint
            Array.Copy(BacSender.adr, 0, b, 7, 18);
            // Send To BBMD
            SendToBBMDs(b, msg_length + 18);
            // Send To FD, except the sender
            SendToFDs(b, msg_length + 18, EPsender);
            // Broadcast if required
            if (ToGlobalBroadcast == true)
            {
                IPEndPoint ep;
                BacnetIpV6UdpProtocolTransport.Convert(BroadcastAdd, out ep);
                MyTransport.Send(b, msg_length + 18, ep);
            }
        }