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]); }
// 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); }
protected void NextStep(ByteArraySegment readPos, int toRead, int state) { m_readPos = readPos; m_toRead = toRead; this.State = state; }
// 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; } }
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); }
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); }
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; }
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); }
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); }
// 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; } }
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; }
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; }
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 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(); }
public ByteArraySegment(ByteArraySegment otherSegment, int offset) { m_innerBuffer = otherSegment.m_innerBuffer; Offset = otherSegment.Offset + offset; }
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; }
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(); }