/// <summary>Implements scan for new packets (invoked internally after reception of new data) and implements stale rx data detection and handling when no new data has been received.</summary> public void Service(bool performFullRescan) { // check for unscanned data if (performFullRescan) { lastScannedContentCount = 0; } if (BufferDataCount == 0 || BufferDataCount == lastScannedContentCount) { return; } PacketEndScannerDelegate scannerDelegate = packetEndScannerDelegate ?? defaultPacketEndScannerDelegate ?? (defaultPacketEndScannerDelegate = DefaultPacketEndScannerDelegate); bool foundPacket = false; for (;;) { int bufferDataCount = BufferDataCount; int nextPacketLen = scannerDelegate(buffer, getIdx, bufferDataCount, lastScannedContentCount); if (nextPacketLen == 0) { lastScannedContentCount = bufferDataCount; break; } else { lastScannedContentCount = 0; foundPacket = true; int dataCopyStartIdx = getIdx; bool isFlushedData = (nextPacketLen < 0); nextPacketLen = Math.Abs(nextPacketLen); int dataCopyLen = Math.Min(bufferDataCount, nextPacketLen); bool isWhitespace = false; if (isFlushedData) { // we do not strip whitespace from flushed data. } else if (stripWhitespace) { while (dataCopyLen > 0) { if (!IsWhiteSpace(buffer[dataCopyStartIdx])) { break; } dataCopyStartIdx++; dataCopyLen--; } while (dataCopyLen > 0) { if (!IsWhiteSpace(buffer[dataCopyStartIdx + dataCopyLen - 1])) { break; } dataCopyLen--; } isWhitespace = (dataCopyLen == 0); } else if (detectWhitespace) { isWhitespace = true; // assume that it is all whitespace for (int scanOffset = 0; scanOffset < dataCopyLen; scanOffset++) { if (!IsWhiteSpace(buffer[getIdx + scanOffset])) { isWhitespace = false; break; } } } // extract bytes from buffer and append into new packet if (!isWhitespace || !DiscardWhitespacePackets) { Packet p; if (!isFlushedData) { p = new Packet((!isWhitespace ? PacketType.Data : PacketType.WhiteSpace), new byte[dataCopyLen]); } else { p = new Packet(PacketType.Flushed, new byte[dataCopyLen]); } if (dataCopyLen > 0) { System.Buffer.BlockCopy(buffer, dataCopyStartIdx, p.Data, 0, dataCopyLen); } extractedPacketQueue.Enqueue(p); } // else this run is all whitespace and we have been configured to DiscardWhitespacePackets - so just drop these bytes. UsedNChars(nextPacketLen); } } // drop leading whitespace from buffer immediately (this will prevent them from causing generation of unexpected timeout packets for trailing whitespace that is ignored) if (stripWhitespace) { int whiteSpaceRunLength = 0; while (whiteSpaceRunLength < BufferDataCount && IsWhiteSpace(buffer[getIdx + whiteSpaceRunLength])) { whiteSpaceRunLength++; } if (whiteSpaceRunLength > 0) { UsedNChars(whiteSpaceRunLength); } } // check for timeout: when both the contentPutAge and the contentGetAge are larger than the PacketTimeout and it is not zero. if (!foundPacket && BufferDataCount > 0 && PacketTimeout != TimeSpan.Zero) { QpcTimeStamp now = QpcTimeStamp.Now; TimeSpan contentPutAge = now - ContentPutTime; TimeSpan contentGetAge = now - ContentGetTime; if (contentPutAge > PacketTimeout && contentGetAge > PacketTimeout) { double contentAgeInSec = System.Math.Min(contentPutAge.TotalSeconds, contentGetAge.TotalSeconds); string opStr = ((contentPutAge < contentGetAge) ? "Put" : "Get"); // transfer the current bytes in the sliding buffer into a new packet and reset the sliding buffer Packet p = new Packet(PacketType.Timeout, new byte[BufferDataCount], Utils.Fcns.CheckedFormat("Timeout: {0} stale chars found in buffer {1:f3} seconds after most recent {2}", BufferDataCount, contentAgeInSec, opStr)); System.Buffer.BlockCopy(buffer, getIdx, p.Data, 0, BufferDataCount); extractedPacketQueue.Enqueue(p); UsedNChars(BufferDataCount); } } }
/// <summary>Implements scan for new packets (invoked internally after reception of new data) and implements stale rx data detection and handling when no new data has been received.</summary> public void Service(bool performFullRescan) { // check for unscanned data if (performFullRescan) lastScannedContentCount = 0; if (BufferDataCount == 0 || BufferDataCount == lastScannedContentCount) return; PacketEndScannerDelegate scannerDelegate = packetEndScannerDelegate ?? defaultPacketEndScannerDelegate ?? (defaultPacketEndScannerDelegate = DefaultPacketEndScannerDelegate); bool foundPacket = false; for (;;) { int bufferDataCount = BufferDataCount; int nextPacketLen = scannerDelegate(buffer, getIdx, bufferDataCount, lastScannedContentCount); if (nextPacketLen == 0) { lastScannedContentCount = bufferDataCount; break; } else { lastScannedContentCount = 0; foundPacket = true; int dataCopyStartIdx = getIdx; bool isFlushedData = (nextPacketLen < 0); nextPacketLen = Math.Abs(nextPacketLen); int dataCopyLen = Math.Min(bufferDataCount, nextPacketLen); bool isWhitespace = false; if (isFlushedData) { // we do not strip whitespace from flushed data. } else if (StripWhitespace) { while (dataCopyLen > 0) { if (!IsWhiteSpace(buffer[dataCopyStartIdx])) break; dataCopyStartIdx++; dataCopyLen--; } while (dataCopyLen > 0) { if (!IsWhiteSpace(buffer[dataCopyStartIdx + dataCopyLen - 1])) break; dataCopyLen--; } isWhitespace = (dataCopyLen == 0); } else { isWhitespace = true; // assume that it is all whitespace for (int scanOffset = 0; scanOffset < dataCopyLen; scanOffset++) { if (!IsWhiteSpace(buffer[getIdx + scanOffset])) isWhitespace = false; } } // extract bytes from buffer and append into new packet if (!isWhitespace || !DiscardWhitespacePackets) { Packet p; if (!isFlushedData) p = new Packet((!isWhitespace ? PacketType.Data : PacketType.WhiteSpace), new byte[dataCopyLen]); else p = new Packet(PacketType.Flushed, new byte[dataCopyLen]); if (dataCopyLen > 0) System.Buffer.BlockCopy(buffer, dataCopyStartIdx, p.Data, 0, dataCopyLen); extractedPacketQueue.Enqueue(p); } UsedNChars(nextPacketLen); } } // drop leading whitespace from buffer immediately (this will prevent them from causing generation of unexpected timeout packets for trailing whitespace that is ignored) if (StripWhitespace && BufferDataCount > 0) { if (IsWhiteSpace(buffer[getIdx])) UsedNChars(1); } // check for timeout: when both the contentPutAge and the contentGetAge are larger than the PacketTimeout and it is not zero. if (!foundPacket && BufferDataCount > 0 && PacketTimeout != TimeSpan.Zero) { QpcTimeStamp now = QpcTimeStamp.Now; TimeSpan contentPutAge = now - ContentPutTime; TimeSpan contentGetAge = now - ContentGetTime; if (contentPutAge > PacketTimeout && contentGetAge > PacketTimeout) { double contentAgeInSec = System.Math.Min(contentPutAge.TotalSeconds, contentGetAge.TotalSeconds); string opStr = ((contentPutAge < contentGetAge) ? "Put" : "Get"); // transfer the current bytes in the sliding buffer into a new packet and reset the sliding buffer Packet p = new Packet(PacketType.Timeout, new byte[BufferDataCount], Utils.Fcns.CheckedFormat("Timeout: {0} stale chars found in buffer {1:f3} seconds after most recent {2}", BufferDataCount, contentAgeInSec, opStr)); System.Buffer.BlockCopy(buffer, getIdx, p.Data, 0, BufferDataCount); extractedPacketQueue.Enqueue(p); UsedNChars(BufferDataCount); } } }