Ejemplo n.º 1
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;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Establish a connection and a session for the client.
        /// </summary>
        /// <param name="host">The network host name or IP address to connect.</param>
        /// <param name="port">The port to connect.</param>
        /// <param name="useSsl">If true, use secure socket.</param>
        /// <param name="userName">If set, the user name for authentication.</param>
        /// <param name="password">If set, the password for authentication.</param>
        public void Connect(string host, int port, bool useSsl, string userName, string password)
        {
            this.transport = Connect(host, port, useSsl);

            byte[] header = new byte[8] {
                (byte)'A', (byte)'M', (byte)'Q', (byte)'P', 0, 1, 0, 0
            };
            byte[] retHeader;
            if (userName != null)
            {
                header[4] = 3;
                this.transport.Write(header, 0, 8);
                Fx.DebugPrint(true, 0, "AMQP", new List {
                    string.Concat(header[5], header[6], header[7])
                }, header[4]);

                byte[] b1 = Encoding.UTF8.GetBytes(userName);
                byte[] b2 = Encoding.UTF8.GetBytes(password ?? string.Empty);
                byte[] b  = new byte[1 + b1.Length + 1 + b2.Length];
                Array.Copy(b1, 0, b, 1, b1.Length);
                Array.Copy(b2, 0, b, b1.Length + 2, b2.Length);
                List saslInit = new List()
                {
                    new Symbol("PLAIN"), b
                };
                this.WriteFrame(1, 0, 0x41, saslInit);
                Fx.DebugPrint(true, 0, "sasl-init", saslInit, "mechanism");
                this.transport.Flush();

                retHeader = this.ReadFixedSizeBuffer(8);
                Fx.DebugPrint(false, 0, "AMQP", new List {
                    string.Concat(retHeader[5], retHeader[6], retHeader[7])
                }, retHeader[4]);
                Fx.AssertAndThrow(ErrorCode.ClientInitializeHeaderCheckFailed, AreHeaderEqual(header, retHeader));

                List body = this.ReadFrameBody(1, 0, 0x40);
                Fx.DebugPrint(false, 0, "sasl-mechanisms", body, "server-mechanisms");
                Fx.AssertAndThrow(ErrorCode.ClientInitializeWrongBodyCount, body.Count > 0);
                Symbol[] mechanisms = GetSymbolMultiple(body[0]);
                Fx.AssertAndThrow(ErrorCode.ClientInitializeWrongSymbol, Array.IndexOf(mechanisms, new Symbol("PLAIN")) >= 0);

                body = this.ReadFrameBody(1, 0, 0x44);
                Fx.AssertAndThrow(ErrorCode.ClientInitializeWrongBodyCount, body.Count > 0);
                Fx.DebugPrint(false, 0, "sasl-outcome", body, "code");
                Fx.AssertAndThrow(ErrorCode.ClientInitializeSaslFailed, body[0].Equals((byte)0));   // sasl-outcome.code = OK

                header[4] = 0;
            }

            this.transport.Write(header, 0, 8);
            Fx.DebugPrint(true, 0, "AMQP", new List {
                string.Concat(header[5], header[6], header[7])
            }, header[4]);

            // perform open
            this.state |= OpenSent;
            var open = new List()
            {
                Guid.NewGuid().ToString(), this.hostName ?? host, MaxFrameSize, (ushort)0
            };

            this.WriteFrame(0, 0, 0x10, open);
            Fx.DebugPrint(true, 0, "open", open, "container-id", "host-name", "max-frame-size", "channel-max", "idle-time-out");

            // perform begin
            this.state |= BeginSent;
            var begin = new List()
            {
                null, this.nextOutgoingId, this.inWindow, this.outWindow, (uint)(this.links.Length - 1)
            };

            this.WriteFrame(0, 0, 0x11, begin);
            Fx.DebugPrint(true, 0, "begin", begin, "remote-channel", "next-outgoing-id", "incoming-window", "outgoing-window", "handle-max");

            retHeader = this.ReadFixedSizeBuffer(8);
            Fx.DebugPrint(false, 0, "AMQP", new List {
                string.Concat(retHeader[5], retHeader[6], retHeader[7])
            }, retHeader[4]);
            Fx.AssertAndThrow(ErrorCode.ClientInitializeHeaderCheckFailed, AreHeaderEqual(header, retHeader));
            new Thread(this.PumpThread).Start();
        }