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); }
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); } }
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); }
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 ! } }
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); }
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); }
public BacnetAddress GetBroadcastAddress() { if (BroadcastAddress == null) { BroadcastAddress = _GetBroadcastAddress(); } return(BroadcastAddress); }
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 */ }
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); }
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(); }
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); }
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); }
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(); }
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; }
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); } }
// 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()); }
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); }
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); }
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); } }
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); }
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; }
public BacnetAddress GetBroadcastAddress() { return(_broadcastAddress ?? (_broadcastAddress = _GetBroadcastAddress())); }
protected void InvokeMessageRecieved(byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress) { MessageRecieved?.Invoke(this, buffer, offset, msgLength, remoteAddress); }
// 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); } }
// 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); // ? }
// 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); } }