Esempio n. 1
0
        internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
        {
            if (delivery == null)
            {
                delivery = this.deliveryCurrent;
                AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
            }
            else
            {
                buffer.AddReference();
                delivery.Buffer = buffer;
                lock (this.ThisLock)
                {
                    this.OnDelivery(transfer.DeliveryId);
                }
            }

            if (!transfer.More)
            {
                this.deliveryCurrent = null;
                delivery.Message     = Message.Decode(delivery.Buffer);

                Waiter          waiter;
                MessageCallback callback = this.onMessage;
                lock (this.ThisLock)
                {
                    waiter = (Waiter)this.waiterList.First;
                    if (waiter != null)
                    {
                        this.waiterList.Remove(waiter);
                    }
                    else if (callback == null)
                    {
                        this.receivedMessages.Add(new MessageNode()
                        {
                            Message = delivery.Message
                        });
                        return;
                    }
                }

                while (waiter != null)
                {
                    if (waiter.Signal(delivery.Message))
                    {
                        return;
                    }

                    lock (this.ThisLock)
                    {
                        waiter = (Waiter)this.waiterList.First;
                        if (waiter != null)
                        {
                            this.waiterList.Remove(waiter);
                        }
                        else if (callback == null)
                        {
                            this.receivedMessages.Add(new MessageNode()
                            {
                                Message = delivery.Message
                            });
                            return;
                        }
                    }
                }

                Fx.Assert(waiter == null, "waiter must be null now");
                Fx.Assert(callback != null, "callback must not be null now");
                callback(this, delivery.Message);
            }
            else
            {
                this.deliveryCurrent = delivery;
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Sets the read position.
 /// </summary>
 /// <param name="seekPosition">Position to set.</param>
 public void Seek(int seekPosition)
 {
     Fx.Assert(seekPosition >= 0, "seekPosition must not be negative.");
     Fx.Assert((this.start + seekPosition) <= this.write, "seekPosition too large.");
     this.read = this.start + seekPosition;
 }
Esempio n. 3
0
 /// <summary>
 /// Moves back the write position. As a result, length is decreased by size.
 /// </summary>
 /// <param name="size"></param>
 public void Shrink(int size)
 {
     Fx.Assert(size >= 0 && size <= this.Length, "size must be positive and not greater then length.");
     this.write -= size;
 }
Esempio n. 4
0
 /// <summary>
 /// Advances the write position. As a result, length is increased by size.
 /// </summary>
 /// <param name="size">Size to advance.</param>
 public void Append(int size)
 {
     Fx.Assert(size >= 0, "size must be positive.");
     Fx.Assert((this.write + size) <= this.end, "Append size too large.");
     this.write += size;
 }
Esempio n. 5
0
 /// <summary>
 /// Advances the read position.
 /// </summary>
 /// <param name="size">Size to advance.</param>
 public void Complete(int size)
 {
     Fx.Assert(size >= 0, "size must be positive.");
     Fx.Assert((this.read + size) <= this.write, "Complete size too large.");
     this.read += size;
 }
Esempio n. 6
0
        void Parse(string address)
        {
            //  amqp[s]://user:[email protected]:port/foo/bar
            ParseState state = ParseState.Scheme;
            int startIndex = 0;
            for (int i = 0; i < address.Length; ++i)
            {
                switch (address[i])
                {
                    case ':':
                        if (state == ParseState.Scheme)
                        {
                            this.Scheme = address.Substring(startIndex, i - startIndex);
                            state = ParseState.Slash1;
                        }
                        else if (state == ParseState.User)
                        {
                            this.User = address.Substring(startIndex, i - startIndex);
                            state = ParseState.Password;
                            startIndex = i + 1;
                        }
                        else if (state == ParseState.Host)
                        {
                            this.Host = address.Substring(startIndex, i - startIndex);
                            state = ParseState.Port;
                            startIndex = i + 1;
                        }
                        else
                        {
                            throw new AmqpException(ErrorCode.InvalidField,
                                Fx.Format(SRAmqp.InvalidAddressFormat));
                        }
                        break;
                    case '/':
                        if (state == ParseState.Slash1)
                        {
                            state = ParseState.Slash2;
                        }
                        else if (state == ParseState.Slash2)
                        {
                            state = ParseState.User;
                            startIndex = i + 1;
                        }
                        else if (state == ParseState.User || state == ParseState.Host)
                        {
                            this.Host = address.Substring(startIndex, i - startIndex);
                            state = ParseState.Path;
                            startIndex = i;
                        }
                        else if (state == ParseState.Port)
                        {
                            this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
                            state = ParseState.Path;
                            startIndex = i;
                        }
                        else if (state == ParseState.Password)
                        {
                            this.Host = this.User;
                            this.User = null;
                            this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
                            state = ParseState.Path;
                            startIndex = i;
                        }
                        break;
                    case '@':
                        if (state == ParseState.Password)
                        {
                            this.Password = address.Substring(startIndex, i - startIndex);
                            state = ParseState.Host;
                            startIndex = i + 1;
                        }
                        else
                        {
                            throw new AmqpException(ErrorCode.InvalidField,
                                Fx.Format(SRAmqp.InvalidAddressFormat));
                        }
                        break;
                    default:
                        break;
                }

                if (state == ParseState.Path)
                {
                    this.Path = address.Substring(startIndex);
                    break;
                }
            }

            // check state in case of no trailing slash
            if (state == ParseState.User || state == ParseState.Host)
            {
                this.Host = address.Substring(startIndex);
            }
            else if (state == ParseState.Password)
            {
                this.Host = this.User;
                this.User = null;
                if (startIndex < address.Length - 1)
                {
                    this.Port = int.Parse(address.Substring(startIndex));
                }
            }
            else if (state == ParseState.Port)
            {
                this.Port = int.Parse(address.Substring(startIndex));
            }

            if (this.Password != null && this.Password.Length > 0)
            {
                this.Password = Uri.UnescapeDataString(this.Password);
            }

            if (this.User != null && this.User.Length > 0)
            {
                this.User = Uri.UnescapeDataString(this.User);
            }

            if (this.Host != null)
            {
                this.Host = Uri.UnescapeDataString(this.Host);
            }
        }
Esempio n. 7
0
 public void Start()
 {
     Fx.StartThread(this.PumpThread);
 }
Esempio n. 8
0
        internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
        {
            if (!transfer.More)
            {
                Waiter          waiter;
                MessageCallback callback;
                lock (this.ThisLock)
                {
                    if (delivery == null)
                    {
                        // multi-transfer delivery
                        delivery             = this.deliveryCurrent;
                        this.deliveryCurrent = null;
                        Fx.Assert(delivery != null, "Must have a delivery in the queue");
                        AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
                        delivery.Message = Message.Decode(delivery.Buffer);
                        delivery.Buffer  = null;
                    }
                    else
                    {
                        // single tranfer delivery
                        this.OnDelivery(transfer.DeliveryId);
                        delivery.Message = Message.Decode(buffer);
                    }

                    callback = this.onMessage;
                    waiter   = (Waiter)this.waiterList.First;
                    if (waiter != null)
                    {
                        this.waiterList.Remove(waiter);
                    }

                    if (waiter == null && callback == null)
                    {
                        this.receivedMessages.Add(new MessageNode()
                        {
                            Message = delivery.Message
                        });
                        return;
                    }
                }

                while (waiter != null)
                {
                    if (waiter.Signal(delivery.Message))
                    {
                        this.OnDeliverMessage();
                        return;
                    }

                    lock (this.ThisLock)
                    {
                        waiter = (Waiter)this.waiterList.First;
                        if (waiter != null)
                        {
                            this.waiterList.Remove(waiter);
                        }
                        else if (callback == null)
                        {
                            this.receivedMessages.Add(new MessageNode()
                            {
                                Message = delivery.Message
                            });
                            return;
                        }
                    }
                }

                Fx.Assert(waiter == null, "waiter must be null now");
                Fx.Assert(callback != null, "callback must not be null now");
                callback(this, delivery.Message);
                this.OnDeliverMessage();
            }
            else
            {
                lock (this.ThisLock)
                {
                    if (delivery == null)
                    {
                        delivery = this.deliveryCurrent;
                        Fx.Assert(delivery != null, "Must have a current delivery");
                        AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
                    }
                    else
                    {
                        this.OnDelivery(transfer.DeliveryId);
                        delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
                        AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
                        this.deliveryCurrent = delivery;
                    }
                }
            }
        }
Esempio n. 9
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;
            }
        }
Esempio n. 10
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();
        }