Example #1
0
 public int Send(ITftpPacket packet)
 {
     return(Send(packet.Serialize()));
 }
Example #2
0
        /*
         * 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);
        }