@Override public void activate_out() { io_object.set_pollout(handle); // Speculative write: The assumption is that at the moment new message // was sent by the user the socket is probably available for writing. // Thus we try to write the data to socket avoiding polling for POLLOUT. // Consequently, the latency should be better in request/reply scenarios. out_event(); }
public void plug(IOThread io_thread_, SessionBase session_) { assert (!plugged); plugged = true; // Connect to session object. assert (session == null); assert (session_ != null); session = session_; socket = session.get_soket(); io_object = new IOObject(null); io_object.set_handler(this); // Connect to I/O threads poller object. io_object.plug(io_thread_); io_object.add_fd(handle); io_enabled = true; // Send the 'length' and 'flags' fields of the identity message. // The 'length' field is encoded in the long format. greeting_output_buffer.put((byte) 0xff); greeting_output_buffer.putLong(options.identity_size + 1); greeting_output_buffer.put((byte) 0x7f); io_object.set_pollin(handle); // When there's a raw custom encoder, we don't send 10 bytes frame boolean custom = false; try { custom = options.encoder != null && options.encoder.getDeclaredField("RAW_ENCODER") != null; } catch (SecurityException e) { } catch (NoSuchFieldException e) { } if (!custom) { outsize = greeting_output_buffer.position(); outbuf = new Transfer.ByteBufferTransfer((ByteBuffer) greeting_output_buffer.flip()); io_object.set_pollout(handle); } // Flush all the data that may have been already received downstream. in_event(); }
private boolean handshake() { assert (handshaking); // Receive the greeting. while (greeting.position() < GREETING_SIZE) { final int n = read(greeting); if (n == -1) { error(); return false; } if (n == 0) return false; // 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 (greeting.array()[0] != -1) break; if (greeting.position() < 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 ((greeting.array()[9] & 0x01) == 0) break; // The peer is using versioned protocol. // Send the rest of the greeting, if necessary. if (greeting_output_buffer.limit() < GREETING_SIZE) { if (outsize == 0) io_object.set_pollout(handle); int pos = greeting_output_buffer.position(); greeting_output_buffer.position(10).limit(GREETING_SIZE); greeting_output_buffer.put((byte) 1); // Protocol version greeting_output_buffer.put((byte) options.type); // Socket type greeting_output_buffer.position(pos); outsize += 2; } } // Position of the version field in the greeting. final int version_pos = 10; // Is the peer using the unversioned protocol? // If so, we send and receive rests of identity // messages. if (greeting.array()[0] != -1 || (greeting.array()[9] & 0x01) == 0) { encoder = new_encoder(Config.out_batch_size.getValue(), null, 0); encoder.set_msg_source(session); decoder = new_decoder(Config.in_batch_size.getValue(), options.maxmsgsize, null, 0); decoder.set_msg_sink(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. final int header_size = options.identity_size + 1 >= 255 ? 10 : 2; ByteBuffer tmp = ByteBuffer.allocate(header_size); encoder.get_data(tmp); assert (tmp.remaining() == header_size); // Make sure the decoder sees the data we have already received. inbuf = greeting; greeting.flip(); insize = greeting.remaining(); // 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 (options.type == ZMQ.ZMQ_PUB || options.type == ZMQ.ZMQ_XPUB) decoder.set_msg_sink(this); } else if (greeting.array()[version_pos] == 0) { // ZMTP/1.0 framing. encoder = new_encoder(Config.out_batch_size.getValue(), null, 0); encoder.set_msg_source(session); decoder = new_decoder(Config.in_batch_size.getValue(), options.maxmsgsize, null, 0); decoder.set_msg_sink(session); } else { // v1 framing protocol. encoder = new_encoder(Config.out_batch_size.getValue(), session, V1Protocol.VERSION); decoder = new_decoder( Config.in_batch_size.getValue(), options.maxmsgsize, session, V1Protocol.VERSION); } // Start polling for output if necessary. if (outsize == 0) io_object.set_pollout(handle); // Handshaking was successful. // Switch into the normal message flow. handshaking = false; return true; }