Esempio n. 1
0
 private static void First4BytesHeaderEncode(IList <byte> b, BacnetBvlcFunctions function, int msgLength)
 {
     b[0] = BVLL_TYPE_BACNET_IP;
     b[1] = (byte)function;
     b[2] = (byte)((msgLength & 0xFF00) >> 8);
     b[3] = (byte)((msgLength & 0x00FF) >> 0);
 }
Esempio n. 2
0
 private void First4BytesHeaderEncode(byte[] b, BacnetBvlcFunctions function, int msg_length)
 {
     b[0] = BVLL_TYPE_BACNET_IP;
     b[1] = (byte)function;
     b[2] = (byte)(((msg_length) & 0xFF00) >> 8);
     b[3] = (byte)(((msg_length) & 0x00FF) >> 0);
 }
Esempio n. 3
0
        void Bvlc_MessageReceived(System.Net.IPEndPoint sender, BacnetBvlcFunctions function, BacnetBvlcResults result, object data)
        {
            if (!sender.Equals(BBMDep))
            {
                return;         // don't care
            }
            if (InvokeRequired) // GUI call back
            {
                BeginInvoke(new Action <System.Net.IPEndPoint, BacnetBvlcFunctions, BacnetBvlcResults, object>(Bvlc_MessageReceived), new object[] { sender, function, result, data });
                return;
            }

            if (function == BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE_ACK) // an table (could be empty)
            {
                List <Tuple <IPEndPoint, IPAddress> > Entries = (List <Tuple <IPEndPoint, IPAddress> >)data;
                BBMDTable.Rows.Clear();
                foreach (Tuple <IPEndPoint, IPAddress> tpl in Entries)
                {
                    BBMDTable.Rows.Add(new object[] { tpl.Item1.Address.ToString(), tpl.Item1.Port, tpl.Item2.ToString() });
                }
                lbBBMDlInfo.Visible = false;
            }

            if (function == BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE_ACK)
            {
                List <Tuple <IPEndPoint, ushort, ushort> > Entries = (List <Tuple <IPEndPoint, ushort, ushort> >)data;
                FDRTable.Rows.Clear();
                foreach (Tuple <IPEndPoint, ushort, ushort> tpl in Entries)
                {
                    FDRTable.Rows.Add(new object[] { tpl.Item1.ToString(), tpl.Item2.ToString(), tpl.Item3.ToString() });
                }
                lbFDRInfo.Visible = false;
            }
            if ((function == BacnetBvlcFunctions.BVLC_RESULT) && (result == BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION) && (WriteInOperation))
            {
                WriteInOperation = false;
                transport.Bvlc.SendReadBroadCastTable(BBMDep);
            }

            if ((function == BacnetBvlcFunctions.BVLC_RESULT) && (result == BacnetBvlcResults.BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK))
            {
                lbBBMDlInfo.Visible = true;
                lbBBMDlInfo.Text    = "Read Broadcast Table Rejected";
            }
            if ((function == BacnetBvlcFunctions.BVLC_RESULT) && (result == BacnetBvlcResults.BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK) && (WriteInOperation))
            {
                lbBBMDlInfo.Visible = true;
                WriteInOperation    = false;
                lbBBMDlInfo.Text    = "Write Broadcast Table Rejected";
            }
            if ((function == BacnetBvlcFunctions.BVLC_RESULT) && (result == BacnetBvlcResults.BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK))
            {
                lbFDRInfo.Visible = true;
                lbFDRInfo.Text    = "Read FDR Table Rejected";
            }
        }
Esempio n. 4
0
        // Encode is called by internal services if the BBMD is also an active device
        public int Encode(byte[] buffer, int offset, BacnetBvlcFunctions function, int msgLength)
        {
            // offset always 0, we are the first after udp

            // do the job
            First4BytesHeaderEncode(buffer, function, msgLength);

            // optional BBMD service
            if (_bbmdFdServiceActivated && function == BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU)
            {
                var me = _myBbmdTransport.LocalEndPoint;
                // just sometime working, enable to get the local ep, always 0.0.0.0 if the socket is open with
                // System.Net.IPAddress.Any
                // So in this case don't send a bad message
                if (me.Address.ToString() != "0.0.0.0")
                {
                    Forward_NPDU(buffer, msgLength, false, me);   // send to all BBMDs and FDs
                }
            }
            return(4); // ready to send
        }
Esempio n. 5
0
        // Decode is called each time an Udp Frame is received
        public int Decode(byte[] buffer, int offset, out BacnetBvlcFunctions function, out int msgLength, IPEndPoint sender)
        {
            // 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  = (BacnetBvlcFunctions)buffer[1];
            msgLength = (buffer[2] << 8) | (buffer[3] << 0);
            if (buffer[0] != BVLL_TYPE_BACNET_IP || buffer.Length != msgLength)
            {
                return(-1);
            }

            switch (function)
            {
            case BacnetBvlcFunctions.BVLC_RESULT:
                var resultCode = (buffer[4] << 8) + buffer[5];
                MessageReceived?.Invoke(sender, function, (BacnetBvlcResults)resultCode, null);
                return(0);      // not for the upper layers

            case BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU:
                return(4);                                         // only for the upper layers

            case BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU: // Normaly received in an IP local or global broadcast packet
                // Send to FDs & BBMDs, not broadcast or it will be made twice !
                if (_bbmdFdServiceActivated)
                {
                    Forward_NPDU(buffer, msgLength, false, sender);
                }
                return(4);                                // also for the upper layers

            case BacnetBvlcFunctions.BVLC_FORWARDED_NPDU: // Sent only by a BBMD, broadcast on it network, or broadcast demand by one of it's FDs
                if (_bbmdFdServiceActivated && msgLength >= 10)
                {
                    bool ret;
                    lock (_bbmds)
                        ret = _bbmds.Exists(items => items.Key.Address.Equals(sender.Address));  // verify sender (@ not Port!) presence in the table

                    if (ret)                                                                     // message from a know BBMD address, sent to all FDs and broadcast
                    {
                        SendToFDs(buffer, msgLength);                                            // send without modification

                        // Assume all BVLC_FORWARDED_NPDU are directly sent to me in the
                        // unicast mode and not by the way of the local broadcast address
                        // ie my mask must be 255.255.255.255 in the others BBMD tables
                        // 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, ...)
                        _myBbmdTransport.Send(buffer, msgLength, new IPEndPoint(IPAddress.Parse(_broadcastAdd), _myBbmdTransport.SharedPort));
                    }
                }

                return(10);                                                // also for the upper layers

            case BacnetBvlcFunctions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD
                if (_bbmdFdServiceActivated)
                {
                    // 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, msgLength, true, sender);
                        }
                        else
                        {
                            SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
                        }
                    }
                }
                return(0);      // not for the upper layers

            case BacnetBvlcFunctions.BVLC_REGISTER_FOREIGN_DEVICE:
                if (_bbmdFdServiceActivated && msgLength == 6)
                {
                    var ttl = (buffer[4] << 8) + buffer[5];                                  // unit is second
                    RegisterForeignDevice(sender, ttl);
                    SendResult(sender, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION); // ack
                }
                return(0);                                                                   // not for the upper layers

            // We don't care about Read/Write operation in the BBMD/FDR tables (who realy use it ?)
            case BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE:
                SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
                return(0);

            case BacnetBvlcFunctions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
                SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
                return(0);

            case BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE:
                SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
                return(0);

            case BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
            case BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE_ACK:
            {
                var nbEntries = (msgLength - 4) / 10;
                var entries   = new List <Tuple <IPEndPoint, IPAddress> >();

                for (var i = 0; i < nbEntries; i++)
                {
                    long add = BitConverter.ToInt32(buffer, 4 + i * 10);

                    Array.Reverse(buffer, 8 + i * 10, 2);
                    var port = BitConverter.ToUInt16(buffer, 8 + i * 10);

                    // new IPAddress(long) with 255.255.255.255 (ie -1) not OK
                    var mask = new byte[4];
                    Array.Copy(buffer, 10 + i * 10, mask, 0, 4);

                    var entry = new Tuple <IPEndPoint, IPAddress>(new IPEndPoint(new IPAddress(add), port), new IPAddress(mask));
                    entries.Add(entry);
                }

                if (MessageReceived != null && function == BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE_ACK)
                {
                    MessageReceived(sender, function, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION, entries);
                }

                // Today we don't accept it
                if (function == BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE)
                {
                    SendResult(sender, BacnetBvlcResults.BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
                }

                return(0);
            }

            case BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE_ACK:
            {
                var nbEntries = (msgLength - 4) / 10;
                var entries   = new List <Tuple <IPEndPoint, ushort, ushort> >();

                for (var i = 0; i < nbEntries; i++)
                {
                    long add = BitConverter.ToInt32(buffer, 4 + i * 10);

                    Array.Reverse(buffer, 8 + i * 10, 2);
                    var port = BitConverter.ToUInt16(buffer, 8 + i * 10);

                    Array.Reverse(buffer, 10 + i * 10, 2);
                    var ttl = BitConverter.ToUInt16(buffer, 10 + i * 10);
                    Array.Reverse(buffer, 12 + i * 10, 2);
                    var remainTtl = BitConverter.ToUInt16(buffer, 12 + i * 10);

                    var entry = new Tuple <IPEndPoint, ushort, ushort>(new IPEndPoint(new IPAddress(add), port), ttl, remainTtl);
                    entries.Add(entry);
                }

                MessageReceived?.Invoke(sender, function, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION, entries);
                return(0);
            }

            // error encoding function or experimental one
            default:
                return(-1);
            }
        }
Esempio n. 6
0
        // Decode is called each time an Udp Frame is received
        public int Decode(byte[] buffer, int offset, out BacnetBvlcFunctions function, out int msg_length, IPEndPoint sender)
        {
            // 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   = (BacnetBvlcFunctions)buffer[1];
            msg_length = (buffer[2] << 8) | (buffer[3] << 0);
            if ((buffer[0] != BVLL_TYPE_BACNET_IP) || (buffer.Length != msg_length))
            {
                return(-1);
            }

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

            case BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU:
                return(4);                                         // only for the upper layers

            case BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU: // Normaly received in an IP local or global broadcast packet
                // Send to FDs & BBMDs, not broadcast or it will be made twice !
                if (BBMD_FD_ServiceActivated)
                {
                    Forward_NPDU(buffer, msg_length, false, sender);
                }
                return(4);                                // also for the upper layers

            case BacnetBvlcFunctions.BVLC_FORWARDED_NPDU: // Sent only by a BBMD, broadcast on it network, or broadcast demand by one of it's FDs
                if (BBMD_FD_ServiceActivated && (msg_length >= 10))
                {
                    bool ret;
                    lock (BBMDs)
                        ret = BBMDs.Exists(items => items.Key.Address.Equals(sender.Address));  // verify sender (@ not Port!) presence in the table

                    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 local broadcast address
                        // ie my mask must be 255.255.255.255 in the others BBMD tables
                        // 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, ...)
                        MyBBMDTransport.Send(buffer, msg_length, new IPEndPoint(IPAddress.Parse(BroadcastAdd), MyBBMDTransport.SharedPort));
                    }
                }

                return(10);                                                // also for the upper layers

            case BacnetBvlcFunctions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD
                if (BBMD_FD_ServiceActivated)
                {
                    // 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);
                        }
                        else
                        {
                            SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
                        }
                    }
                }
                return(4);      // also for the upper layers

            case BacnetBvlcFunctions.BVLC_REGISTER_FOREIGN_DEVICE:
                if (BBMD_FD_ServiceActivated && (msg_length == 6))
                {
                    int TTL = (buffer[4] << 8) + buffer[5];                                  // unit is second
                    RegisterForeignDevice(sender, TTL);
                    SendResult(sender, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION); // ack
                }
                return(-1);                                                                  // not for the upper layers

            // We don't care about Read/Write operation in the BBMD/FDR tables (who realy use it ?)
            case BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE:
                //SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
                return(-1);

            case BacnetBvlcFunctions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
                //SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
                return(-1);

            case BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE:
                //SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
                return(-1);

            case BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
                //SendResult(sender, BacnetBvlcResults.BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
                return(-1);

            // error encoding function or experimental one
            default:
                return(-1);
            }
        }