bool PrepareAndAddressReply(ref MessageRpc rpc) { bool canSendReply = true; if (!manualAddressing) { if (!object.ReferenceEquals(rpc.RequestID, null)) { RequestReplyCorrelator.PrepareReply(rpc.Reply, rpc.RequestID); } if (!rpc.Channel.HasSession) { canSendReply = RequestReplyCorrelator.AddressReply(rpc.Reply, rpc.ReplyToInfo); } } AddMessageProperties(rpc.Reply, rpc.OperationContext, rpc.Channel); //if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && rpc.EventTraceActivity != null) //{ // rpc.Reply.Properties[EventTraceActivity.Name] = rpc.EventTraceActivity; //} return(canSendReply); }
void PrepareRequest(Message message) { RequestReplyCorrelator.PrepareRequest(message); if (this.requiresManualReplyAddressing) { if (this.localAddress != null) { message.Headers.ReplyTo = this.LocalAddress; } else { message.Headers.ReplyTo = EndpointAddress.AnonymousAddress; } } if (this.webHeaderCollection != null && this.webHeaderCollection.Count > 0) { object prop = null; HttpRequestMessageProperty rmp = null; if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop)) { rmp = prop as HttpRequestMessageProperty; } else { rmp = new HttpRequestMessageProperty(); message.Properties.Add(HttpRequestMessageProperty.Name, rmp); } if (rmp != null && rmp.Headers != null) { rmp.Headers.Add(this.webHeaderCollection); } } }
void DeleteTimedoutRequestsFromCorrelator() { ICorrelatorKey[] array = null; if (timedOutRequests != null && timedOutRequests.Count > 0) { lock (ThisLock) { if (timedOutRequests != null && timedOutRequests.Count > 0) { array = timedOutRequests.ToArray(); timedOutRequests = null; } } } // Remove requests from the correlator since the channel might be either faulting, aborting or closing // We are not going to get a reply for these timed out requests. If they are not removed from the correlator, this will cause a leak. // This operation does not have to be under the lock if (array != null && array.Length > 0) { RequestReplyCorrelator requestReplyCorrelator = correlator as RequestReplyCorrelator; if (requestReplyCorrelator != null) { foreach (ICorrelatorKey request in array) { requestReplyCorrelator.RemoveRequest(request); } } } }
/// <summary> /// Prepares a reply /// </summary> /// <param name="request">The request context to prepare</param> /// <param name="reply">The reply to prepare</param> /// <returns>True if channel is open and prepared reply should be sent; otherwise false.</returns> bool PrepareReply(RequestContext request, Message reply) { // Ensure we only reply once (we may hit the same error multiple times) if (_replied == request) { return(false); } _replied = request; bool canSendReply = true; Message requestMessage = null; try { requestMessage = request.RequestMessage; } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // swallow it } if (!object.ReferenceEquals(requestMessage, null)) { UniqueId requestID = null; try { requestID = requestMessage.Headers.MessageId; } catch (MessageHeaderException) { // swallow it - we don't need to correlate the reply if the MessageId header is bad } if (!object.ReferenceEquals(requestID, null) && !_isManualAddressing) { RequestReplyCorrelator.PrepareReply(reply, requestID); } if (!_hasSession && !_isManualAddressing) { try { canSendReply = RequestReplyCorrelator.AddressReply(reply, requestMessage); } catch (MessageHeaderException) { // swallow it - we don't need to address the reply if the FaultTo header is bad } } } // ObjectDisposeException can happen // if the channel is closed in a different // thread. 99% this check will avoid false // exceptions. return(IsOpen && canSendReply); }
protected void OnReceive(Message message) { DebugTrace.TraceEnter(this, "OnReceive"); if ((message != null) && !this.tokenResolver.FaultInSupportingToken(message)) { if (DebugTrace.Verbose) { DebugTrace.Trace(TraceLevel.Verbose, "Failed to fault in SCT for supporting token signature"); } Fault invalidParameters = Faults.Version(this.protocolVersion).InvalidParameters; if (message.Headers.MessageId != null) { if (DebugTrace.Verbose) { DebugTrace.Trace(TraceLevel.Verbose, "Attempting to send {0} fault", invalidParameters.Code.Name); } Message reply = Library.CreateFaultMessage(message.Headers.MessageId, message.Version, invalidParameters); RequestReplyCorrelator.AddressReply(reply, new RequestReplyCorrelator.ReplyToInfo(message)); SendSecurityHeader header = SupportingTokenChannel <TChannel> .SecurityStandardsManager.CreateSendSecurityHeader(reply, string.Empty, true, false, SecurityAlgorithmSuite.Default, MessageDirection.Output); header.RequireMessageProtection = false; header.AddTimestamp(SecurityProtocolFactory.defaultTimestampValidityDuration); reply = header.SetupExecution(); this.TrySendFaultReply(reply); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(Microsoft.Transactions.SR.GetString("SupportingTokenSignatureExpected"))); } DebugTrace.TraceLeave(this, "OnReceive"); }
private void PrepareRequest(Message nextMessage, RequestSecurityToken rst) { if ((rst != null) && !rst.IsReadOnly) { rst.Message = nextMessage; } RequestReplyCorrelator.PrepareRequest(nextMessage); if (this.RequiresManualReplyAddressing) { nextMessage.Headers.ReplyTo = EndpointAddress.AnonymousAddress; } }
void PrepareRequest(Message nextMessage, RequestSecurityToken rst) { if (rst != null && !rst.IsReadOnly) { rst.Message = nextMessage; } RequestReplyCorrelator.PrepareRequest(nextMessage); if (this.RequiresManualReplyAddressing) { // if we are on HTTP, we need to explicitly add a reply-to header for interop nextMessage.Headers.ReplyTo = EndpointAddress.AnonymousAddress; } }
public async Task <Message> RequestAsync(Message message, CancellationToken token) { RequestReplyCorrelator.PrepareRequest(message); AsyncDuplexRequest duplexRequest = new AsyncDuplexRequest(this); lock (ThisLock) { RequestStarting(message, duplexRequest); } await _channel.SendAsync(message, token); return(await duplexRequest.WaitForReplyAsync(token)); }
private void PrepareRequest(Message message) { RequestReplyCorrelator.PrepareRequest(message); if (this.requiresManualReplyAddressing) { if (this.localAddress != null) { message.Headers.ReplyTo = this.LocalAddress; } else { message.Headers.ReplyTo = EndpointAddress.AnonymousAddress; } } }
void AbortRequests() { IDuplexRequest[] array = null; lock (ThisLock) { if (requests != null) { array = requests.ToArray(); foreach (IDuplexRequest request in array) { request.Abort(); } } requests = null; requestAborted = true; } // Remove requests from the correlator since the channel might be either faulting or aborting, // We are not going to get a reply for these requests. If they are not removed from the correlator, this will cause a leak. // This operation does not have to be under the lock if (array != null && array.Length > 0) { RequestReplyCorrelator requestReplyCorrelator = correlator as RequestReplyCorrelator; if (requestReplyCorrelator != null) { foreach (IDuplexRequest request in array) { ICorrelatorKey keyedRequest = request as ICorrelatorKey; if (keyedRequest != null) { requestReplyCorrelator.RemoveRequest(keyedRequest); } } } } //if there are any timed out requests, delete it from the correlator table DeleteTimedoutRequestsFromCorrelator(); }
public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) { IAsyncResult result2; bool flag = false; AsyncDuplexRequest request = null; try { RequestReplyCorrelator.PrepareRequest(message); request = new AsyncDuplexRequest(message, this, timeout, callback, state); lock (this.ThisLock) { this.RequestStarting(message, request); } IAsyncResult sendResult = this.channel.BeginSend(message, timeout, Fx.ThunkCallback(new AsyncCallback(this.SendCallback)), request); if (sendResult.CompletedSynchronously) { request.FinishedSend(sendResult, true); } this.EnsurePumping(); flag = true; result2 = request; } finally { lock (this.ThisLock) { if (flag) { request.EnableCompletion(); } else { this.RequestCompleting(request); } } } return(result2); }
public async Task <Message> RequestAsync(Message message, CancellationToken token) { AsyncDuplexRequest duplexRequest = null; bool optimized = false; RequestReplyCorrelator.PrepareRequest(message); lock (ThisLock) { if (!Pumping) { optimized = true; syncPumpEnabled = true; } if (!optimized) { duplexRequest = new AsyncDuplexRequest(this); } RequestStarting(message, duplexRequest); } if (optimized) { UniqueId messageId = message.Headers.MessageId; try { await channel.SendAsync(message, token); //if (DiagnosticUtility.ShouldUseActivity && // ServiceModelActivity.Current != null && // ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction) //{ // ServiceModelActivity.Current.Suspend(); //} for (;;) { var result = await channel.TryReceiveAsync(token); if (!result.Success) { // TODO: Derive CancellationToken to attach timeout throw TraceUtility.ThrowHelperError(GetReceiveTimeoutException(TimeSpan.Zero), message); } if (result.Result == null) { AbortRequests(); return(null); } if (result.Result.Headers.RelatesTo == messageId) { ThrowIfInvalidReplyIdentity(result.Result); return(result.Result); } else if (!HandleRequestAsReply(result.Result)) { // SFx drops a message here //if (DiagnosticUtility.ShouldTraceInformation) //{ // EndpointDispatcher dispatcher = null; // if (this.ChannelHandler != null && this.ChannelHandler.Channel != null) // { // dispatcher = this.ChannelHandler.Channel.EndpointDispatcher; // } // TraceUtility.TraceDroppedMessage(reply, dispatcher); //} result.Result.Close(); } } } finally { lock (ThisLock) { RequestCompleting(null); syncPumpEnabled = false; if (pending > 0) { EnsurePumping(); } } } } else { await channel.SendAsync(message, token); EnsurePumping(); return(await duplexRequest.WaitForReplyAsync(token)); } }
public Message Request(Message message, TimeSpan timeout) { SyncDuplexRequest request = null; bool flag = false; RequestReplyCorrelator.PrepareRequest(message); lock (this.ThisLock) { if (!this.Pumping) { flag = true; this.syncPumpEnabled = true; } if (!flag) { request = new SyncDuplexRequest(this); } this.RequestStarting(message, request); } if (flag) { TimeoutHelper helper = new TimeoutHelper(timeout); UniqueId messageId = message.Headers.MessageId; try { this.channel.Send(message, helper.RemainingTime()); if ((DiagnosticUtility.ShouldUseActivity && (ServiceModelActivity.Current != null)) && (ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction)) { ServiceModelActivity.Current.Suspend(); } while (true) { Message message2; TimeSpan span = helper.RemainingTime(); if (!this.channel.TryReceive(span, out message2)) { throw TraceUtility.ThrowHelperError(this.GetReceiveTimeoutException(timeout), message); } if (message2 == null) { this.AbortRequests(); return(null); } if (message2.Headers.RelatesTo == messageId) { this.ThrowIfInvalidReplyIdentity(message2); return(message2); } if (!this.HandleRequestAsReply(message2)) { if (DiagnosticUtility.ShouldTraceInformation) { EndpointDispatcher endpointDispatcher = null; if ((this.ChannelHandler != null) && (this.ChannelHandler.Channel != null)) { endpointDispatcher = this.ChannelHandler.Channel.EndpointDispatcher; } TraceUtility.TraceDroppedMessage(message2, endpointDispatcher); } message2.Close(); } } } finally { lock (this.ThisLock) { this.RequestCompleting(null); this.syncPumpEnabled = false; if (this.pending > 0) { this.EnsurePumping(); } } } } TimeoutHelper helper2 = new TimeoutHelper(timeout); this.channel.Send(message, helper2.RemainingTime()); this.EnsurePumping(); return(request.WaitForReply(helper2.RemainingTime())); }