public void ReceiveAndExpectTimeout() { try { Console.WriteLine("[{0} {1} millis] ReceiveBlocking, timeout is {2} milliseconds (Expecting TimeoutException)...", name, (Stopwatch.GetTimestamp() - stopwatchStartTicks).StopwatchTicksAsInt64Milliseconds(), timeoutMillis); receiveTransmitter.ReceiveBlocking(receiveBuffer, 0, (UInt32)receiveBuffer.Length, timeoutMillis); Assert.Fail("Expected TimeoutException"); } catch (TimeoutException) { Console.WriteLine("[{0} {1} millis] TimeOut Exception", name, (Stopwatch.GetTimestamp() - stopwatchStartTicks).StopwatchTicksAsInt64Milliseconds()); } }
public int ReceiveBlocking(byte[] buffer, UInt32 offset, UInt32 maxLength, int timeoutMillis) { Int64 diffStopwatchTicks = dropReceivedDatagramsUntil - Stopwatch.GetTimestamp(); if (diffStopwatchTicks > 0) { Int32 waitTimeMillis = diffStopwatchTicks.StopwatchTicksAsInt32Milliseconds(); DropAllAvailableDatagrams(); if (timeoutMillis < waitTimeMillis) { Console.WriteLine("[ClumsyTransmitter] Dropping all packets (timeout {0}) drop time {1} is larger than timeout", timeoutMillis, waitTimeMillis); Thread.Sleep(timeoutMillis); DropAllAvailableDatagrams(); return(-1); } if (debugLog != null) { debugLog.WriteLine("[ClumsyTransmitter] Sleeping for {0} milliseconds until clumsy transmitter can receive again", waitTimeMillis); } Thread.Sleep(waitTimeMillis); timeoutMillis -= waitTimeMillis; Console.WriteLine("[ClumsyTransmitter] Old Timeout {0} New Timeout After Drop {1}", timeoutMillis + waitTimeMillis, timeoutMillis); } return(underlyingTransmitter.ReceiveBlocking(buffer, offset, maxLength, timeoutMillis)); }
public void ControllerSendPayloadWithAck(UInt32 offsetLimit, ICdpTimeout timeout) { // 1. Check for acks/resends/halts Byte[] bufferToSend = GetRequestedBuffer(offsetLimit); try { // Cdp Header UInt32 payloadID = nextPayloadID++; bufferToSend[0] = (Byte)(((Byte)CdpFlagValue.PayloadWithAck << 4) | (0x0F & (payloadID >> 8))); bufferToSend[1] = (Byte)payloadID; // // Send the datagram // connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit); Int64 stopwatchTicksAfterSend = Stopwatch.GetTimestamp(); Int32 timeoutMillis = timeout.WaitForAckInitialRetryTimeout(averageLatency); if (timeoutMillis < 0) { throw new InvalidOperationException(String.Format( "The ICdpTimeout class '{0}' returned negative ({1}) when calling WaitForAckInitialTimeout({2})", timeout.GetType().Name, timeoutMillis, averageLatency)); } Int32 retries = 0; // Keep resending the datagram until a header is recevied or timeout is reached while (true) { Console.WriteLine("Send Retry {0}", retries); Int32 bytesRead = connectedDatagramTransmitter.ReceiveBlocking(headerBuffer, 0, 2, timeoutMillis); if (bytesRead < 0) { Int32 elapsedMillis = (Stopwatch.GetTimestamp() - stopwatchTicksAfterSend).StopwatchTicksAsInt32Milliseconds(); timeoutMillis = timeout.WaitForAckRetryOrTimeout(retries, averageLatency, elapsedMillis, timeoutMillis); if (timeoutMillis <= 0) { throw new TimeoutException(String.Format("Timed out waiting for ack: {0} retries {1} milliseconds elapsed", retries, elapsedMillis)); } // Retry sending the packet connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit); retries++; continue; } // // Check the datagram // if (bytesRead == 0) { // It's just a heart beat packet } else { Byte receivedFlagValue = (Byte)(headerBuffer[0] >> 4); UInt32 receivedPayloadID = (UInt32)((0xF00 & (headerBuffer[0] << 8)) | (0xFF & headerBuffer[1])); if (receivedFlagValue == (Byte)CdpFlagValue.Ack) { if (receivedPayloadID == payloadID) { Console.WriteLine("[CdpDebug] Received ACK for payload id {0}", payloadID); break; } Console.WriteLine("[CdpDebug] Got an ack for an old payload id {0}?", receivedPayloadID); } else if (receivedFlagValue == (Byte)CdpFlagValue.Halt) { throw new CdpBadHaltException(); } else if (receivedFlagValue == (Byte)CdpFlagValue.Resend) { if (receivedPayloadID <= payloadID) { UInt32 index = datagramQueue.PayloadIDToIndex(receivedPayloadID); if (index >= 0) { if (receivedPayloadID < payloadID) { do { Console.WriteLine("[Debug] Queue Index {0} Payload ID {1}", index, receivedPayloadID + index); CdpBufferPoolDatagram datagram = datagramQueue.queue[index]; connectedDatagramTransmitter.Send(datagram.datagram, 0, datagram.length); index++; } while (receivedPayloadID + index < payloadID); } connectedDatagramTransmitter.Send(bufferToSend, 0, offsetLimit); } } } else { Console.WriteLine("Unknown flag value {0} from '{1}' (Maybe I should throw an exception? TBD)", receivedFlagValue, connectedDatagramTransmitter.RemoteEndPoint); } } // // Get next timeout // { Int32 elapsedMillis = (Stopwatch.GetTimestamp() - stopwatchTicksAfterSend).StopwatchTicksAsInt32Milliseconds(); timeoutMillis = timeout.WaitForAckRetryOrTimeout(retries, averageLatency, elapsedMillis, timeoutMillis); if (timeoutMillis <= 0) { throw new TimeoutException(String.Format("Timed out waiting for ack: {0} retries {1} milliseconds elapsed", retries, elapsedMillis)); } } } datagramQueue.EmptyAndFree(); // free the queue because everything has been acked } finally { Cdp.BufferPool.FreeBuffer(bufferToSend); } }