/// <summary> /// Called every time the provider sends some bytes to us. /// </summary> /// <param name="ar"></param> private void BytesReceived(IAsyncResult ar) { try { var now = Provider.UtcNow; int bytesRead = -1; bool fetchNext = true; try { bytesRead = Provider.EndRead(ar); } catch (ObjectDisposedException) { fetchNext = false; } catch (SocketException) { fetchNext = false; Reconnect(); } if (bytesRead == 0 || _Disposed) { fetchNext = false; if (!_Disposed) { Reconnect(); } } else if (bytesRead > 0) { if (_Statistics.Lock != null) { lock (_Statistics.Lock) _Statistics.BytesReceived += bytesRead; } // This is a bit of a cheat - I don't want the overhead of taking a copy of the read buffer if nothing is // listening to RawBytesReceived, so I take a peek at the event handler before creating the event args... if (RawBytesReceived != null) { var copyRawBytes = new byte[bytesRead]; Array.Copy(Provider.ReadBuffer, 0, copyRawBytes, 0, bytesRead); _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch() { RawBytesEventArgs = new EventArgs <byte[]>(copyRawBytes) }); } foreach (var extractedBytes in BytesExtractor.ExtractMessageBytes(Provider.ReadBuffer, 0, bytesRead)) { if (extractedBytes.ChecksumFailed) { ++TotalBadMessages; if (_Statistics.Lock != null) { lock (_Statistics.Lock) ++_Statistics.FailedChecksumMessages; } } else { // Another cheat and for the same reason as explained for the RawBytesReceived message - we don't want to // incur the overhead of copying the extracted bytes if there is nothing listening to the event. if (ModeSBytesReceived != null && extractedBytes.Format == ExtractedBytesFormat.ModeS) { _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch() { ModeSBytesEventArgs = new EventArgs <ExtractedBytes>((ExtractedBytes)extractedBytes.Clone()) }); } switch (extractedBytes.Format) { case ExtractedBytesFormat.Port30003: ProcessPort30003MessageBytes(extractedBytes); break; case ExtractedBytesFormat.ModeS: ProcessModeSMessageBytes(now, extractedBytes); break; default: throw new NotImplementedException(); } } } } if (fetchNext) { Provider.BeginRead(BytesReceived); } } catch (Exception ex) { Disconnect(); OnExceptionCaught(new EventArgs <Exception>(ex)); } }
/// <summary> /// Called every time the connection sends some bytes to us. /// </summary> /// <param name="connection"></param> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <param name="bytesRead"></param> private void BytesReceived(IConnection connection, byte[] buffer, int offset, int length, int bytesRead) { try { var now = _Clock.UtcNow; if (bytesRead > 0) { if (Statistics != null) { Statistics.Lock(r => r.BytesReceived += bytesRead); } _LastMessageUtc = now; // This is a bit of a cheat - I don't want the overhead of taking a copy of the read buffer if nothing is // listening to RawBytesReceived, so I take a peek at the event handler before creating the event args... if (RawBytesReceived != null) { var copyRawBytes = new byte[bytesRead]; Array.Copy(buffer, offset, copyRawBytes, 0, bytesRead); _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch() { RawBytesEventArgs = new EventArgs <byte[]>(copyRawBytes) }); } foreach (var extractedBytes in BytesExtractor.ExtractMessageBytes(buffer, offset, bytesRead)) { if (extractedBytes.ChecksumFailed) { ++TotalBadMessages; if (Statistics != null) { Statistics.Lock(r => ++ r.FailedChecksumMessages); } } else { // Another cheat and for the same reason as explained for the RawBytesReceived message - we don't want to // incur the overhead of copying the extracted bytes if there is nothing listening to the event. if (ModeSBytesReceived != null && extractedBytes.Format == ExtractedBytesFormat.ModeS) { _MessageProcessingAndDispatchQueue.Enqueue(new MessageDispatch() { ModeSBytesEventArgs = new EventArgs <ExtractedBytes>((ExtractedBytes)extractedBytes.Clone()) }); } switch (extractedBytes.Format) { case ExtractedBytesFormat.Port30003: ProcessPort30003MessageBytes(extractedBytes); break; case ExtractedBytesFormat.ModeS: ProcessModeSMessageBytes(now, extractedBytes); break; case ExtractedBytesFormat.Compressed: ProcessCompressedMessageBytes(now, extractedBytes); break; case ExtractedBytesFormat.AircraftListJson: ProcessAircraftListJsonMessageBytes(now, extractedBytes); break; case ExtractedBytesFormat.AirnavXRange: ProcessAirnavXRangeMessageBytes(now, extractedBytes); break; default: throw new NotImplementedException(); } } } if (Statistics != null) { Statistics.Lock(r => r.CurrentBufferSize = BytesExtractor.BufferSize); } } Connector.Read(_Buffer, BytesReceived); } catch (Exception ex) { Disconnect(); OnExceptionCaught(new EventArgs <Exception>(ex)); } }