public int Send(ITftpPacket packet) { return(Send(packet.Serialize())); }
/* * This method performs the following steps: * 1) send sendPacket to destinationEP every retryPeriod * 2) All packets for which receiveFilter returns false are discarded * This will continue until: * a) receiveFilter returns true for a received packet - receivedFromEP is set to the * endpoint from which the packet was received and the packet is returned. * b) timeout has elapsed - TimeoutException is thrown * c) cancellationToken has been signalled - OperationCanceledException is thrown */ public ITftpPacket SendAndWaitForResponse( ITftpPacket sendPacket, IPEndPoint destinationEP, TimeSpan timeout, TimeSpan retryPeriod, Func <ITftpPacket, bool> receiveFilter, out IPEndPoint receivedFromEP, CancellationToken cancellationToken) { ITftpPacket receivePacket = null; byte[] sendPacketBytes = sendPacket.Serialize(); // Set up timeout cancellation token and link it with the cancellation token parameter. var timeoutCts = new CancellationTokenSource(timeout); var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token); // Spin up a task thread to re-send sendPacket every retryPeriod. Action sendAction = () => { while (true) { _udp.Send(sendPacketBytes, destinationEP); linkedCts.Token.WaitHandle.WaitOne(retryPeriod); linkedCts.Token.ThrowIfCancellationRequested(); Console.WriteLine("Re-sending packet"); } }; var sendTask = Task.Factory.StartNew(sendAction, linkedCts.Token); try { receivePacket = Receive(receiveFilter, out receivedFromEP, linkedCts.Token); } catch (OperationCanceledException) { // Here we need to disambiguate which cancellation token source caused the OperationCanceledException. // If the cancellation token passed into this method was signalled, // then we need to let the OperationCanceledException propagate up as-is. if (cancellationToken.IsCancellationRequested) { Console.WriteLine("SendAndWaitForResponse was canceled."); throw; } // Otherwise, the timeout cancellation token caused the OperationCanceledException. else { Console.WriteLine("Receive timed out."); throw new TimeoutException(string.Format("A response was not received after {0}.", timeout)); } } // Cancel and clean up the send task. linkedCts.Cancel(); try { sendTask.Wait(); } catch (AggregateException ex) { ex.Handle(e => e is TaskCanceledException); } return(receivePacket); }