/// <summary> /// Reads from the connection. /// </summary> /// <param name="operation"></param> protected override void DoRead(ReadWriteOperation operation) { try { int bytesRead = 0; if (_PreviousReadResult.LengthRemaining > 0) { bytesRead = _PreviousReadResult.CopyChunkIntoBuffer(operation.Buffer, operation.Offset, operation.Length); } else { var threshold = _LastReadTimeUtc.AddMilliseconds(FetchIntervalMilliseconds); while (DateTime.UtcNow < threshold) { // Give up our timeslice Thread.Sleep(1); } _LastReadTimeUtc = DateTime.UtcNow; // Set a minimum threshold for the next read even if this upcoming read fails var bytes = _HttpClient.GetByteArrayAsync(WebAddress).Result; _PreviousReadResult.SetBuffer(bytes, 0, bytes.Length); bytesRead = _PreviousReadResult.CopyChunkIntoBuffer(operation.Buffer, operation.Offset, operation.Length); ConnectionStatus = ConnectionStatus.Connected; _LastReadTimeUtc = DateTime.UtcNow; // Set the point that we want to pause from for a successful read } operation.BytesRead = bytesRead; } catch (Exception ex) { _Connector?.RaiseConnectionException(this, ex); ConnectionStatus = ConnectionStatus.Reconnecting; } }
/// <summary> /// See interface docs. /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <param name="readDelegate"></param> public virtual void Read(byte[] buffer, int offset, int length, ConnectionReadDelegate readDelegate) { var operationQueue = GetOperationQueue(); if (operationQueue != null) { var operation = new ReadWriteOperation(buffer, offset, length, isRead: true, readDelegate: readDelegate); operationQueue.Enqueue(operation); } }
/// <summary> /// See interface docs. /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <param name="staleMessageTimeoutOverride"></param> public virtual void Write(byte[] buffer, int offset, int length, int staleMessageTimeoutOverride = -1) { var operationQueue = GetOperationQueue(); var connector = GetConnector(); if (operationQueue != null && connector != null) { var staleTimeout = staleMessageTimeoutOverride != -1 ? staleMessageTimeoutOverride : connector.StaleMessageTimeout; var staleThreshold = staleTimeout > 0 ? DateTime.UtcNow.AddMilliseconds(staleTimeout) : default(DateTime); IncrementWriteQueueBytes(length); var operation = new ReadWriteOperation(buffer, offset, length, isRead: false, staleThreshold: staleThreshold); operationQueue.Enqueue(operation); } }
/// <summary> /// See base docs. /// </summary> /// <param name="op"></param> protected override void DoWrite(ReadWriteOperation op) { var serialPort = GetSerialPort(); if (serialPort != null) { try { serialPort.Write(op.Buffer, op.Offset, op.Length); } catch (Exception ex) { if (_Connector != null) { _Connector.RaiseConnectionException(this, ex); } op.Abandon = true; } } }
/// <summary> /// See base docs. /// </summary> /// <param name="op"></param> protected override void DoWrite(ReadWriteOperation op) { var socket = GetSocket(); if (socket != null) { try { socket.Send(op.Buffer, op.Offset, op.Length, SocketFlags.None); _LastNetworkActivity = DateTime.UtcNow; } catch (Exception ex) { if (_Connector != null) { _Connector.RaiseConnectionException(this, ex); } op.Abandon = true; } } }
/// <summary> /// See base docs. /// </summary> /// <param name="op"></param> protected override void DoRead(ReadWriteOperation op) { var socket = GetSocket(); if (socket != null) { try { op.BytesRead = socket.Receive(op.Buffer, op.Offset, op.Length, SocketFlags.None); op.Abandon = op.BytesRead == 0; // Other side has forcibly closed the connection _LastNetworkActivity = DateTime.UtcNow; } catch (Exception ex) { if (_Connector != null) { _Connector.RaiseConnectionException(this, ex); } op.Abandon = true; } } }
/// <summary> /// See base docs. /// </summary> /// <param name="op"></param> protected override void DoRead(ReadWriteOperation op) { var serialPort = GetSerialPort(); if (serialPort != null) { _BusyReading.Reset(); try { var timedOut = false; var bytesRead = 0; do { try { timedOut = false; while (!_Closing && serialPort.BytesToRead == 0) { Thread.Sleep(1); // give up the rest of our time slice before trying again } if (!_Closing) { bytesRead = serialPort.Read(op.Buffer, op.Offset, op.Length); } } catch (TimeoutException) { bytesRead = -1; timedOut = true; } serialPort = GetSerialPort(); } while(serialPort != null && !_Closing && (timedOut || bytesRead == 0)); op.BytesRead = bytesRead; op.Abandon = serialPort == null || _Closing; } catch (Exception ex) { if (_Connector != null) { _Connector.RaiseConnectionException(this, ex); } op.Abandon = true; } finally { _BusyReading.Set(); } } }
/// <summary> /// Called when a read or write operation is received. /// </summary> /// <param name="operation"></param> private void OperationQueue_ProcessOperation(ReadWriteOperation operation) { if (operation.IsRead) { DoRead(operation); if (!operation.Abandon) { IncrementBytesRead(operation.BytesRead); if (operation.ReadDelegate != null) { operation.ReadDelegate(this, operation.Buffer, operation.Offset, operation.Length, operation.BytesRead); } } } else { IncrementWriteQueueBytes(-operation.Length); if (DateTime.UtcNow >= operation.StaleThreshold) { IncrementStaleBytesDiscarded(operation.Length); } else { DoWrite(operation); if (!operation.Abandon) { IncrementBytesWritten(operation.Length); } } } if (operation.Abandon) { // The Abandon call will shut down this thread - do not put any code after this point, // it will never run. Abandon(); } }
protected abstract void DoWrite(ReadWriteOperation operation);
/// <summary> /// Does nothing - writes over HTTP connections are not supported. /// </summary> /// <param name="operation"></param> protected override void DoWrite(ReadWriteOperation operation) { ; }