Example #1
0
        private bool IdentifyPeer(Pipe pipe)
        {
            byte[] identity;

            if (m_options.RawSocket)
            {
                // Always assign identity for raw-socket
                identity = new byte[5];
                byte[] result = BitConverter.GetBytes(m_nextPeerId++);
                Buffer.BlockCopy(result, 0, identity, 1, 4);
            }
            else
            {
                // Pick up handshake cases and also case where next identity is set

                var msg = new Msg();
                msg.InitEmpty();

                bool ok = pipe.Read(ref msg);

                if (!ok)
                {
                    return(false);
                }

                if (msg.Size == 0)
                {
                    // Fall back on the auto-generation
                    identity = new byte[5];

                    byte[] result = BitConverter.GetBytes(m_nextPeerId++);

                    Buffer.BlockCopy(result, 0, identity, 1, 4);

                    msg.Close();
                }
                else
                {
                    identity = msg.CloneData();

                    // Ignore peers with duplicate ID.
                    if (m_outpipes.ContainsKey(identity))
                    {
                        msg.Close();
                        return(false);
                    }

                    msg.Close();
                }
            }

            pipe.Identity = identity;
            // Add the record into output pipes lookup table
            var outpipe = new Outpipe(pipe, true);

            m_outpipes.Add(identity, outpipe);

            return(true);
        }
Example #2
0
        /// <summary>
        /// Indicate the given pipe as being ready for reading by this socket.
        /// </summary>
        /// <param name="pipe">the <c>Pipe</c> that is now becoming available for reading</param>
        protected override void XReadActivated(Pipe pipe)
        {
            // There are some subscriptions waiting. Let's process them.
            var sub = new Msg();

            while (pipe.Read(ref sub))
            {
                // Apply the subscription to the trie.
                byte[] data = sub.Data;
                int    size = sub.Size;
                if (size > 0 && (data[0] == 0 || data[0] == 1))
                {
                    if (m_manual)
                    {
                        m_lastPipe = pipe;

                        m_pending.Enqueue(sub.CloneData());
                    }
                    else
                    {
                        var unique = data[0] == 0
                            ? m_subscriptions.Remove(data, 1, size - 1, pipe)
                            : m_subscriptions.Add(data, 1, size - 1, pipe);

                        // If the subscription is not a duplicate, store it so that it can be
                        // passed to used on next recv call.
                        if (m_options.SocketType == ZmqSocketType.Xpub && (unique || m_verbose))
                        {
                            m_pending.Enqueue(sub.CloneData());
                        }
                    }
                }
                else // process message unrelated to sub/unsub
                {
                    m_pending.Enqueue(sub.CloneData());
                }

                sub.Close();
            }
        }
Example #3
0
        private bool IdentifyPeer([NotNull] Pipe pipe)
        {
            byte[] identity;

            if (m_options.RawSocket)
            {
                // Always assign identity for raw-socket
                identity = new byte[5];
                byte[] result = BitConverter.GetBytes(m_nextPeerId++);
                Buffer.BlockCopy(result, 0, identity, 1, 4);
            }
            else
            {
                // Pick up handshake cases and also case where next identity is set

                var msg = new Msg();
                msg.InitEmpty();

                bool ok = pipe.Read(ref msg);

                if (!ok)
                {
                    return(false);
                }

                if (msg.Size == 0)
                {
                    // Fall back on the auto-generation
                    identity = new byte[5];

                    byte[] result = BitConverter.GetBytes(m_nextPeerId++);

                    Buffer.BlockCopy(result, 0, identity, 1, 4);

                    msg.Close();
                }
                else
                {
                    identity = msg.CloneData();
                    msg.Close();

                    Outpipe existPipe;

                    if (m_outpipes.TryGetValue(identity, out existPipe))
                    {
                        if (!m_handover)
                        {
                            // Ignore peers with duplicate ID.
                            return(false);
                        }
                        else
                        {
                            //  We will allow the new connection to take over this
                            //  identity. Temporarily assign a new identity to the
                            //  existing pipe so we can terminate it asynchronously.
                            var    newIdentity = new byte[5];
                            byte[] result      = BitConverter.GetBytes(m_nextPeerId++);
                            Buffer.BlockCopy(result, 0, newIdentity, 1, 4);
                            existPipe.Pipe.Identity = newIdentity;
                            m_outpipes.Add(newIdentity, existPipe);

                            //  Remove the existing identity entry to allow the new
                            //  connection to take the identity.
                            m_outpipes.Remove(identity);

                            if (existPipe.Pipe == m_currentIn)
                            {
                                m_closingCurrentIn = true;
                            }
                            else
                            {
                                existPipe.Pipe.Terminate(true);
                            }
                        }
                    }
                }
            }

            pipe.Identity = identity;
            // Add the record into output pipes lookup table
            var outpipe = new Outpipe(pipe, true);

            m_outpipes.Add(identity, outpipe);

            return(true);
        }
Example #4
0
        /// <summary>
        /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending.
        /// </summary>
        /// <param name="msg">the message to transmit</param>
        /// <returns><c>true</c> if the message was sent successfully</returns>
        /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception>
        protected override bool XSend(ref Msg msg)
        {
            // If this is the first part of the message it's the ID of the
            // peer to send the message to.
            if (!m_moreOut)
            {
                Debug.Assert(m_currentOut == null);

                // If we have malformed message (prefix with no subsequent message)
                // then just silently ignore it.
                // TODO: The connections should be killed instead.
                if (msg.HasMore)
                {
                    m_moreOut = true;

                    // Find the pipe associated with the identity stored in the prefix.
                    // If there's no such pipe just silently ignore the message, unless
                    // mandatory is set.

                    var identity = msg.Size == msg.Data.Length
                        ? msg.Data
                        : msg.CloneData();

                    Outpipe op;

                    if (m_outpipes.TryGetValue(identity, out op))
                    {
                        m_currentOut = op.Pipe;
                        if (!m_currentOut.CheckWrite())
                        {
                            op.Active    = false;
                            m_currentOut = null;
                            if (m_mandatory)
                            {
                                m_moreOut = false;
                                return(false);
                            }
                        }
                    }
                    else if (m_mandatory)
                    {
                        m_moreOut = false;
                        throw new HostUnreachableException("In Router.XSend");
                    }
                }

                // Detach the message from the data buffer.
                msg.Close();
                msg.InitEmpty();

                return(true);
            }

            if (m_options.RawSocket)
            {
                msg.ResetFlags(MsgFlags.More);
            }

            // Check whether this is the last part of the message.
            m_moreOut = msg.HasMore;

            // Push the message into the pipe. If there's no out pipe, just drop it.
            if (m_currentOut != null)
            {
                // Close the remote connection if user has asked to do so
                // by sending zero length message.
                // Pending messages in the pipe will be dropped (on receiving term-ack)
                if (m_rawSocket && msg.Size == 0)
                {
                    m_currentOut.Terminate(false);
                    msg.Close();
                    msg.InitEmpty();
                    m_currentOut = null;
                    return(true);
                }

                bool ok = m_currentOut.Write(ref msg);
                if (!ok)
                {
                    m_currentOut = null;
                }
                else if (!m_moreOut)
                {
                    m_currentOut.Flush();
                    m_currentOut = null;
                }
            }
            else
            {
                msg.Close();
            }

            // Detach the message from the data buffer.
            msg.InitEmpty();

            return(true);
        }
Example #5
0
        /// <summary>
        ///     Transmit the given message. The <c>Send</c> method calls this to do the actual sending.
        /// </summary>
        /// <param name="msg">the message to transmit</param>
        /// <returns><c>true</c> if the message was sent successfully</returns>
        /// <exception cref="HostUnreachableException">In Stream.XSend</exception>
        protected override bool XSend(ref Msg msg)
        {
            // If this is the first part of the message it's the ID of the
            // peer to send the message to.
            if (!this.m_moreOut)
            {
                Debug.Assert(this.m_currentOut == null);

                // If we have malformed message (prefix with no subsequent message)
                // then just silently ignore it.
                // TODO: The connections should be killed instead.
                if (msg.HasMore)
                {
                    // Find the pipe associated with the identity stored in the prefix.
                    // If there's no such pipe just silently ignore the message, unless
                    // mandatory is set.

                    byte[] identity = msg.Size == msg.Data.Length
                        ? msg.Data
                        : msg.CloneData();

                    Outpipe op;
                    if (this.m_outpipes.TryGetValue(identity, out op))
                    {
                        this.m_currentOut = op.Pipe;
                        if (!this.m_currentOut.CheckWrite())
                        {
                            op.Active         = false;
                            this.m_currentOut = null;
                            return(false);
                        }
                    }
                    else
                    {
                        throw new HostUnreachableException("In Stream.XSend");
                    }
                }

                this.m_moreOut = true;

                msg.Close();
                msg.InitEmpty();

                return(true);
            }

            // Ignore the MORE flag
            msg.ResetFlags(MsgFlags.More);

            // This is the last part of the message.
            this.m_moreOut = false;

            // Push the message into the pipe. If there's no out pipe, just drop it.
            if (this.m_currentOut != null)
            {
                if (msg.Size == 0)
                {
                    this.m_currentOut.Terminate(false);
                    this.m_currentOut = null;
                    return(true);
                }

                bool ok = this.m_currentOut.Write(ref msg);
                if (ok)
                {
                    this.m_currentOut.Flush();
                }

                this.m_currentOut = null;
            }

            // Detach the message from the data buffer.
            msg.InitEmpty();

            return(true);
        }
Example #6
0
        private bool IdentifyPeer( Pipe pipe)
        {
            byte[] identity;

            if (m_options.RawSocket)
            {
                // Always assign identity for raw-socket
                identity = new byte[5];
                byte[] result = BitConverter.GetBytes(m_nextPeerId++);
                Buffer.BlockCopy(result, 0, identity, 1, 4);
            }
            else
            {
                // Pick up handshake cases and also case where next identity is set

                var msg = new Msg();
                msg.InitEmpty();

                bool ok = pipe.Read(ref msg);

                if (!ok)
                    return false;

                if (msg.Size == 0)
                {
                    // Fall back on the auto-generation
                    identity = new byte[5];

                    byte[] result = BitConverter.GetBytes(m_nextPeerId++);

                    Buffer.BlockCopy(result, 0, identity, 1, 4);

                    msg.Close();
                }
                else
                {
                    identity = msg.CloneData();

                    // Ignore peers with duplicate ID.
                    if (m_outpipes.ContainsKey(identity))
                    {
                        msg.Close();
                        return false;
                    }

                    msg.Close();
                }
            }

            pipe.Identity = identity;
            // Add the record into output pipes lookup table
            var outpipe = new Outpipe(pipe, true);
            m_outpipes.Add(identity, outpipe);

            return true;
        }
Example #7
0
        /// <summary>
        /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending.
        /// </summary>
        /// <param name="msg">the message to transmit</param>
        /// <returns><c>true</c> if the message was sent successfully</returns>
        /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception>
        protected override bool XSend(ref Msg msg)
        {
            // If this is the first part of the message it's the ID of the
            // peer to send the message to.
            if (!m_moreOut)
            {
                Debug.Assert(m_currentOut == null);

                // If we have malformed message (prefix with no subsequent message)
                // then just silently ignore it.
                // TODO: The connections should be killed instead.
                if (msg.HasMore)
                {
                    m_moreOut = true;

                    // Find the pipe associated with the identity stored in the prefix.
                    // If there's no such pipe just silently ignore the message, unless
                    // mandatory is set.

                    var identity = msg.Size == msg.Data.Length 
                        ? msg.Data
                        : msg.CloneData();

                    Outpipe op;

                    if (m_outpipes.TryGetValue(identity, out op))
                    {
                        m_currentOut = op.Pipe;
                        if (!m_currentOut.CheckWrite())
                        {
                            op.Active = false;
                            m_currentOut = null;
                            if (m_mandatory)
                            {
                                m_moreOut = false;
                                return false;
                            }
                        }
                    }
                    else if (m_mandatory)
                    {
                        m_moreOut = false;
                        throw new HostUnreachableException("In Router.XSend");
                    }
                }

                // Detach the message from the data buffer.
                msg.Close();
                msg.InitEmpty();

                return true;
            }

            if (m_options.RawSocket)
            {
                msg.ResetFlags(MsgFlags.More);
            }

            // Check whether this is the last part of the message.
            m_moreOut = msg.HasMore;

            // Push the message into the pipe. If there's no out pipe, just drop it.
            if (m_currentOut != null)
            {
                // Close the remote connection if user has asked to do so
                // by sending zero length message.
                // Pending messages in the pipe will be dropped (on receiving term-ack)
                if (m_rawSocket && msg.Size == 0)
                {
                    m_currentOut.Terminate(false);
                    msg.Close();
                    msg.InitEmpty();
                    m_currentOut = null;
                    return true;
                }

                bool ok = m_currentOut.Write(ref msg);
                if (!ok)
                    m_currentOut = null;
                else if (!m_moreOut)
                {
                    m_currentOut.Flush();
                    m_currentOut = null;
                }
            }
            else
            {
                msg.Close();
            }

            // Detach the message from the data buffer.            
            msg.InitEmpty();

            return true;
        }
Example #8
0
        /// <summary>
        /// Indicate the given pipe as being ready for reading by this socket.
        /// </summary>
        /// <param name="pipe">the <c>Pipe</c> that is now becoming available for reading</param>
        protected override void XReadActivated(Pipe pipe)
        {
            // There are some subscriptions waiting. Let's process them.
            var sub = new Msg();
            while (pipe.Read(ref sub))
            {
                // Apply the subscription to the trie.
                byte[] data = sub.Data;
                int size = sub.Size;
                if (size > 0 && (data[0] == 0 || data[0] == 1))
                {
                    if (m_manual)
                    {
                        m_lastPipe = pipe;

                        m_pending.Enqueue(sub.CloneData());
                    }
                    else
                    {
                        var unique = data[0] == 0
                            ? m_subscriptions.Remove(data, 1, size - 1, pipe)
                            : m_subscriptions.Add(data, 1, size - 1, pipe);

                        // If the subscription is not a duplicate, store it so that it can be
                        // passed to used on next recv call.
                        if (m_options.SocketType == ZmqSocketType.Xpub && (unique || m_verbose))
                            m_pending.Enqueue(sub.CloneData());
                    }
                }
                else // process message unrelated to sub/unsub
                {
                    m_pending.Enqueue(sub.CloneData());
                }

                sub.Close();
            }
        }
Example #9
0
        private bool IdentifyPeer([NotNull] Pipe pipe)
        {
            byte[] identity;

            if (m_options.RawSocket)
            {
                // Always assign identity for raw-socket
                identity = new byte[5];
                byte[] result = BitConverter.GetBytes(m_nextPeerId++);
                Buffer.BlockCopy(result, 0, identity, 1, 4);
            }
            else
            {
                // Pick up handshake cases and also case where next identity is set

                var msg = new Msg();
                msg.InitEmpty();

                bool ok = pipe.Read(ref msg);

                if (!ok)
                    return false;

                if (msg.Size == 0)
                {
                    // Fall back on the auto-generation
                    identity = new byte[5];

                    byte[] result = BitConverter.GetBytes(m_nextPeerId++);

                    Buffer.BlockCopy(result, 0, identity, 1, 4);

                    msg.Close();
                }
                else
                {
                    identity = msg.CloneData();
                    msg.Close();

                    Outpipe existPipe;                 

                    if (m_outpipes.TryGetValue(identity, out existPipe))
                    {                        
                        if (!m_handover)
                        {
                            // Ignore peers with duplicate ID.
                            return false;
                        }
                        else
                        {
                            //  We will allow the new connection to take over this
                            //  identity. Temporarily assign a new identity to the
                            //  existing pipe so we can terminate it asynchronously.
                            var newIdentity = new byte[5];
                            byte[] result = BitConverter.GetBytes(m_nextPeerId++);
                            Buffer.BlockCopy(result, 0, newIdentity, 1, 4);
                            existPipe.Pipe.Identity = newIdentity;                        
                            m_outpipes.Add(newIdentity, existPipe);

                            //  Remove the existing identity entry to allow the new
                            //  connection to take the identity.
                            m_outpipes.Remove(identity);

                            if (existPipe.Pipe == m_currentIn)
                                m_closingCurrentIn = true;
                            else
                                existPipe.Pipe.Terminate(true);
                        }
                    }
                }
            }

            pipe.Identity = identity;
            // Add the record into output pipes lookup table
            var outpipe = new Outpipe(pipe, true);
            m_outpipes.Add(identity, outpipe);

            return true;
        }
Example #10
0
        /// <summary>
        /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending.
        /// </summary>
        /// <param name="msg">the message to transmit</param>
        /// <returns><c>true</c> if the message was sent successfully</returns>
        /// <exception cref="HostUnreachableException">In Stream.XSend</exception>
        protected override bool XSend(ref Msg msg)
        {
            // If this is the first part of the message it's the ID of the
            // peer to send the message to.
            if (!m_moreOut)
            {
                Debug.Assert(m_currentOut == null);

                // If we have malformed message (prefix with no subsequent message)
                // then just silently ignore it.
                // TODO: The connections should be killed instead.
                if (msg.HasMore)
                {
                    // Find the pipe associated with the identity stored in the prefix.
                    // If there's no such pipe just silently ignore the message, unless
                    // mandatory is set.

                    var identity = msg.Size == msg.Data.Length
                        ? msg.Data
                        : msg.CloneData();

                    Outpipe op;
                    if (m_outpipes.TryGetValue(identity, out op))
                    {
                        m_currentOut = op.Pipe;
                        if (!m_currentOut.CheckWrite())
                        {
                            op.Active = false;
                            m_currentOut = null;
                            return false;
                        }
                    }
                    else
                    {
                        throw new HostUnreachableException("In Stream.XSend");
                    }
                }

                m_moreOut = true;

                msg.Close();
                msg.InitEmpty();

                return true;
            }

            // Ignore the MORE flag
            msg.ResetFlags(MsgFlags.More);

            // This is the last part of the message.
            m_moreOut = false;

            // Push the message into the pipe. If there's no out pipe, just drop it.
            if (m_currentOut != null)
            {
                if (msg.Size == 0)
                {
                    m_currentOut.Terminate(false);
                    m_currentOut = null;
                    return true;
                }

                bool ok = m_currentOut.Write(ref msg);
                if (ok)
                {
                    m_currentOut.Flush();
                }

                m_currentOut = null;
            }

            // Detach the message from the data buffer.
            msg.InitEmpty();

            return true;
        }
        /// <summary>
        /// Transmit the given message. The <c>Send</c> method calls this to do the actual sending.
        /// </summary>
        /// <param name="msg">the message to transmit</param>
        /// <returns><c>true</c> if the message was sent successfully</returns>
        /// <exception cref="HostUnreachableException">The receiving host must be identifiable.</exception>
        protected override bool XSend(ref Msg msg)
        {
            // If this is the first part of the message it's the ID of the
            // peer to send the message to.
            if (m_sendingState == State.RoutingId)
            {
                Debug.Assert(m_currentOut == null);

                // If we have malformed message (prefix with no subsequent message)
                // then just silently ignore it.
                if (msg.HasMore)
                {
                    // Find the pipe associated with the routingId stored in the prefix.
                    var routingId = msg.Size == msg.Data.Length
                        ? msg.Data
                        : msg.CloneData();

                    if (m_outpipes.TryGetValue(routingId, out Outpipe op))
                    {
                        m_currentOut = op.Pipe;
                        if (!m_currentOut.CheckWrite())
                        {
                            op.Active    = false;
                            m_currentOut = null;

                            if (!op.Pipe.Active)
                            {
                                throw new HostUnreachableException("In Peer.XSend");
                            }

                            return(false);
                        }
                    }
                    else
                    {
                        throw new HostUnreachableException("In Peer.XSend");
                    }

                    m_sendingState = State.Data;
                }

                // Detach the message from the data buffer.
                msg.Close();
                msg.InitEmpty();

                return(true);
            }

            m_sendingState = State.RoutingId;

            //  Peer sockets do not allow multipart data (ZMQ_SNDMORE)
            if (msg.HasMore)
            {
                throw new InvalidException();
            }

            // Push the message into the pipe. If there's no out pipe, just drop it.
            if (m_currentOut != null)
            {
                bool ok = m_currentOut.Write(ref msg);

                if (ok)
                {
                    m_currentOut.Flush();
                }

                m_currentOut = null;
            }
            else
            {
                msg.Close();
            }

            // Detach the message from the data buffer.
            msg.InitEmpty();

            return(true);
        }