public async Task Unsubscribe(string subscriptionName) { TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); ReceiverLink receiverLink = new ReceiverLink(UnderlyingSession, subscriptionName, new Attach { LinkName = subscriptionName }, (link, attach) => { Tracer.InfoFormat("Attempting to close subscription {0}. Attach response {1}", subscriptionName, attach); if (attach.Source is Source source) { Tracer.InfoFormat("Found subscription {0} on remote with source {1}.", subscriptionName, source); tcs.TrySetResult(true); } }); receiverLink.AddClosedCallback((sender, error) => { string failureMessage = string.Equals(sender.Error?.Condition, ErrorCode.NotFound) ? $"Cannot remove Subscription {subscriptionName} that does not exists" : $"Subscription {subscriptionName} unsubscribe operation failure"; NMSException exception = ExceptionSupport.GetException(sender, failureMessage); tcs.TrySetException(exception); }); await tcs.Task; receiverLink.Close(TimeSpan.FromMilliseconds(sessionInfo.closeTimeout)); }
public Task Attach() { Source source = CreateSource(); Target target = CreateTarget(); Attach frame = new Attach { Source = source, Target = target, SndSettleMode = SenderSettleMode.Unsettled, IncompleteUnsettled = false, InitialDeliveryCount = 0 }; string linkName = info.Id + ":" + target.Address; var taskCompletionSource = new TaskCompletionSource <bool>(); senderLink = new SenderLink(session.UnderlyingSession, linkName, frame, HandleOpened(taskCompletionSource)); senderLink.AddClosedCallback((sender, error) => { NMSException exception = ExceptionSupport.GetException(error, "Received Amqp link detach with Error for link {0}", info.Id); if (!taskCompletionSource.TrySetException(exception)) { session.RemoveProducer(info.Id); // If session is not closed it means that the link was remotely detached if (!senderLink.Session.IsClosed) { session.Connection.Provider.FireResourceClosed(info, exception); } } }); return(taskCompletionSource.Task); }
private void SendSync(global::Amqp.Message message, DeliveryState deliveryState) { ManualResetEvent manualResetEvent = new ManualResetEvent(false); Outcome outcome = null; senderLink.Send(message, deliveryState, Callback, manualResetEvent); if (!manualResetEvent.WaitOne((int)session.Connection.Provider.SendTimeout)) { throw new TimeoutException(Fx.Format(SRAmqp.AmqpTimeout, "send", session.Connection.Provider.SendTimeout, nameof(message))); } if (outcome == null) { return; } if (outcome.Descriptor.Name.Equals(MessageSupport.RELEASED_INSTANCE.Descriptor.Name)) { Error error = new Error(ErrorCode.MessageReleased); throw ExceptionSupport.GetException(error, $"Message {message.Properties.GetMessageId()} released"); } if (outcome.Descriptor.Name.Equals(MessageSupport.REJECTED_INSTANCE.Descriptor.Name)) { Rejected rejected = (Rejected)outcome; throw ExceptionSupport.GetException(rejected.Error, $"Message {message.Properties.GetMessageId()} rejected"); } void Callback(ILink l, global::Amqp.Message m, Outcome o, object s) { outcome = o; manualResetEvent.Set(); } }
public async Task <ISession> CreateSessionAsync(AcknowledgementMode acknowledgementMode) { CheckClosedOrFailed(); await CreateNmsConnectionAsync().Await(); NmsSession session = new NmsSession(this, GetNextSessionId(), acknowledgementMode); try { await session.Begin().Await(); sessions.TryAdd(session.SessionInfo.Id, session); if (started) { session.Start(); } return(session); } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Failed to establish amqp Session."); } }
public Task Start() { TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); var requestTimeout = Connection.Provider.RequestTimeout; if (requestTimeout > 0) { CancellationTokenSource ct = new CancellationTokenSource(TimeSpan.FromMilliseconds(requestTimeout)); ct.Token.Register(() => tcs.TrySetCanceled(), false); } UnderlyingSession = new Session(Connection.UnderlyingConnection, CreateBeginFrame(), (session, begin) => { tcs.TrySetResult(true); }); UnderlyingSession.AddClosedCallback((sender, error) => { if (!tcs.TrySetException(ExceptionSupport.GetException(error))) { Connection.RemoveSession(SessionInfo.Id); } }); return(tcs.Task); }
public ISession CreateSession(AcknowledgementMode acknowledgementMode) { CheckClosedOrFailed(); CreateNmsConnection(); NmsSession session = new NmsSession(this, SessionIdGenerator.GenerateId(), acknowledgementMode) { SessionInfo = { requestTimeout = ConnectionInfo.requestTimeout } }; try { session.Begin().ConfigureAwait(false).GetAwaiter().GetResult(); sessions.TryAdd(session.SessionInfo.Id, session); if (started) { session.Start(); } return(session); } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Failed to establish amqp Session."); } }
private void Disconnect() { if (this.state.CompareAndSet(ConnectionState.CONNECTED, ConnectionState.CLOSING) && this.impl != null) { Tracer.InfoFormat("Sending Close Request On Connection {0}.", ClientId); try { if (!this.impl.IsClosed) { this.impl.Close(TimeSpan.FromMilliseconds(connInfo.closeTimeout), null); } } catch (AmqpException amqpEx) { throw ExceptionSupport.Wrap(amqpEx, "Error Closing Amqp Connection " + ClientId); } catch (TimeoutException tmoutEx) { throw ExceptionSupport.GetTimeoutException(this.impl, "Timeout waiting for Amqp Connection {0} Close response. Message : {1}", ClientId, tmoutEx.Message); } finally { if (this.state.CompareAndSet(ConnectionState.CLOSING, ConnectionState.CLOSED)) { // connection cleanup. MessageFactory <ConnectionInfo> .Unregister(this); this.impl = null; } } } }
protected virtual void OnAttachResponse(ILink link, Attach attachResponse) { Tracer.InfoFormat("Received Performative Attach response on Link: {0}, Response: {1}", ConsumerId, attachResponse.ToString()); OnResponse(); if (link.Error != null) { this.Session.OnException(ExceptionSupport.GetException(link, "Consumer {0} Attach Failure.", this.ConsumerId)); } }
internal void OnConnectionClosed(Error error) { bool connectionExplicitlyClosed = error == null; if (!connectionExplicitlyClosed) { Listener?.OnConnectionFailure(ExceptionSupport.GetException(error)); } }
/// <summary>Gets a Task to represent the asynchronous operation.</summary> /// <param name="source">The asynchronous operation.</param> /// <param name="cancellationToken">The token used to request cancellation of the asynchronous operation.</param> /// <returns>The Task representing the asynchronous operation.</returns> public static Task <TResult> AsTask <TResult>(this IAsyncOperation <TResult> source, CancellationToken cancellationToken) { if (source == null) { throw new ArgumentNullException(nameof(source)); } Contract.EndContractBlock(); // If source is actually a NetFx-to-WinRT adapter, unwrap it instead of creating a new Task: var wrapper = source as TaskToAsyncOperationAdapter <TResult>; if (wrapper != null && !wrapper.CompletedSynchronously) { Task <TResult> innerTask = wrapper.Task as Task <TResult>; Debug.Assert(innerTask != null); Debug.Assert(innerTask.Status != TaskStatus.Created); // Is WaitingForActivation a legal state at this moment? if (!innerTask.IsCompleted) { // The race here is benign: If the task completes here, the concatination is useless, but not damaging. if (cancellationToken.CanBeCanceled && wrapper.CancelTokenSource != null) { ConcatenateCancelTokens(cancellationToken, wrapper.CancelTokenSource, innerTask); } } return(innerTask); } // Fast path to return a completed Task if the operation has already completed switch (source.Status) { case AsyncStatus.Completed: return(Task.FromResult(source.GetResults())); case AsyncStatus.Error: return(Task.FromException <TResult>(ExceptionSupport.AttachRestrictedErrorInfo(source.ErrorCode))); case AsyncStatus.Canceled: return(Task.FromCanceled <TResult>(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true))); } // Benign race: source may complete here. Things still work, just not taking the fast path. // Source is not a NetFx-to-WinRT adapter, but a native future. Hook up the task: var bridge = new AsyncInfoToTaskBridge <TResult, VoidValueTypeParameter>(cancellationToken); source.Completed = new AsyncOperationCompletedHandler <TResult>(bridge.CompleteFromAsyncOperation); bridge.RegisterForCancellation(source); return(bridge.Task); }
private X509Certificate2Collection LoadClientCertificates() { X509Certificate2Collection certificates = new X509Certificate2Collection(); if (!String.IsNullOrWhiteSpace(this.ClientCertFileName)) { Tracer.DebugFormat("Attempting to load Client Certificate file: {0}", this.ClientCertFileName); X509Certificate2 certificate = new X509Certificate2(this.ClientCertFileName, this.ClientCertPassword); Tracer.DebugFormat("Loaded Client Certificate: {0}", certificate.Subject); certificates.Add(certificate); } else { string storeName = String.IsNullOrWhiteSpace(this.KeyStoreName) ? StoreName.My.ToString() : this.KeyStoreName; StoreLocation storeLocation = StoreLocation.CurrentUser; if (!String.IsNullOrWhiteSpace(this.KeyStoreLocation)) { bool found = false; foreach (string location in Enum.GetNames(typeof(StoreLocation))) { if (String.Compare(this.KeyStoreLocation, location, true) == 0) { storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), location, true); found = true; break; } } if (!found) { throw new NMSException(string.Format("Invalid Store location {0}", this.KeyStoreLocation), NMSErrorCode.PROPERTY_ERROR); } } Tracer.DebugFormat("Loading store {0}, from location {1}.", storeName, storeLocation.ToString()); try { X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2[] storeCertificates = new X509Certificate2[store.Certificates.Count]; store.Certificates.CopyTo(storeCertificates, 0); certificates.AddRange(storeCertificates); } catch (Exception ex) { Tracer.WarnFormat("Error loading KeyStore, name : {0}; location : {1}. Cause {2}", storeName, storeLocation, ex); throw ExceptionSupport.Wrap(ex, "Error loading KeyStore.", storeName, storeLocation.ToString()); } } return(certificates); }
protected void DoAMQPSendAsync(Amqp.Message amqpMessage, OutcomeCallback ackCallback) { try { this.link.Send(amqpMessage, ackCallback, this); MsgsSentOnLink++; } catch (Exception ex) { Tracer.ErrorFormat("Encountered Error on sending message from Producer {0}. Message: {1}. Stack : {2}.", Id, ex.Message, ex.StackTrace); throw ExceptionSupport.Wrap(ex); } }
public void Close() { try { UnderlyingConnection?.Close(); } catch (Exception ex) { // log network errors NMSException nmse = ExceptionSupport.Wrap(ex, "Amqp Connection close failure for NMS Connection {0}", this.Info.Id); Tracer.DebugFormat("Caught Exception while closing Amqp Connection {0}. Exception {1}", this.Info.Id, nmse); } }
private ClosedCallback HandleClosed(TaskCompletionSource <bool> tsc) => (sender, error) => { NMSException exception = ExceptionSupport.GetException(error, "Received Amqp link detach with Error for link {0}", info.Id); if (!tsc.TrySetException(exception)) { session.RemoveConsumer(info.Id); // If session is not closed it means that the link was remotely detached if (!receiverLink.Session.IsClosed) { session.Connection.Provider.FireResourceClosed(info, exception); } } };
public void Close() { try { senderLink.Close(TimeSpan.FromMilliseconds(info.closeTimeout)); } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Failed to close Link {0}", this.info.Id); } }
protected void DispatchException(Exception ex) { Apache.NMS.ExceptionListener listener = this.ExceptionListener; if (listener != null) { // Wrap does nothing if this is already a NMS exception, otherwise // wrap it appropriately. listener(ExceptionSupport.Wrap(ex)); } else { Tracer.WarnFormat("Received Async exception. Type {0} Message {1}", ex.GetType().Name, ex.Message); Tracer.DebugFormat("Async Exception Stack {0}", ex); } }
public void Close() { try { var closeTimeout = session.Connection.Provider.CloseTimeout; senderLink.Close(TimeSpan.FromMilliseconds(closeTimeout)); } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Failed to close Link {0}", this.info.Id); } }
public async Task CloseAsync() { try { var closeTimeout = session.Connection.Provider.CloseTimeout; await senderLink.CloseAsync(TimeSpan.FromMilliseconds(closeTimeout)).AwaitRunContinuationAsync(); } catch (NMSException) { throw; } catch (Exception ex) { throw ExceptionSupport.Wrap(ex, "Failed to close Link {0}", this.info.Id); } }
public async Task CloseAsync() { try { if (UnderlyingConnection != null) { await UnderlyingConnection.CloseAsync().AwaitRunContinuationAsync(); } } catch (Exception ex) { // log network errors NMSException nmse = ExceptionSupport.Wrap(ex, "Amqp Connection close failure for NMS Connection {0}", this.Info.Id); Tracer.DebugFormat("Caught Exception while closing Amqp Connection {0}. Exception {1}", this.Info.Id, nmse); } }
public AmqpSendTask(SenderLink link, global::Amqp.Message message, DeliveryState deliveryState, long timeoutMillis) { if (timeoutMillis != NmsConnectionInfo.INFINITE) { this.timer = new Timer(OnTimer, this, timeoutMillis, -1); } try { link.Send(message, deliveryState, OnOutcome, this); } catch (Exception e) { this.timer?.Dispose(); this.SetException(ExceptionSupport.Wrap(e)); } }
public void Send(OutboundMessageDispatch envelope) { if (envelope.Message.Facade is AmqpNmsMessageFacade facade) { AmqpCodec.EncodeMessage(facade); global::Amqp.Message message = facade.Message; try { var transactionalState = session.TransactionContext?.GetTxnEnrolledState(); if (envelope.SendAsync) { SendAsync(message, transactionalState); } else { // TODO: Should be unified after https://github.com/Azure/amqpnetlite/pull/374 is sorted out if (transactionalState != null) { SendSync(message, transactionalState); } else { senderLink.Send(message, TimeSpan.FromMilliseconds(session.Connection.Provider.SendTimeout)); } } } catch (TimeoutException tex) { throw ExceptionSupport.GetTimeoutException(this.senderLink, tex.Message); } catch (AmqpException amqpEx) { string messageId = AmqpMessageIdHelper.ToMessageIdString(message.Properties?.GetMessageId()); throw ExceptionSupport.Wrap(amqpEx, $"Failure to send message {messageId} on Producer {info.Id}"); } catch (Exception ex) { Tracer.ErrorFormat( $"Encountered Error on sending message from Producer {info.Id}. Message: {ex.Message}. Stack : {ex.StackTrace}."); throw ExceptionSupport.Wrap(ex); } } }
protected override void OnFailure() { string failureMessage = ""; if (String.Compare(this.Link.Error?.Condition, Amqp.ErrorCode.NotFound, false) == 0) { failureMessage = string.Format( "Cannot remove Subscription {0} that does not exists", this.Info.SubscriptionName ); } else { failureMessage = string.Format("Subscription {0} unsubscribe operation failure", this.Info.SubscriptionName); } throw ExceptionSupport.GetException(this.Link, failureMessage); }
public Task Attach() { Target target = new Target(); Source source = CreateSource(); Attach attach = new Attach { Target = target, Source = source, RcvSettleMode = ReceiverSettleMode.First, SndSettleMode = (info.IsBrowser) ? SenderSettleMode.Settled : SenderSettleMode.Unsettled, }; string name; if (info.IsDurable) { name = info.SubscriptionName; } else { string destinationAddress = source.Address ?? ""; name = "nms:receiver:" + info.Id + (destinationAddress.Length == 0 ? "" : (":" + destinationAddress)); } var taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); link = new ReceiverLink(session.UnderlyingSession, name, attach, (link1, attach1) => { taskCompletionSource.SetResult(true); }); link.AddClosedCallback((sender, error) => { NMSException exception = ExceptionSupport.GetException(error, "Received Amqp link detach with Error for link {0}", info.Id); if (!taskCompletionSource.TrySetException(exception)) { session.RemoveConsumer(info.Id); // If session is not closed it means that the link was remotely detached if (!link.Session.IsClosed) { session.Connection.Provider.FireResourceClosed(info, exception); } } }); return(taskCompletionSource.Task); }
public void Send(OutboundMessageDispatch envelope) { if (envelope.Message.Facade is AmqpNmsMessageFacade facade) { AmqpCodec.EncodeMessage(facade); global::Amqp.Message message = facade.Message; try { // If the transaction has failed due to remote termination etc then we just indicate // the send has succeeded until the a new transaction is started. if (session.IsTransacted && session.IsTransactionFailed) { return; } var transactionalState = session.TransactionContext?.GetTxnEnrolledState(); if (envelope.SendAsync) { SendAsync(message, transactionalState); } else { SendSync(message, transactionalState); } } catch (TimeoutException tex) { throw ExceptionSupport.GetTimeoutException(this.senderLink, tex.Message); } catch (AmqpException amqpEx) { string messageId = AmqpMessageIdHelper.ToMessageIdString(message.Properties?.GetMessageId()); throw ExceptionSupport.Wrap(amqpEx, $"Failure to send message {messageId} on Producer {info.Id}"); } catch (Exception ex) { Tracer.ErrorFormat( $"Encountered Error on sending message from Producer {info.Id}. Message: {ex.Message}. Stack : {ex.StackTrace}."); throw ExceptionSupport.Wrap(ex); } } }
private void OnClosed(IAmqpObject sender, Error error) { if (Tracer.IsDebugEnabled) { Tracer.Debug($"Connection closed. {error}"); } bool connectionExplicitlyClosed = error == null; if (!connectionExplicitlyClosed) { var exception = ExceptionSupport.GetException(error); if (!this.tsc.TrySetException(exception)) { Provider.OnConnectionClosed(exception); } } }
private void OnInternalClosed(IAmqpObject sender, Error error) { string name = null; Connection self = null; try { self = this; // name should throw should the finalizer of the Connection object already completed. name = self.ClientId; Tracer.InfoFormat("Received Close Request for Connection {0}.", name); if (self.state.CompareAndSet(ConnectionState.CONNECTED, ConnectionState.CLOSED)) { // unexpected or amqp transport close. // notify any error to exception Dispatcher. if (error != null) { NMSException nmse = ExceptionSupport.GetException(error, "Connection {0} Closed.", name); self.OnException(nmse); } // shutdown connection facilities. if (self.IsStarted) { self.Shutdown(); } MessageFactory <ConnectionInfo> .Unregister(self); } else if (self.state.CompareAndSet(ConnectionState.CLOSING, ConnectionState.CLOSED)) { // application close. MessageFactory <ConnectionInfo> .Unregister(self); } self.latch?.countDown(); } catch (Exception ex) { Tracer.DebugFormat("Caught Exception during Amqp Connection close for NMS Connection{0}. Exception {1}", name != null ? (" " + name) : "", ex); } }
public void Close() { connectionSession?.Close(); foreach (var session in sessions.Values.ToArray()) { session.Close(); } try { UnderlyingConnection?.Close(); } catch (Exception ex) { // log network errors NMSException nmse = ExceptionSupport.Wrap(ex, "Amqp Connection close failure for NMS Connection {0}", this.info.Id); Tracer.DebugFormat("Caught Exception while closing Amqp Connection {0}. Exception {1}", this.info.Id, nmse); } }
protected void DoAMQPSendSync(Amqp.Message amqpMessage, TimeSpan timeout) { try { this.link.Send(amqpMessage, timeout); MsgsSentOnLink++; } catch (TimeoutException tex) { throw ExceptionSupport.GetTimeoutException(this.link, tex.Message); } catch (AmqpException amqpEx) { string messageId = MessageSupport.CreateNMSMessageId(amqpMessage.Properties.GetMessageId()); throw ExceptionSupport.Wrap(amqpEx, "Failure to send message {1} on Producer {0}", this.Id, messageId); } catch (Exception ex) { Tracer.ErrorFormat("Encountered Error on sending message from Producer {0}. Message: {1}. Stack : {2}.", Id, ex.Message, ex.StackTrace); throw ExceptionSupport.Wrap(ex); } }
public Task Start() { TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); if (sessionInfo.requestTimeout > 0) { CancellationTokenSource ct = new CancellationTokenSource(TimeSpan.FromMilliseconds(sessionInfo.requestTimeout)); ct.Token.Register(() => tcs.TrySetCanceled(), false); } underlyingSession = new global::Amqp.Session(Connection.UnderlyingConnection, CreateBeginFrame(), (session, begin) => { sessionInfo.remoteChannel = begin.RemoteChannel; tcs.TrySetResult(true); }); underlyingSession.AddClosedCallback((sender, error) => { tcs.TrySetException(ExceptionSupport.GetException(error)); }); return(tcs.Task); }
public void Send(OutboundMessageDispatch envelope) { if (envelope.Message.Facade is AmqpNmsMessageFacade facade) { AmqpCodec.EncodeMessage(facade); global::Amqp.Message message = facade.Message; try { var transactionalState = session.TransactionContext?.GetTxnEnrolledState(); if (envelope.SendAsync) { SendAsync(message, transactionalState); } else { SendSync(message, transactionalState); } } catch (TimeoutException tex) { throw ExceptionSupport.GetTimeoutException(this.senderLink, tex.Message); } catch (AmqpException amqpEx) { string messageId = AmqpMessageIdHelper.ToMessageIdString(message.Properties?.GetMessageId()); throw ExceptionSupport.Wrap(amqpEx, $"Failure to send message {messageId} on Producer {info.Id}"); } catch (Exception ex) { Tracer.ErrorFormat( $"Encountered Error on sending message from Producer {info.Id}. Message: {ex.Message}. Stack : {ex.StackTrace}."); throw ExceptionSupport.Wrap(ex); } } }