예제 #1
0
파일: V1Decoder.cs 프로젝트: knocte/netmq
        private bool EightByteSizeReady()
        {
            //  The payload size is encoded as 64-bit unsigned integer.
            //  The most significant byte comes first.

            long msg_size = m_tmpbuf.GetLong(0);

            //  Message size must not exceed the maximum allowed size.
            if (m_maxmsgsize >= 0)
                if (msg_size > m_maxmsgsize) {
                    DecodingError ();
                    return false;
                }

            //  Message size must fit within range of size_t data type.
            if (msg_size > int.MaxValue) {
                DecodingError ();
                return false;
            }

            //  in_progress is initialised at this point so in theory we should
            //  close it before calling init_size, however, it's a 0-byte
            //  message and thus we can treat it as uninitialised.
            m_inProgress = new Msg ((int) msg_size);

            m_inProgress.SetFlags (m_msgFlags);
            NextStep (m_inProgress.Data , m_inProgress.Size, MessageReadyState);

            return true;
        }
예제 #2
0
파일: Router.cs 프로젝트: knocte/netmq
        protected override Msg XRecv(SendRecieveOptions flags)
        {
            Msg msg = null;
            if (m_prefetched) {
                if (!m_identitySent) {
                    msg = m_prefetchedId;
                    m_prefetchedId = null;
                    m_identitySent = true;
                }
                else {
                    msg = m_prefetchedMsg;
                    m_prefetchedMsg = null;
                    m_prefetched = false;
                }
                m_moreIn = msg.HasMore;
                return msg;
            }

            Pipe[] pipe = new Pipe[1];
            msg = m_fq.RecvPipe (pipe);

            //  It's possible that we receive peer's identity. That happens
            //  after reconnection. The current implementation assumes that
            //  the peer always uses the same identity.
            //  TODO: handle the situation when the peer changes its identity.
            while (msg != null && msg.IsIdentity )
                msg = m_fq.RecvPipe (pipe);

            if (msg == null)
                return null;

            Debug.Assert(pipe[0] != null);

            //  If we are in the middle of reading a message, just return the next part.
            if (m_moreIn)
                m_moreIn = msg.HasMore;
            else {
                //  We are at the beginning of a message.
                //  Keep the message part we have in the prefetch buffer
                //  and return the ID of the peer instead.
                m_prefetchedMsg = msg;

                m_prefetched = true;

                Blob identity = pipe[0].Identity;
                msg = new Msg(identity.Data);
                msg.SetFlags(MsgFlags.More);
                m_identitySent = true;
            }

            return msg;
        }
예제 #3
0
파일: V1Decoder.cs 프로젝트: knocte/netmq
        private bool OneByteSizeReady()
        {
            //  Message size must not exceed the maximum allowed size.
            if (m_maxmsgsize >= 0)
                if (m_tmpbuf [0] > m_maxmsgsize) {
                    DecodingError ();
                    return false;
                }

            //  in_progress is initialised at this point so in theory we should
            //  close it before calling zmq_msg_init_size, however, it's a 0-byte
            //  message and thus we can treat it as uninitialised...
            m_inProgress = new Msg(m_tmpbuf [0]);

            m_inProgress.SetFlags (m_msgFlags);
            NextStep (m_inProgress.Data , m_inProgress.Size ,MessageReadyState);

            return true;
        }
예제 #4
0
파일: Router.cs 프로젝트: knocte/netmq
        protected override bool XHasIn()
        {
            //  If we are in the middle of reading the messages, there are
            //  definitely more parts available.
            if (m_moreIn)
                return true;

            //  We may already have a message pre-fetched.
            if (m_prefetched)
                return true;

            //  Try to read the next message.
            //  The message, if read, is kept in the pre-fetch buffer.
            Pipe[] pipe = new Pipe[1];
            m_prefetchedMsg = m_fq.RecvPipe (pipe);

            //  It's possible that we receive peer's identity. That happens
            //  after reconnection. The current implementation assumes that
            //  the peer always uses the same identity.
            //  TODO: handle the situation when the peer changes its identity.
            while (m_prefetchedMsg != null && m_prefetchedMsg.IsIdentity )
                m_prefetchedMsg = m_fq.RecvPipe (pipe);

            if (m_prefetchedMsg == null)
                return false;

            Debug.Assert(pipe[0] != null);

            Blob identity = pipe[0].Identity ;
            m_prefetchedId = new Msg(identity.Data);
            m_prefetchedId.SetFlags(MsgFlags.More);

            m_prefetched = true;
            m_identitySent = false;

            return true;
        }
예제 #5
0
파일: SocketBase.cs 프로젝트: knocte/netmq
        public bool Send(Msg msg, SendRecieveOptions flags)
        {
            if (m_ctxTerminated)
            {
                ZError.ErrorNumber = (ErrorNumber.ETERM);
                return false;
            }

            //  Check whether message passed to the function is valid.
            if (msg == null)
            {
                ZError.ErrorNumber = (ErrorNumber.EFAULT);
                throw new ArgumentException();
            }

            //  Process pending commands, if any.
            bool rc = ProcessCommands(0, true);
            if (!rc)
                return false;

            //  Clear any user-visible flags that are set on the message.
            msg.ResetFlags(MsgFlags.More);

            //  At this point we impose the flags on the message.
            if ((flags & SendRecieveOptions.SendMore) > 0)
                msg.SetFlags(MsgFlags.More);

            //  Try to send the message.
            rc = XSend(msg, flags);
            if (rc)
                return true;
            if (!ZError.IsError(ErrorNumber.EAGAIN))
                return false;

            //  In case of non-blocking send we'll simply propagate
            //  the error - including EAGAIN - up the stack.
            if ((flags & SendRecieveOptions.DontWait) > 0 || m_options.SendTimeout == 0)
                return false;

            //  Compute the time when the timeout should occur.
            //  If the timeout is infite, don't care.
            int timeout = m_options.SendTimeout;
            long end = timeout < 0 ? 0 : (Clock.NowMs() + timeout);

            //  Oops, we couldn't send the message. Wait for the next
            //  command, process it and try to send the message again.
            //  If timeout is reached in the meantime, return EAGAIN.
            while (true)
            {
                if (!ProcessCommands(timeout, false))
                    return false;

                rc = XSend(msg, flags);
                if (rc)
                    break;

                if (!ZError.IsError(ErrorNumber.EAGAIN))
                    return false;

                if (timeout > 0)
                {
                    timeout = (int)(end - Clock.NowMs());
                    if (timeout <= 0)
                    {
                        ZError.ErrorNumber = (ErrorNumber.EAGAIN);
                        return false;
                    }
                }
            }
            return true;
        }
예제 #6
0
파일: SocketBase.cs 프로젝트: knocte/netmq
        public bool Connect(String addr)
        {
            if (m_ctxTerminated)
            {
                ZError.ErrorNumber = (ErrorNumber.ETERM);
                return false;
            }

            //  Process pending commands, if any.
            bool brc = ProcessCommands(0, false);
            if (!brc)
                return false;

            //  Parse addr_ string.
            Uri uri;
            try
            {
                uri = new Uri(addr);
            }
            catch (Exception e)
            {
                throw new ArgumentException(addr, e);
            }

            String protocol = uri.Scheme;
            String address = uri.Authority;
            String path = uri.AbsolutePath;
            if (string.IsNullOrEmpty(address))
                address = path;

            CheckProtocol(protocol);

            if (protocol.Equals("inproc"))
            {

                //  TODO: inproc connect is specific with respect to creating pipes
                //  as there's no 'reconnect' functionality implemented. Once that
                //  is in place we should follow generic pipe creation algorithm.

                //  Find the peer endpoint.
                Ctx.Endpoint peer = FindEndpoint(addr);
                if (peer.Socket == null)
                    return false;
                // The total HWM for an inproc connection should be the sum of
                // the binder's HWM and the connector's HWM.
                int sndhwm;
                int rcvhwm;
                if (m_options.SendHighWatermark == 0 || peer.Options.ReceiveHighWatermark == 0)
                    sndhwm = 0;
                else
                    sndhwm = m_options.SendHighWatermark + peer.Options.ReceiveHighWatermark;
                if (m_options.ReceiveHighWatermark == 0 || peer.Options.SendHighWatermark == 0)
                    rcvhwm = 0;
                else
                    rcvhwm = m_options.ReceiveHighWatermark + peer.Options.SendHighWatermark;

                //  Create a bi-directional pipe to connect the peers.
                ZObject[] parents = { this, peer.Socket };
                Pipe[] pipes = { null, null };
                int[] hwms = { sndhwm, rcvhwm };
                bool[] delays = { m_options.DelayOnDisconnect, m_options.DelayOnClose };
                Pipe.Pipepair(parents, pipes, hwms, delays);

                //  Attach local end of the pipe to this socket object.
                AttachPipe(pipes[0]);

                //  If required, send the identity of the peer to the local socket.
                if (peer.Options.RecvIdentity)
                {
                    Msg id = new Msg(peer.Options.IdentitySize);
                    id.Put(peer.Options.Identity, 0, peer.Options.IdentitySize);
                    id.SetFlags(MsgFlags.Identity);
                    bool written = pipes[0].Write(id);
                    Debug.Assert(written);
                    pipes[0].Flush();
                }

                //  If required, send the identity of the local socket to the peer.
                if (m_options.RecvIdentity)
                {
                    Msg id = new Msg(m_options.IdentitySize);
                    id.Put(m_options.Identity, 0, m_options.IdentitySize);
                    id.SetFlags(MsgFlags.Identity);
                    bool written = pipes[1].Write(id);
                    Debug.Assert(written);
                    pipes[1].Flush();
                }

                //  Attach remote end of the pipe to the peer socket. Note that peer's
                //  seqnum was incremented in find_endpoint function. We don't need it
                //  increased here.
                SendBind(peer.Socket, pipes[1], false);

                // Save last endpoint URI
                m_options.LastEndpoint = addr;

                return true;
            }

            //  Choose the I/O thread to run the session in.
            IOThread ioThread = ChooseIOThread(m_options.Affinity);
            if (ioThread == null)
            {
                throw new ArgumentException("Empty IO Thread");
            }
            Address paddr = new Address(protocol, address);

            //  Resolve address (if needed by the protocol)
            if (protocol.Equals("tcp"))
            {
                paddr.Resolved = (new TcpAddress());
                paddr.Resolved.Resolve(
                    address, m_options.IPv4Only);
            }
            else if (protocol.Equals("Ipc"))
            {
                paddr.Resolved = (new IpcAddress());
                paddr.Resolved.Resolve(address, true);
            }
            //  Create session.
            SessionBase session = SessionBase.Create(ioThread, true, this,
                                                                                                m_options, paddr);
            Debug.Assert(session != null);

            //  PGM does not support subscription forwarding; ask for all data to be
            //  sent to this pipe.
            bool icanhasall = false;
            if (protocol.Equals("pgm") || protocol.Equals("epgm"))
                icanhasall = true;

            if (!m_options.DelayAttachOnConnect || icanhasall)
            {
                //  Create a bi-directional pipe.
                ZObject[] parents = { this, session };
                Pipe[] pipes = { null, null };
                int[] hwms = { m_options.SendHighWatermark, m_options.ReceiveHighWatermark };
                bool[] delays = { m_options.DelayOnDisconnect, m_options.DelayOnClose };
                Pipe.Pipepair(parents, pipes, hwms, delays);

                //  Attach local end of the pipe to the socket object.
                AttachPipe(pipes[0], icanhasall);

                //  Attach remote end of the pipe to the session object later on.
                session.AttachPipe(pipes[1]);
            }

            // Save last endpoint URI
            m_options.LastEndpoint = paddr.ToString();

            AddEndpoint(addr, session);
            return true;
        }
예제 #7
0
파일: Req.cs 프로젝트: knocte/netmq
        protected override bool XSend(Msg msg, SendRecieveOptions flags)
        {
            //  If we've sent a request and we still haven't got the reply,
            //  we can't send another request.
            if (m_receivingReply) {
                throw new InvalidOperationException("Cannot send another request");
            }

            bool rc;

            //  First part of the request is the request identity.
            if (m_messageBegins) {
                Msg bottom = new Msg();
                bottom.SetFlags (MsgFlags.More);
                rc = base.XSend (bottom, 0);
                if (!rc)
                    return false;
                m_messageBegins = false;
            }

            bool more = msg.HasMore;

            rc = base.XSend (msg, flags);
            if (!rc)
                return rc;

            //  If the request was fully sent, flip the FSM into reply-receiving state.
            if (!more) {
                m_receivingReply = true;
                m_messageBegins = true;
            }

            return true;
        }
예제 #8
0
파일: SessionBase.cs 프로젝트: knocte/netmq
        public virtual bool PushMsg(Msg msg)
        {
            //  First message to receive is identity (if required).
            if (!m_identityReceived) {
                msg.SetFlags (MsgFlags.Identity);
                m_identityReceived = true;

                if (!m_options.RecvIdentity) {
                    return true;
                }
            }

            if (m_pipe != null && m_pipe.Write (msg)) {
                return true;
            }

            ZError.ErrorNumber = (ErrorNumber.EAGAIN);
            return false;
        }