/// <summary> /// Handles a received netgram /// </summary> /// <param name="message">The netgram received message</param> private void _handleReceivedNetgram(NetgramReceivedMessage message) { var buffer = message.Segment.Buffer; var offset = message.Segment.Offset; var end = message.Segment.End; NetgramHeader header = new NetgramHeader(); offset = header.Deserialize(buffer, offset, end); InboundAppgram appgram = null; lock (_lock) { if (header.IsNetworkMessage) { _processNetworkMessage(message, header, buffer, offset, end); } else { appgram = _createInboundAppgram(message, header, buffer, offset, end); } } if (appgram != null) { _appgramObservers.Next(appgram); } }
/// <summary> /// Creates an inbound appgram /// </summary> /// <param name="netgram">The received netgram</param> /// <param name="header">The header of the netgram</param> /// <param name="buffer">The buffer containing the appgram</param> /// <param name="offset">The offset of the appgram within the buffer</param> /// <param name="end">The end of the content in the buffer</param> private InboundAppgram _createInboundAppgram(NetgramReceivedMessage netgram, NetgramHeader header, byte[] buffer, int offset, int end) { InboundAppgram appgram = new InboundAppgram(); appgram.Source = _getSource(netgram, header); appgram.ExpectingReply = header.ExpectingReply; appgram.Priority = header.Priority; appgram.Segment = new BufferSegment(buffer, offset, end); return(appgram); }
/// <summary> /// Retrieves the qualified source address of a netgram /// </summary> /// <param name="netgram">The received netgram</param> /// <param name="header">The netgram header</param> /// <returns>The qualified source address</returns> private Address _getSource(NetgramReceivedMessage netgram, NetgramHeader header) { if (header.Source != null) { return(header.Source); } else { Route route = _table.GetRouteByPortId(netgram.PortId); return(new Address(route.Network, netgram.Source)); } }
/// <summary> /// Called whenever a packet is captured on the capture device /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event args</param> private void _onPacketArrival(object sender, CaptureEventArgs e) { // don't process any packet too short to not be valid if (e.Packet.Data.Length < _minimumPacketLength) { return; } // don't process any packets sent by the local device if (_isOutboundPacket(e.Packet.Data)) { return; } byte[] buffer = e.Packet.Data; int offset = 0; Mac destination, source; int length; byte dsap, ssap, control; destination = new Mac(buffer, offset, 6); offset += 6; source = new Mac(buffer, offset, 6); offset += 6; length = buffer.ReadUInt16(offset); offset += 2; dsap = buffer[offset++]; ssap = buffer[offset++]; control = buffer[offset++]; // don't process non-BACnet packets if (dsap != 0x82 || ssap != 0x82 || control != 0x03) { return; } NetgramReceivedMessage message = new NetgramReceivedMessage( this.PortId, source, new BufferSegment(buffer, offset, buffer.Length)); if (Session != null) { Session.QueueMessage(message); } }
/// <summary> /// Processes a received i am router to network message /// </summary> /// <param name="netgram">The received netgram</param> /// <param name="header">The netgram header</param> /// <param name="message">The i am router to network message</param> private void _processIAmRouterToNetworkMessage(NetgramReceivedMessage netgram, NetgramHeader header, IAmRouterToNetworkMessage message) { // we only use routes from directly connected devices if (header.Destination == null && message.Networks != null) { foreach (var network in message.Networks) { var route = _table.AddRemoteRoute(network, netgram.PortId, netgram.Source); for (var node = _netgramQueue.First; node != null;) { if (node.Value.Destination.Network == network) { var temp = node.Next; _sendWithRoute(route, node.Value); _netgramQueue.Remove(node); node = temp; } else { node = node.Next; } } for (var node = _networkSearchTimers.First; node != null;) { if (node.Value.Network == network) { var temp = node.Next; node.Value.Dispose(); _networkSearchTimers.Remove(node); node = temp; } else { node = node.Next; } } } } }
/// <summary> /// Called whenever a datagram is received /// </summary> /// <param name="ep">The IPEndPoint of the sending device</param> /// <param name="buffer">The buffer containing the datagram</param> /// <param name="length">The length of the received datagram</param> /// <returns>The inbound netgram to propagate, if any</returns> private void _onDatagramReceived(IPEndPoint ep, byte[] buffer, int length) { int offset = 0; BvlcHeader header = null; IBvlcMessage message = null; NetgramReceivedMessage netgram = null; Mac mac = IPUtils.IPEndPointToMac(ep); try { if (length < 4) { throw new Exception("Received datagram under 4 bytes long"); } header = new BvlcHeader(); offset = header.Deserialize(buffer, offset); if (header.Length != length) { throw new Exception("Received bvlc datagram with non-matching lengths"); } message = _createMessage(header.Function); offset = message.Deserialize(buffer, offset); lock (_lock) { netgram = _processMessage(mac, message, buffer, offset, length); } if (netgram != null && Session != null) { Session.QueueMessage(netgram); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
/// <summary> /// Processes a received network message /// </summary> /// <param name="netgram">The netgram received message</param> /// <param name="header">The header of the netgram</param> /// <param name="buffer">The buffer containing the appgram</param> /// <param name="offset">The offset of the appgram within the buffer</param> /// <param name="end">The end of the content in the buffer</param> private void _processNetworkMessage(NetgramReceivedMessage netgram, NetgramHeader header, byte[] buffer, int offset, int end) { try { INetworkMessage message = _createNetworkMessage(header.VendorId, header.MessageType); offset = message.Deserialize(buffer, offset, end); switch (message.Type) { case MessageType.WhoIsRouterToNetwork: _processWhoIsRouterToNetworkMessage(netgram, header, (WhoIsRouterToNetworkMessage)message); break; case MessageType.IAmRouterToNetwork: _processIAmRouterToNetworkMessage(netgram, header, (IAmRouterToNetworkMessage)message); break; } } catch (Exception ex) { Console.WriteLine(ex); } }
/// <summary> /// Processes a received who is router to network message /// </summary> /// <param name="netgram">The netgram received message</param> /// <param name="header">The netgram header</param> /// <param name="message">The who is router to network message</param> private void _processWhoIsRouterToNetworkMessage(NetgramReceivedMessage netgram, NetgramHeader header, WhoIsRouterToNetworkMessage message) { }