Beispiel #1
0
        public Decoder(int bufsize, long maxmsgsize)
            : base(bufsize)
        {
            m_maxmsgsize = maxmsgsize;
            m_tmpbuf = new ByteArraySegment(new byte[8]);

            //  At the beginning, read one byte and go to one_byte_size_ready state.
            NextStep (m_tmpbuf, 1, OneByteSizeReadyState);
        }
 public PgmSender(IOThread ioThread, Options options, Address addr)
     : base(ioThread)
 {
     m_options = options;
     m_addr = addr;
     m_encoder = null;
     m_outBuffer = null;
     m_outBufferSize = 0;
     m_writeSize = 0;
     m_encoder = new Encoder(0, m_options.Endian);
 }
        public void Init(PgmAddress pgmAddress)
        {
            m_pgmSocket = new PgmSocket(m_options, PgmSocketType.Publisher, m_addr.Resolved as PgmAddress);
            m_pgmSocket.Init();

            m_socket = m_pgmSocket.FD;

            IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 0);

            m_socket.Bind(localEndpoint);

            m_pgmSocket.InitOptions();

            m_socket.Connect(pgmAddress.Address);
            m_socket.Blocking = false;

            m_outBufferSize = Config.PgmMaxTPDU;
            m_outBuffer = new ByteArraySegment(new byte[m_outBufferSize]);
        }
Beispiel #4
0
        //  Returns a buffer to be filled with binary data.
        public void GetBuffer(ref ByteArraySegment data, ref int size)
        {
            //  If we are expected to read large message, we'll opt for zero-
            //  copy, i.e. we'll ask caller to fill the data directly to the
            //  message. Note that subsequent read(s) are non-blocking, thus
            //  each single read reads at most SO_RCVBUF bytes at once not
            //  depending on how large is the chunk returned from here.
            //  As a consequence, large messages being received won't block
            //  other engines running in the same I/O thread for excessive
            //  amounts of time.

            if (m_toRead >= m_bufsize)
            {
                data = m_readPos;
                size = m_toRead;
                return;
            }

            data = new ByteArraySegment(m_buf);
            size = m_bufsize;
        }
        public void IntLittleEndian()
        {
            ByteArraySegment byteArraySegment = new ByteArraySegment(new byte[4]);

            byteArraySegment.PutInteger(Endianness.Little, 1, 0);

            Assert.AreEqual(1, byteArraySegment[0]);
            Assert.AreEqual(0, byteArraySegment[3]);

            long num = byteArraySegment.GetInteger(Endianness.Little, 0);

            Assert.AreEqual(1, num);

            byteArraySegment.PutInteger(Endianness.Little, 16777216, 0);

            Assert.AreEqual(1, byteArraySegment[3]);
            Assert.AreEqual(0, byteArraySegment[0]);

            num = byteArraySegment.GetInteger(Endianness.Little, 0);

            Assert.AreEqual(16777216, num);
        }
        public void LongLittleEndian()
        {
            ByteArraySegment byteArraySegment = new ByteArraySegment(new byte[8]);

            byteArraySegment.PutLong(Endianness.Little, 1, 0);

            Assert.AreEqual(byteArraySegment[0], 1);
            Assert.AreEqual(0, byteArraySegment[7]);

            long num = byteArraySegment.GetLong(Endianness.Little, 0);

            Assert.AreEqual(1, num);

            byteArraySegment.PutLong(Endianness.Little, 72057594037927936, 0);

            Assert.AreEqual(1, byteArraySegment[7]);
            Assert.AreEqual(0, byteArraySegment[0]);

            num = byteArraySegment.GetLong(Endianness.Little, 0);

            Assert.AreEqual(72057594037927936, num);
        }
Beispiel #7
0
 protected void NextStep(ByteArraySegment readPos, int toRead, int state)
 {
     m_readPos  = readPos;
     m_toRead   = toRead;
     this.State = state;
 }
Beispiel #8
0
        //  Processes the data in the buffer previously allocated using
        //  get_buffer function. size_ argument specifies nemuber of bytes
        //  actually filled into the buffer. Function returns number of
        //  bytes actually processed.
        public int ProcessBuffer(ByteArraySegment data, int size)
        {
            //  Check if we had an error in previous attempt.
            if (State < 0)
            {
                return(-1);
            }

            //  In case of zero-copy simply adjust the pointers, no copying
            //  is required. Also, run the state machine in case all the data
            //  were processed.
            if (data != null && data.Equals(m_readPos))
            {
                m_readPos.AdvanceOffset(size);
                m_toRead -= size;

                while (m_toRead == 0)
                {
                    if (!Next())
                    {
                        if (State < 0)
                        {
                            return(-1);
                        }
                        return(size);
                    }
                }
                return(size);
            }

            int pos = 0;

            while (true)
            {
                //  Try to get more space in the message to fill in.
                //  If none is available, return.
                while (m_toRead == 0)
                {
                    if (!Next())
                    {
                        if (State < 0)
                        {
                            return(-1);
                        }

                        return(pos);
                    }
                }

                //  If there are no more data in the buffer, return.
                if (pos == size)
                {
                    return(pos);
                }

                //  Copy the data from buffer to the message.
                int toCopy = Math.Min(m_toRead, size - pos);
                data.CopyTo(pos, m_readPos, 0, toCopy);
                m_readPos.AdvanceOffset(toCopy);
                pos      += toCopy;
                m_toRead -= toCopy;
            }
        }
Beispiel #9
0
        private bool Handshake()
        {
            Debug.Assert(m_handshaking);

            //  Receive the greeting.
            while (m_greetingBytesRead < GreetingSize)
            {
                ByteArraySegment greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead);

                int n = Read(greetingSegment, GreetingSize - m_greetingBytesRead);
                if (n == -1)
                {
                    Error();
                    return(false);
                }

                if (n == 0)
                {
                    return(false);
                }

                m_greetingBytesRead += n;

                //  We have received at least one byte from the peer.
                //  If the first byte is not 0xff, we know that the
                //  peer is using unversioned protocol.
                if (m_greeting[0] != 0xff)
                {
                    break;
                }

                if (m_greetingBytesRead < 10)
                {
                    continue;
                }

                //  Inspect the right-most bit of the 10th byte (which coincides
                //  with the 'flags' field if a regular message was sent).
                //  Zero indicates this is a header of identity message
                //  (i.e. the peer is using the unversioned protocol).
                if ((m_greeting[9] & 0x01) == 0)
                {
                    break;
                }

                //  The peer is using versioned protocol.
                //  Send the rest of the greeting, if necessary.
                if (!(((byte[])m_outpos) == ((byte[])m_greetingOutputBuffer) &&
                      m_outpos.Offset + m_outsize == GreetingSize))
                {
                    if (m_outsize == 0)
                    {
                        m_ioObject.SetPollout(m_handle);
                    }

                    m_outpos[m_outsize++] = 1;                     // Protocol version
                    m_outpos[m_outsize++] = (byte)m_options.SocketType;
                }
            }

            //  Is the peer using the unversioned protocol?
            //  If so, we send and receive rests of identity
            //  messages.
            if (m_greeting[0] != 0xff || (m_greeting[9] & 0x01) == 0)
            {
                m_encoder = new Encoder(Config.OutBatchSize, m_options.Endian);
                m_encoder.SetMsgSource(m_session);

                m_decoder = new Decoder(Config.InBatchSize, m_options.Maxmsgsize, m_options.Endian);

                m_decoder.SetMsgSink(m_session);

                //  We have already sent the message header.
                //  Since there is no way to tell the encoder to
                //  skip the message header, we simply throw that
                //  header data away.
                int              headerSize = m_options.IdentitySize + 1 >= 255 ? 10 : 2;
                byte[]           tmp        = new byte[10];
                ByteArraySegment bufferp    = new ByteArraySegment(tmp);

                int bufferSize = headerSize;

                m_encoder.GetData(ref bufferp, ref bufferSize);

                Debug.Assert(bufferSize == headerSize);

                //  Make sure the decoder sees the data we have already received.
                m_inpos  = new ByteArraySegment(m_greeting);
                m_insize = m_greetingBytesRead;

                //  To allow for interoperability with peers that do not forward
                //  their subscriptions, we inject a phony subsription
                //  message into the incomming message stream. To put this
                //  message right after the identity message, we temporarily
                //  divert the message stream from session to ourselves.
                if (m_options.SocketType == ZmqSocketType.Pub || m_options.SocketType == ZmqSocketType.Xpub)
                {
                    m_decoder.SetMsgSink(this);
                }
            }
            else if (m_greeting[VersionPos] == 0)
            {
                //  ZMTP/1.0 framing.
                m_encoder = new Encoder(Config.OutBatchSize, m_options.Endian);
                m_encoder.SetMsgSource(m_session);

                m_decoder = new Decoder(Config.InBatchSize, m_options.Maxmsgsize, m_options.Endian);
                m_decoder.SetMsgSink(m_session);
            }
            else
            {
                //  v1 framing protocol.
                m_encoder = new V1Encoder(Config.OutBatchSize, m_session, m_options.Endian);

                m_decoder = new V1Decoder(Config.InBatchSize, m_options.Maxmsgsize, m_session, m_options.Endian);
            }
            // Start polling for output if necessary.
            if (m_outsize == 0)
            {
                m_ioObject.SetPollout(m_handle);
            }

            //  Handshaking was successful.
            //  Switch into the normal message flow.
            m_handshaking = false;

            return(true);
        }
Beispiel #10
0
 public void CopyTo(ByteArraySegment otherSegment, int toCopy)
 {
     CopyTo(0, otherSegment, 0, toCopy);
 }
        public void UnsignedShortLittleEndian()
        {
            ByteArraySegment byteArraySegment = new ByteArraySegment(new byte[2]);

            byteArraySegment.PutUnsingedShort(Endianness.Little, 1, 0);

            Assert.AreEqual(1, byteArraySegment[0]);
            Assert.AreEqual(0, byteArraySegment[1]);

            long num = byteArraySegment.GetUnsignedShort(Endianness.Little, 0);

            Assert.AreEqual(1, num);

            byteArraySegment.PutUnsingedShort(Endianness.Little, 256, 0);

            Assert.AreEqual(1, byteArraySegment[1]);
            Assert.AreEqual(0, byteArraySegment[0]);

            num = byteArraySegment.GetUnsignedShort(Endianness.Little, 0);

            Assert.AreEqual(256, num);
        }
Beispiel #12
0
        private bool Handshake()
        {
            Debug.Assert(m_handshaking);

            //  Receive the greeting.
            while (m_greetingBytesRead < GreetingSize)
            {
                ByteArraySegment greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead);

                int n = Read(greetingSegment, GreetingSize - m_greetingBytesRead);
                if (n == -1)
                {
                    Error();
                    return false;
                }

                if (n == 0)
                    return false;

                m_greetingBytesRead += n;

                //  We have received at least one byte from the peer.
                //  If the first byte is not 0xff, we know that the
                //  peer is using unversioned protocol.
                if (m_greeting[0] != 0xff)
                    break;

                if (m_greetingBytesRead < 10)
                    continue;

                //  Inspect the right-most bit of the 10th byte (which coincides
                //  with the 'flags' field if a regular message was sent).
                //  Zero indicates this is a header of identity message
                //  (i.e. the peer is using the unversioned protocol).
                if ((m_greeting[9] & 0x01) == 0)
                    break;

                //  The peer is using versioned protocol.
                //  Send the rest of the greeting, if necessary.
                if (!(((byte[]) m_outpos) == ((byte[]) m_greetingOutputBuffer) &&
                      m_outpos.Offset + m_outsize == GreetingSize))
                {
                    if (m_outsize == 0)
                        m_ioObject.SetPollout(m_handle);

                    m_outpos[m_outsize++] = 1; // Protocol version
                    m_outpos[m_outsize++] = (byte) m_options.SocketType;
                }
            }

            //  Is the peer using the unversioned protocol?
            //  If so, we send and receive rests of identity
            //  messages.
            if (m_greeting[0] != 0xff || (m_greeting[9] & 0x01) == 0)
            {
                m_encoder = new Encoder(Config.OutBatchSize);
                m_encoder.SetMsgSource(m_session);

                m_decoder = new Decoder(Config.InBatchSize, m_options.Maxmsgsize);

                m_decoder.SetMsgSink(m_session);

                //  We have already sent the message header.
                //  Since there is no way to tell the encoder to
                //  skip the message header, we simply throw that
                //  header data away.
                int headerSize = m_options.IdentitySize + 1 >= 255 ? 10 : 2;
                byte[] tmp = new byte[10];
                ByteArraySegment bufferp = new ByteArraySegment(tmp);

                int bufferSize = headerSize;

                m_encoder.GetData(ref bufferp, ref bufferSize);

                Debug.Assert(bufferSize == headerSize);

                //  Make sure the decoder sees the data we have already received.
                m_inpos = new ByteArraySegment(m_greeting);
                m_insize = m_greetingBytesRead;

                //  To allow for interoperability with peers that do not forward
                //  their subscriptions, we inject a phony subsription
                //  message into the incomming message stream. To put this
                //  message right after the identity message, we temporarily
                //  divert the message stream from session to ourselves.
                if (m_options.SocketType == ZmqSocketType.Pub || m_options.SocketType == ZmqSocketType.Xpub)
                    m_decoder.SetMsgSink(this);
            }
            else if (m_greeting[VersionPos] == 0)
            {
                //  ZMTP/1.0 framing.
                m_encoder = new Encoder(Config.OutBatchSize);
                m_encoder.SetMsgSource(m_session);

                m_decoder = new Decoder(Config.InBatchSize, m_options.Maxmsgsize);
                m_decoder.SetMsgSink(m_session);
            }
            else
            {
                //  v1 framing protocol.
                m_encoder = new V1Encoder(Config.OutBatchSize, m_session);

                m_decoder = new V1Decoder(Config.InBatchSize, m_options.Maxmsgsize, m_session);
            }
            // Start polling for output if necessary.
            if (m_outsize == 0)
                m_ioObject.SetPollout(m_handle);

            //  Handshaking was successful.
            //  Switch into the normal message flow.
            m_handshaking = false;

            return true;
        }
Beispiel #13
0
        public void OutEvent()
        {
            //  If write buffer is empty, try to read new data from the encoder.
            if (m_outsize == 0)
            {
                m_outpos = null;
                m_encoder.GetData(ref m_outpos, ref m_outsize);

                //  If there is no data to send, stop polling for output.
                if (m_outsize == 0)
                {
                    m_ioObject.ResetPollout(m_handle);

                    return;
                }
            }

            //  If there are any data to write in write buffer, write as much as
            //  possible to the socket. Note that amount of data to write can be
            //  arbitratily large. However, we assume that underlying TCP layer has
            //  limited transmission buffer and thus the actual number of bytes
            //  written should be reasonably modest.
            int nbytes = Write(m_outpos, m_outsize);

            //  IO error has occurred. We stop waiting for output events.
            //  The engine is not terminated until we detect input error;
            //  this is necessary to prevent losing incomming messages.
            if (nbytes == -1)
            {
                m_ioObject.ResetPollout(m_handle);
                return;
            }

            m_outpos.AdvanceOffset(nbytes);
            m_outsize -= nbytes;

            //  If we are still handshaking and there are no data
            //  to send, stop polling for output.
            if (m_handshaking)
                if (m_outsize == 0)
                    m_ioObject.ResetPollout(m_handle);
        }
Beispiel #14
0
        public void InEvent()
        {
            if (m_pendingBytes > 0)
                return;

            //  Get new batch of data.
            //  Note the workaround made not to break strict-aliasing rules.
            data.Reset();

            int received = 0;

            try
            {
                received = m_handle.Receive((byte[])data);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    return;
                    //break;
                }
                else
                {
                    m_joined = false;
                    Error();
                    return;
                }
            }

            //  No data to process. This may happen if the packet received is
            //  neither ODATA nor ODATA.
            if (received == 0)
            {
                return;
            }

            //  Read the offset of the fist message in the current packet.
            Debug.Assert(received >= sizeof(ushort));
            ushort offset = data.GetUnsignedShort(m_options.Endian, 0);
            data.AdvanceOffset(sizeof(ushort));
            received -= sizeof(ushort);

            //  Join the stream if needed.
            if (!m_joined)
            {
                //  There is no beginning of the message in current packet.
                //  Ignore the data.
                if (offset == 0xffff)
                    return;

                Debug.Assert(offset <= received);
                Debug.Assert(m_decoder == null);

                //  We have to move data to the begining of the first message.
                data.AdvanceOffset(offset);
                received -= offset;

                //  Mark the stream as joined.
                m_joined = true;

                //  Create and connect decoder for the peer.
                m_decoder = new Decoder(0, m_options.Maxmsgsize, m_options.Endian);
                m_decoder.SetMsgSink(m_session);
            }

            //  Push all the data to the decoder.
            int processed = m_decoder.ProcessBuffer(data, received);
            if (processed < received)
            {
                //  Save some state so we can resume the decoding process later.
                m_pendingBytes = received - processed;
                m_pendingData = new ByteArraySegment(data, processed);

                //  Stop polling.
                m_ioObject.ResetPollin(m_handle);

                return;
            }

            m_session.Flush();
        }
        //  The function returns a batch of binary data. The data
        //  are filled to a supplied buffer. If no buffer is supplied (data_
        //  points to NULL) decoder object will provide buffer of its own.


        public void GetData(ref ByteArraySegment data, ref int size)
        {
            int offset = -1;

            GetData(ref data, ref size, ref offset);
        }
Beispiel #16
0
        //  Processes the data in the buffer previously allocated using
        //  get_buffer function. size_ argument specifies nemuber of bytes
        //  actually filled into the buffer. Function returns number of
        //  bytes actually processed.
        public int ProcessBuffer(ByteArraySegment data, int size)
        {
            //  Check if we had an error in previous attempt.
            if (State < 0)
            {
                return -1;
            }

            //  In case of zero-copy simply adjust the pointers, no copying
            //  is required. Also, run the state machine in case all the data
            //  were processed.
            if (data.Equals(m_readPos))
            {
                m_readPos.AdvanceOffset(size);
                m_toRead -= size;

                while (m_toRead == 0)
                {
                    if (!Next())
                    {
                        if (State < 0)
                        {
                            return -1;
                        }
                        return size;
                    }
                }
                return size;
            }

            int pos = 0;
            while (true)
            {

                //  Try to get more space in the message to fill in.
                //  If none is available, return.
                while (m_toRead == 0)
                {
                    if (!Next())
                    {
                        if (State < 0)
                        {
                            return -1;
                        }

                        return pos;
                    }
                }

                //  If there are no more data in the buffer, return.
                if (pos == size)
                    return pos;

                //  Copy the data from buffer to the message.
                int toCopy = Math.Min(m_toRead, size - pos);
                data.CopyTo(pos, m_readPos, 0, toCopy);
                m_readPos.AdvanceOffset(toCopy);
                pos += toCopy;
                m_toRead -= toCopy;
            }
        }
Beispiel #17
0
        public override void OutEvent()
        {
            //  POLLOUT event from send socket. If write buffer is empty,
            //  try to read new data from the encoder.
            if (m_writeSize == 0)
            {

                //  First two bytes (sizeof uint16_t) are used to store message
                //  offset in following steps. Note that by passing our buffer to
                //  the get data function we prevent it from returning its own buffer.
                ByteArraySegment bf = new ByteArraySegment(m_outBuffer, sizeof(ushort));
                int bfsz = m_outBufferSize - sizeof(ushort);
                int offset = -1;
                m_encoder.GetData(ref bf, ref bfsz, ref offset);

                //  If there are no data to write stop polling for output.
                if (bfsz == 0)
                {
                    ResetPollout(m_socket);
                    return;
                }

                //  Put offset information in the buffer.
                m_writeSize = bfsz + sizeof(ushort);

                m_outBuffer.PutUnsingedShort(m_options.Endian, offset == -1 ? (ushort)0xffff : (ushort)offset, 0);
            }

            //  Send the data.
            int nbytes = m_socket.Send((byte[])m_outBuffer, m_outBuffer.Offset, m_writeSize, SocketFlags.None);

            //  We can write either all data or 0 which means rate limit reached.
            if (nbytes == m_writeSize)
            {
                m_writeSize = 0;
            }
            else
            {
                Debug.Assert(false);

                throw NetMQException.Create(ErrorCode.ESOCKET);
            }
        }
        public void GetData(ref ByteArraySegment data, ref int size, ref int offset)
        {
            ByteArraySegment buffer = data ?? new ByteArraySegment(m_buf);
            int bufferSize = data == null ? m_buffersize : size;

            int pos = 0;

            while (pos < bufferSize)
            {
                //  If there are no more data to return, run the state machine.
                //  If there are still no data, return what we already have
                //  in the buffer.
                if (m_toWrite == 0)
                {
                    //  If we are to encode the beginning of a new message,
                    //  adjust the message offset.

                    if (m_beginning)
                    {
                        if (offset == -1)
                        {
                            offset = pos;
                        }
                    }

                    if (!Next())
                        break;
                }

                //  If there are no data in the buffer yet and we are able to
                //  fill whole buffer in a single go, let's use zero-copy.
                //  There's no disadvantage to it as we cannot stuck multiple
                //  messages into the buffer anyway. Note that subsequent
                //  write(s) are non-blocking, thus each single write writes
                //  at most SO_SNDBUF bytes at once not depending on how large
                //  is the chunk returned from here.
                //  As a consequence, large messages being sent won't block
                //  other engines running in the same I/O thread for excessive
                //  amounts of time.
                if (pos == 0 && data == null && m_toWrite >= bufferSize)
                {
                    data = m_writePos;
                    size = m_toWrite;

                    m_writePos = null;
                    m_toWrite = 0;
                    return;
                }

                //  Copy data to the buffer. If the buffer is full, return.
                int toCopy = Math.Min(m_toWrite, bufferSize - pos);

                if (toCopy != 0)
                {
                    m_writePos.CopyTo(0,buffer, pos, toCopy);
                    pos += toCopy;
                    m_writePos.AdvanceOffset(toCopy);
                    m_toWrite -= toCopy;
                }
            }

            data = buffer;
            size = pos;
        }
        //  The function returns a batch of binary data. The data
        //  are filled to a supplied buffer. If no buffer is supplied (data_
        //  points to NULL) decoder object will provide buffer of its own.
        public void GetData(ref ByteArraySegment data, ref int size)
        {
            int offset = -1;

            GetData(ref data, ref size, ref offset);
        }
        //protected void next_step (Msg msg_, int state_, bool beginning_) {
        //    if (msg_ == null)
        //        next_step((ByteBuffer) null, 0, state_, beginning_);
        //    else
        //        next_step(msg_.data(), msg_.size(), state_, beginning_);
        //}
        protected void NextStep(ByteArraySegment writePos, int toWrite,
		                         int state, bool beginning)
        {
            m_writePos = writePos;
            m_toWrite = toWrite;
            State = state;
            m_beginning = beginning;
        }
Beispiel #21
0
 protected void NextStep(ByteArraySegment readPos, int toRead, int state)
 {
     m_readPos = readPos;
     m_toRead = toRead;
     this.State = state;
 }
 public void CopyTo(ByteArraySegment otherSegment, int toCopy)
 {
     CopyTo(0, otherSegment, 0, toCopy);
 }
        public void GetData(ref ByteArraySegment data, ref int size, ref int offset)
        {
            ByteArraySegment buffer = data ?? new ByteArraySegment(m_buf);
            int bufferSize          = data == null ? m_buffersize : size;

            int pos = 0;

            while (pos < bufferSize)
            {
                //  If there are no more data to return, run the state machine.
                //  If there are still no data, return what we already have
                //  in the buffer.
                if (m_toWrite == 0)
                {
                    //  If we are to encode the beginning of a new message,
                    //  adjust the message offset.

                    if (m_beginning)
                    {
                        if (offset == -1)
                        {
                            offset = pos;
                        }
                    }

                    if (!Next())
                    {
                        break;
                    }
                }

                //  If there are no data in the buffer yet and we are able to
                //  fill whole buffer in a single go, let's use zero-copy.
                //  There's no disadvantage to it as we cannot stuck multiple
                //  messages into the buffer anyway. Note that subsequent
                //  write(s) are non-blocking, thus each single write writes
                //  at most SO_SNDBUF bytes at once not depending on how large
                //  is the chunk returned from here.
                //  As a consequence, large messages being sent won't block
                //  other engines running in the same I/O thread for excessive
                //  amounts of time.
                if (pos == 0 && data == null && m_toWrite >= bufferSize)
                {
                    data = m_writePos;
                    size = m_toWrite;

                    m_writePos = null;
                    m_toWrite  = 0;
                    return;
                }

                //  Copy data to the buffer. If the buffer is full, return.
                int toCopy = Math.Min(m_toWrite, bufferSize - pos);

                if (toCopy != 0)
                {
                    m_writePos.CopyTo(0, buffer, pos, toCopy);
                    pos += toCopy;
                    m_writePos.AdvanceOffset(toCopy);
                    m_toWrite -= toCopy;
                }
            }

            data = buffer;
            size = pos;
        }
 public void CopyTo(int fromOffset, ByteArraySegment dest, int destOffset, int toCopy)
 {
     Buffer.BlockCopy(m_innerBuffer, Offset + fromOffset, dest.m_innerBuffer, dest.Offset + destOffset, toCopy);
 }
 public ByteArraySegment(ByteArraySegment otherSegment, int offset)
 {
     m_innerBuffer = otherSegment.m_innerBuffer;
     Offset        = otherSegment.Offset + offset;
 }
Beispiel #26
0
 public void CopyTo(int fromOffset, ByteArraySegment dest, int destOffset, int toCopy)
 {
     Buffer.BlockCopy(m_innerBuffer, Offset + fromOffset, dest.m_innerBuffer, dest.Offset + destOffset, toCopy);
 }
Beispiel #27
0
        public void Plug(IOThread ioThread,
		                 SessionBase session)
        {
            Debug.Assert(!m_plugged);
            m_plugged = true;

            //  Connect to session object.
            Debug.Assert(m_session == null);
            Debug.Assert(session != null);
            m_session = session;
            m_socket = m_session.Socket;

            m_ioObject = new IOObject(null);
            m_ioObject.SetHandler(this);
            //  Connect to I/O threads poller object.
            m_ioObject.Plug(ioThread);
            m_ioObject.AddFd(m_handle);

            //  Send the 'length' and 'flags' fields of the identity message.
            //  The 'length' field is encoded in the long format.

            m_greetingOutputBuffer[m_outsize++] = ((byte) 0xff);
            m_greetingOutputBuffer.PutLong((long) m_options.IdentitySize + 1, 1);
            m_outsize += 8;
            m_greetingOutputBuffer[m_outsize++] = ((byte) 0x7f);

            m_outpos = new ByteArraySegment(m_greetingOutputBuffer);

            m_ioObject.SetPollin(m_handle);
            m_ioObject.SetPollout(m_handle);

            //  Flush all the data that may have been already received downstream.
            InEvent();
        }
Beispiel #28
0
 public ByteArraySegment(ByteArraySegment otherSegment, int offset)
 {
     m_innerBuffer = otherSegment.m_innerBuffer;
     Offset = otherSegment.Offset + offset;
 }
Beispiel #29
0
        private int Write(ByteArraySegment data, int size)
        {
            int nbytes = 0;
            try
            {
                nbytes = m_handle.Send((byte[]) data, data.Offset, size, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                //  If not a single byte can be written to the socket in non-blocking mode
                //  we'll get an error (this may happen during the speculative write).
                if (ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    return 0;
                }
                else if ((
                         	ex.SocketErrorCode == SocketError.NetworkDown ||
                         	ex.SocketErrorCode == SocketError.NetworkReset ||
                         	ex.SocketErrorCode == SocketError.HostUnreachable ||
                         	ex.SocketErrorCode == SocketError.ConnectionAborted ||
                         	ex.SocketErrorCode == SocketError.TimedOut ||
                         	ex.SocketErrorCode == SocketError.ConnectionReset))
                {
                    return -1;
                }
                else
                {
                    Debug.Assert(false);
                }
            }

            return nbytes;
        }
Beispiel #30
0
        public void InEvent()
        {
            if (m_pendingBytes > 0)
            {
                return;
            }

            //  Get new batch of data.
            //  Note the workaround made not to break strict-aliasing rules.
            data.Reset();

            int received = 0;

            try
            {
                received = m_handle.Receive((byte[])data);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.WouldBlock)
                {
                    return;
                    //break;
                }
                else
                {
                    m_joined = false;
                    Error();
                    return;
                }
            }

            //  No data to process. This may happen if the packet received is
            //  neither ODATA nor ODATA.
            if (received == 0)
            {
                return;
            }

            //  Read the offset of the fist message in the current packet.
            Debug.Assert(received >= sizeof(ushort));
            ushort offset = data.GetUnsignedShort(m_options.Endian, 0);

            data.AdvanceOffset(sizeof(ushort));
            received -= sizeof(ushort);

            //  Join the stream if needed.
            if (!m_joined)
            {
                //  There is no beginning of the message in current packet.
                //  Ignore the data.
                if (offset == 0xffff)
                {
                    return;
                }

                Debug.Assert(offset <= received);
                Debug.Assert(m_decoder == null);

                //  We have to move data to the begining of the first message.
                data.AdvanceOffset(offset);
                received -= offset;

                //  Mark the stream as joined.
                m_joined = true;

                //  Create and connect decoder for the peer.
                m_decoder = new Decoder(0, m_options.Maxmsgsize, m_options.Endian);
                m_decoder.SetMsgSink(m_session);
            }

            //  Push all the data to the decoder.
            int processed = m_decoder.ProcessBuffer(data, received);

            if (processed < received)
            {
                //  Save some state so we can resume the decoding process later.
                m_pendingBytes = received - processed;
                m_pendingData  = new ByteArraySegment(data, processed);

                //  Stop polling.
                m_ioObject.ResetPollin(m_handle);

                return;
            }

            m_session.Flush();
        }