private bool ContinueRetransmission(RetransmitState state) { this.ThrowIfTimedOut(); while (true) { switch (state) { case RetransmitState.TransmitCompleted: if (!this.retransmitIterator.MoveNext()) { // We are done retransmitting return(true); } if (this.retransmitIterator.CurrentDelay > 0) { this.retransmitTimer.Set(this.retransmitIterator.CurrentDelay); return(false); } state = RetransmitState.WaitCompleted; break; case RetransmitState.WaitCompleted: if (this.IsCanceled) { this.channel.ThrowIfAborted(); return(true); } // since we only invoke the encoder once just before the initial send of the message // we need to handle logging the message in the retransmission case if (MessageLogger.LogMessagesAtTransportLevel) { UdpOutputChannel.LogMessage(ref this.message, this.messageData); } // !completedSync if (!this.BeginTransmitMessage()) { return(false); } state = RetransmitState.TransmitCompleted; break; default: Fx.Assert("Unknown RetransmitState value encountered"); return(true); } } }
protected override void OnSend(Message message, TimeSpan timeout) { if (message is NullMessage) { return; } TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); IPEndPoint remoteEndPoint; UdpSocket[] sendSockets; Exception exceptionToBeThrown; sendSockets = this.GetSendSockets(message, out remoteEndPoint, out exceptionToBeThrown); if (exceptionToBeThrown != null) { throw FxTrace.Exception.AsError(exceptionToBeThrown); } if (timeoutHelper.RemainingTime() <= TimeSpan.Zero) { throw FxTrace.Exception.AsError(new TimeoutException(SR.SendTimedOut(remoteEndPoint, timeout))); } bool returnBuffer = false; ArraySegment <byte> messageData = default(ArraySegment <byte>); bool sendingMulticast = UdpUtility.IsMulticastAddress(remoteEndPoint.Address); SynchronousRetransmissionHelper retransmitHelper = null; RetransmitIterator retransmitIterator = null; bool shouldRetransmit = this.ShouldRetransmitMessage(sendingMulticast); try { if (shouldRetransmit) { retransmitIterator = this.CreateRetransmitIterator(sendingMulticast); retransmitHelper = new SynchronousRetransmissionHelper(sendingMulticast); this.RetransmitStarting(message.Headers.MessageId, retransmitHelper); } messageData = this.EncodeMessage(message); returnBuffer = true; this.TransmitMessage(messageData, sendSockets, remoteEndPoint, timeoutHelper); if (shouldRetransmit) { while (retransmitIterator.MoveNext()) { // wait for currentDelay time, then retransmit if (retransmitIterator.CurrentDelay > 0) { retransmitHelper.Wait(retransmitIterator.CurrentDelay); } if (retransmitHelper.IsCanceled) { ThrowIfAborted(); return; } // since we only invoke the encoder once just before the initial send of the message // we need to handle logging the message in the retransmission case if (MessageLogger.LogMessagesAtTransportLevel) { UdpOutputChannel.LogMessage(ref message, messageData); } this.TransmitMessage(messageData, sendSockets, remoteEndPoint, timeoutHelper); } } } finally { if (returnBuffer) { this.BufferManager.ReturnBuffer(messageData.Array); } if (shouldRetransmit) { this.RetransmitStopping(message.Headers.MessageId); if (retransmitHelper != null) { retransmitHelper.Dispose(); } } } }