public ByteArraySegment(ByteArraySegment otherSegment, int offset) { m_innerBuffer = otherSegment.m_innerBuffer; Offset = otherSegment.Offset + offset; }
public void CopyTo(ByteArraySegment otherSegment, int toCopy) { CopyTo(0, otherSegment, 0, toCopy); }
public void CopyTo(int fromOffset, ByteArraySegment dest, int destOffset, int toCopy) { Buffer.BlockCopy(m_innerBuffer, Offset + fromOffset, dest.m_innerBuffer, dest.Offset + destOffset, toCopy); }
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; }
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 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 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); }