The Link class represents an AMQP link.
Наследование: Amqp.AmqpObject
Пример #1
0
        public static async Task<TransactionalState> GetTransactionalStateAsync(Link link)
        {
            Transaction txn = Transaction.Current;
            if (txn != null)
            {
                byte[] txnId = await instance.EnlistAsync(link, txn);
                return new TransactionalState() { TxnId = txnId };
            }

            return null;
        }
Пример #2
0
        Controller GetOrCreateController(Link link)
        {
            Controller controller;
            lock (this.SyncRoot)
            {
                if (!this.controllers.TryGetValue(link.Session.Connection, out controller))
                {
                    Session session = new Session(link.Session.Connection);
                    controller = new Controller(session);
                    controller.Closed += this.OnControllerClosed;
                    this.controllers.Add(link.Session.Connection, controller);
                }
            }

            return controller;
        }
Пример #3
0
        async Task<byte[]> EnlistAsync(Link link, Transaction txn)
        {
            string id = txn.TransactionInformation.LocalIdentifier;
            Enlistment enlistment;
            lock (this.SyncRoot)
            {
                if (!this.enlistments.TryGetValue(id, out enlistment))
                {
                    enlistment = new Enlistment(this, txn);
                    this.enlistments.Add(id, enlistment);
                    txn.TransactionCompleted += this.OnTransactionCompleted;

                    if (!txn.EnlistPromotableSinglePhase(enlistment))
                    {
                        this.enlistments.Remove(id);
                        txn.TransactionCompleted -= this.OnTransactionCompleted;
                        throw new InvalidOperationException("DTC not supported");
                    }
                }
            }

            return await enlistment.EnlistAsync(link);
        }
Пример #4
0
        internal virtual void OnAttach(Attach attach)
        {
            lock (this.ThisLock)
            {
                if (attach.Handle > this.handleMax)
                {
                    throw new AmqpException(ErrorCode.NotAllowed,
                        Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1));
                }

                for (int i = 0; i < this.localLinks.Length; ++i)
                {
                    Link link = this.localLinks[i];
                    if (link != null && string.Compare(link.Name, attach.LinkName) == 0)
                    {
                        link.OnAttach(attach.Handle, attach);

                        int count = this.remoteLinks.Length;
                        if (count - 1 < attach.Handle)
                        {
                            int size = Math.Min(count * 2, (int)this.handleMax + 1);
                            Link[] expanded = new Link[size];
                            Array.Copy(this.remoteLinks, expanded, count);
                            this.remoteLinks = expanded;
                        }

                        var remoteLink = this.remoteLinks[attach.Handle];
                        if (remoteLink != null)
                        {
                            throw new AmqpException(ErrorCode.HandleInUse,
                                Fx.Format(SRAmqp.AmqpHandleInUse, attach.Handle, remoteLink.Name));
                        }

                        this.remoteLinks[attach.Handle] = link;
                        return;
                    }
                }
            }

            throw new AmqpException(ErrorCode.NotFound,
                Fx.Format(SRAmqp.LinkNotFound, attach.LinkName));
        }
Пример #5
0
        internal uint AddLink(Link link)
        {
            this.ThrowIfEnded("AddLink");
            lock (this.ThisLock)
            {
                int count = this.localLinks.Length;
                for (int i = 0; i < count; ++i)
                {
                    if (this.localLinks[i] == null)
                    {
                        this.localLinks[i] = link;
                        return (uint)i;
                    }
                }

                if (count - 1 < this.handleMax)
                {
                    int size = Math.Min(count * 2, (int)this.handleMax + 1);
                    Link[] expanded = new Link[size];
                    Array.Copy(this.localLinks, expanded, count);
                    this.localLinks = expanded;
                    this.localLinks[count] = link;
                    return (ushort)count;
                }

                throw new AmqpException(ErrorCode.NotAllowed,
                    Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1));
            }
        }
Пример #6
0
            public async Task<byte[]> EnlistAsync(Link link)
            {
                if (this.txnid != null)
                {
                    return this.txnid;
                }

                lock (this.syncRoot)
                {
                    if (this.declareTask == null)
                    {
                        this.controller = this.owner.GetOrCreateController(link);
                        this.declareTask = this.controller.DeclareAsync();
                    }
                }

                return this.txnid = await this.declareTask;
            }
Пример #7
0
        internal Delivery RemoveDeliveries(Link link)
        {
            LinkedList list = null;
            lock (this.ThisLock)
            {
                Delivery temp = (Delivery)this.outgoingList.First;
                while (temp != null)
                {
                    Delivery curr = temp;
                    temp = (Delivery)temp.Next;
                    if (curr.Link == link)
                    {
                        this.outgoingList.Remove(curr);
                        if (list == null)
                        {
                            list = new LinkedList();
                        }

                        list.Add(curr);
                    }
                }
            }

            return list == null ? null : (Delivery)list.First;
        }
Пример #8
0
 internal void RemoveLink(Link link, uint remoteHandle)
 {
     lock (this.ThisLock)
     {
         this.localLinks[link.Handle] = null;
         this.remoteLinks[remoteHandle] = null;
     }
 }
Пример #9
0
        internal uint AddLink(Link link)
        {
            this.ThrowIfEnded("AddLink");
            lock (this.ThisLock)
            {
                int index = -1;
                int count = this.localLinks.Length;
                for (int i = 0; i < count; ++i)
                {
                    if (this.localLinks[i] == null)
                    {
                        if (index < 0)
                        {
                            index = i;
                        }
                    }
                    else if (string.Compare(this.localLinks[i].Name, link.Name) == 0)
                    {
                        throw new AmqpException(ErrorCode.NotAllowed, link.Name + " has been attached.");
                    }
                }

                if (index >= 0)
                {
                    this.localLinks[index] = link;
                    return (uint)index;
                }

                if (count - 1 < this.handleMax)
                {
                    int size = (int)Math.Min(count * 2 - 1, this.handleMax) + 1;
                    Link[] expanded = new Link[size];
                    Array.Copy(this.localLinks, expanded, count);
                    this.localLinks = expanded;
                    this.localLinks[count] = link;
                    return (ushort)count;
                }

                throw new AmqpException(ErrorCode.NotAllowed,
                    Fx.Format(SRAmqp.AmqpHandleExceeded, this.handleMax + 1));
            }
        }
Пример #10
0
        internal void AddRemoteLink(uint remoteHandle, Link link)
        {
            lock (this.ThisLock)
            {
                int count = this.remoteLinks.Length;
                if (count - 1 < remoteHandle)
                {
                    int size = (int)Math.Min(count * 2 - 1, this.handleMax) + 1;
                    Link[] expanded = new Link[size];
                    Array.Copy(this.remoteLinks, expanded, count);
                    this.remoteLinks = expanded;
                }

                var remoteLink = this.remoteLinks[remoteHandle];
                if (remoteLink != null)
                {
                    throw new AmqpException(ErrorCode.HandleInUse,
                        Fx.Format(SRAmqp.AmqpHandleInUse, remoteHandle, remoteLink.Name));
                }

                this.remoteLinks[remoteHandle] = link;
            }
        }
Пример #11
0
        void AddLink(Link link, bool role, string source, string target)
        {
            int index;
            link.Handle = this.GetLinkHandle(out index);
            link.RemoteHandle = (uint)~index;
            this.links[index] = link;

            link.State = AttachSent;
            List attach = new List()
            {
                link.Name, link.Handle, link.Role, null, null,
                new DescribedValue(0x28ul, new List() { source }),
                new DescribedValue(0x29ul, new List() { target })
            };

            this.WriteFrame(0, 0, 0x12, attach);
            Fx.DebugPrint(true, 0, "attach", attach, "name", "handle", "role", "snd-mode", "rcv-mode", "source", "target");
        }
Пример #12
0
 void RaiseErrorEvent(Link link, Symbol error)
 {
     var onError = this.OnError;
     if (onError != null)
     {
         onError.Invoke(this, link, error);
     }
 }
Пример #13
0
 internal void CloseLink(Link link)
 {
     link.State |= DetachSent;
     List detach = new List { link.Handle, true };
     this.WriteFrame(0, 0, 0x16, detach);
     Fx.DebugPrint(true, 0, "detach", detach, "handle");
     try
     {
         this.Wait(o => (((Link)o).State & DetachReceived) == 0, link, 60000);
     }
     finally
     {
         link.State = 0xff;
         int index = (int)link.RemoteHandle;
         lock (this)
         {
             if (index >= 0)
             {
                 this.links[index] = null;
             }
             else
             {
                 this.links[~index] = null;
             }
         }
     }
 }
Пример #14
0
 static void client_OnError(Client client, Link link, Symbol error)
 {
     Microsoft.SPOT.Debug.Print((link != null ? "Link" : "Client") + " was closed due to error " + (error ?? "[unknown]"));
 }
Пример #15
0
        void OnFrame(ushort channel, ulong code, List fields, ByteBuffer payload)
        {
            switch (code)
            {
            case 0x10ul:      // open
                Fx.DebugPrint(false, channel, "open", fields, "container-id", "host-name", "max-frame-size", "channel-max", "idle-time-out");
                this.state |= OpenReceived;

                // process open.idle-time-out if exists: final value is determined by the min of the local and the remote values
                uint remoteValue = uint.MaxValue;
                if (fields.Count >= 5 && fields[4] != null)
                {
                    remoteValue = (uint)fields[4];
                }
                uint timeout = this.idleTimeout < remoteValue ? this.idleTimeout : remoteValue;
                if (timeout < uint.MaxValue)
                {
                    timeout            -= 5000;
                    timeout             = timeout > MaxIdleTimeout ? MaxIdleTimeout : timeout;
                    this.heartBeatTimer = new Timer(onHeartBeatTimer, this, (int)timeout, (int)timeout);
                }
                break;

            case 0x11ul:      // begin
                Fx.DebugPrint(false, channel, "begin", fields, "remote-channel", "next-outgoing-id", "incoming-window", "outgoing-window", "handle-max");
                this.nextIncomingId = (uint)fields[1];
                this.outWindow      = (uint)fields[2];
                this.state         |= BeginReceived;
                break;

            case 0x12ul:      // attach
            {
                Fx.DebugPrint(false, channel, "attach", fields, "name", "handle", "role", "snd-mode", "rcv-mode", "source", "target");
                Link link         = null;
                uint remoteHandle = (uint)fields[1];
                Fx.AssertAndThrow(ErrorCode.ClientInvalidHandle, remoteHandle < this.links.Length);
                lock (this)
                {
                    for (int i = 0; i < this.links.Length; i++)
                    {
                        if (this.links[i] != null && this.links[i].Name.Equals(fields[0]))
                        {
                            link = this.links[i];
                            int index = (int)~link.RemoteHandle;
                            Fx.AssertAndThrow(ErrorCode.ClientInvalidHandle, index == i);
                            if (index != (int)remoteHandle)
                            {
                                Fx.AssertAndThrow(ErrorCode.ClientHandlInUse, this.links[(int)remoteHandle] == null);
                                this.links[(int)remoteHandle] = link;
                                this.links[i] = null;
                            }
                            break;
                        }
                    }
                }
                Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null);
                link.RemoteHandle = remoteHandle;
                link.State       |= AttachReceived;
                link.OnAttach(fields);
                break;
            }

            case 0x13ul:      // flow
            {
                Fx.DebugPrint(false, channel, "flow", fields, "next-in-id", "in-window", "next-out", "out-window", "handle", "dc", "credit");
                uint nextIncomingId = (uint)fields[0];
                uint incomingWindow = (uint)fields[1];
                lock (this)
                {
                    this.outWindow = incomingWindow < uint.MaxValue ?
                                     nextIncomingId + incomingWindow - this.nextOutgoingId :
                                     uint.MaxValue;
                }

                if (fields[4] != null)
                {
                    Link link = this.links[(uint)fields[4]];
                    Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null);
                    link.OnFlow(fields);
                }
                break;
            }

            case 0x14ul:      // transfer
            {
                lock (this)
                {
                    this.nextOutgoingId++;
                    if (--this.inWindow == 0)
                    {
                        this.inWindow = DefaultWindowSize;
                        List flow = new List()
                        {
                            this.nextIncomingId, this.inWindow, this.nextOutgoingId, this.outWindow
                        };
                        this.WriteFrame(0, 0, 0x13, flow);
                        Fx.DebugPrint(true, 0, "flow", flow, "next-in-id", "in-window", "next-out", "out-window", "handle", "dc", "credit");
                    }
                }

                Link link = this.links[(uint)fields[0]];
                Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null);
                ((Receiver)link).OnTransfer(fields, payload);
                break;
            }

            case 0x15ul:      // disposition
            {
                Fx.DebugPrint(false, channel, "disposition", fields, "role", "first", "last");
                bool role  = (bool)fields[0];
                uint first = (uint)fields[1];
                uint last  = fields[2] == null ? first : (uint)fields[2];
                for (int i = 0; i < this.links.Length; i++)
                {
                    Link link = this.links[i];
                    if (link != null && role != link.Role)
                    {
                        link.OnDisposition(first, last, fields[4] as DescribedValue);
                    }
                }
                break;
            }

            case 0x16ul:      // detach
            {
                Fx.DebugPrint(false, channel, "detach", fields, "handle");
                Link link = this.links[(uint)fields[0]];
                Fx.AssertAndThrow(ErrorCode.ClientLinkNotFound, link != null);
                link.State |= DetachReceived;
                if ((link.State & DetachSent) == 0)
                {
                    this.CloseLink(link);
                    this.RaiseErrorEvent(link, GetError(fields, 2));
                }
                break;
            }

            case 0x17ul:      // end
                Fx.DebugPrint(false, channel, "end", null);
                this.state |= EndReceived;
                if ((this.state & EndSent) == 0)
                {
                    this.WriteFrame(0, 0, 0x17ul, new List());
                    Fx.DebugPrint(true, channel, "end", null);
                    this.ClearLinks();
                }
                break;

            case 0x18ul:      // close
                Fx.DebugPrint(false, channel, "close", null);
                this.state |= CloseReceived;
                if ((this.state & CloseSent) == 0)
                {
                    this.Close();
                    this.RaiseErrorEvent(null, GetError(fields, 0));
                }
                break;

            default:
                Fx.AssertAndThrow(ErrorCode.ClientInvalidCodeOnFrame, false);
                break;
            }
        }