Ejemplo n.º 1
0
  @Override
  public void in_event() {

    //  If still handshaking, receive and process the greeting message.
    if (handshaking) if (!handshake()) return;

    assert (decoder != null);
    boolean disconnection = false;

    //  If there's no data to process in the buffer...
    if (insize == 0) {

      //  Retrieve the buffer and read as much data as possible.
      //  Note that buffer can be arbitrarily large. However, we assume
      //  the underlying TCP layer has fixed buffer size and thus the
      //  number of bytes read will be always limited.
      inbuf = decoder.get_buffer();
      insize = read(inbuf);
      inbuf.flip();

      //  Check whether the peer has closed the connection.
      if (insize == -1) {
        insize = 0;
        disconnection = true;
      }
    }

    //  Push the data to the decoder.
    int processed = decoder.process_buffer(inbuf, insize);

    if (processed == -1) {
      disconnection = true;
    } else {

      //  Stop polling for input if we got stuck.
      if (processed < insize) io_object.reset_pollin(handle);

      //  Adjust the buffer.
      insize -= processed;
    }

    //  Flush all messages the decoder may have produced.
    session.flush();

    //  An input error has occurred. If the last decoded message
    //  has already been accepted, we terminate the engine immediately.
    //  Otherwise, we stop waiting for socket events and postpone
    //  the termination until after the message is accepted.
    if (disconnection) {
      if (decoder.stalled()) {
        io_object.rm_fd(handle);
        io_enabled = false;
      } else error();
    }
  }
Ejemplo n.º 2
0
  @Override
  public void activate_in() {
    if (!io_enabled) {
      //  There was an input error but the engine could not
      //  be terminated (due to the stalled decoder).
      //  Flush the pending message and terminate the engine now.
      decoder.process_buffer(inbuf, 0);
      assert (!decoder.stalled());
      session.flush();
      error();
      return;
    }

    io_object.set_pollin(handle);

    //  Speculative read.
    io_object.in_event();
  }
Ejemplo n.º 3
0
  private void unplug() {
    assert (plugged);
    plugged = false;

    //  Cancel all fd subscriptions.
    if (io_enabled) {
      io_object.rm_fd(handle);
      io_enabled = false;
    }

    //  Disconnect from I/O threads poller object.
    io_object.unplug();

    //  Disconnect from session object.
    if (encoder != null) encoder.set_msg_source(null);
    if (decoder != null) decoder.set_msg_sink(null);
    session = null;
  }
Ejemplo n.º 4
0
  @Override
  public int push_msg(Msg msg_) {
    assert (options.type == ZMQ.ZMQ_PUB || options.type == ZMQ.ZMQ_XPUB);

    //  The first message is identity.
    //  Let the session process it.
    int rc = session.push_msg(msg_);
    assert (rc == 0);

    //  Inject the subscription message so that the ZMQ 2.x peer
    //  receives our messages.
    msg_ = new Msg(1);
    msg_.put((byte) 1);
    rc = session.push_msg(msg_);
    session.flush();

    //  Once we have injected the subscription message, we can
    //  Divert the message flow back to the session.
    assert (decoder != null);
    decoder.set_msg_sink(session);

    return rc;
  }
Ejemplo n.º 5
0
  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;
  }