示例#1
0
        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));
        }
示例#2
0
        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);
        }
示例#3
0
        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();
            }
        }
示例#4
0
        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.");
            }
        }
示例#5
0
        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.");
            }
        }
示例#7
0
        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);
        }
示例#12
0
 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);
     }
 }
示例#13
0
 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);
     }
 }
示例#14
0
        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);
     }
 }
示例#16
0
 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);
     }
 }
示例#17
0
 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);
     }
 }
示例#18
0
 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);
     }
 }
示例#19
0
 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);
     }
 }
示例#20
0
        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);
                }
            }
        }
示例#22
0
        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);
        }
示例#24
0
        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);
                }
            }
        }
示例#25
0
        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);
                }
            }
        }
示例#26
0
        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);
            }
        }
示例#28
0
 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);
                }
            }
        }