Search in sources :

Example 11 with ValueReference

use of zmq.util.ValueReference in project jeromq by zeromq.

the class StreamEngine method handshake.

// Detects the protocol used by the peer.
private boolean handshake() {
    assert (handshaking);
    assert (greetingRecv.position() < greetingSize);
    final Mechanisms mechanism = options.mechanism;
    assert (mechanism != null);
    // Position of the version field in the greeting.
    final int revisionPos = SIGNATURE_SIZE;
    // Make sure batch sizes match large buffer sizes
    final int inBatchSize = Math.max(options.rcvbuf, Config.IN_BATCH_SIZE.getValue());
    final int outBatchSize = Math.max(options.sndbuf, Config.OUT_BATCH_SIZE.getValue());
    // Receive the greeting.
    while (greetingRecv.position() < greetingSize) {
        final int n = read(greetingRecv);
        if (n == 0) {
            error(ErrorReason.CONNECTION);
            return false;
        }
        if (n == -1) {
            if (!errno.is(ZError.EAGAIN)) {
                error(ErrorReason.CONNECTION);
            }
            return false;
        }
        // peer is using unversioned protocol.
        if ((greetingRecv.get(0) & 0xff) != 0xff) {
            // then the other peer is using ZMTP 1.0.
            break;
        }
        if (greetingRecv.position() < SIGNATURE_SIZE) {
            continue;
        }
        // (i.e. the peer is using the unversioned protocol).
        if ((greetingRecv.get(9) & 0x01) != 0x01) {
            break;
        }
        // If the least significant bit is 1, the peer is using ZMTP 2.0 or later
        // and has sent us the ZMTP signature.
        int outpos = greetingSend.position();
        // Send the major version number.
        if (greetingSend.limit() == SIGNATURE_SIZE) {
            if (outsize == 0) {
                ioObject.setPollOut(handle);
            }
            greetingSend.limit(SIGNATURE_SIZE + 1);
            // Major version number
            greetingSend.put(revisionPos, Protocol.V3.revision);
            outsize += 1;
        }
        if (greetingRecv.position() > SIGNATURE_SIZE) {
            if (greetingSend.limit() == SIGNATURE_SIZE + 1) {
                if (outsize == 0) {
                    ioObject.setPollOut(handle);
                }
                // We read a further byte, which indicates the ZMTP version.
                byte protocol = greetingRecv.get(revisionPos);
                if (protocol == Protocol.V1.revision || protocol == Protocol.V2.revision) {
                    // If this is V1 or V2, we have a ZMTP 2.0 peer.
                    greetingSend.limit(V2_GREETING_SIZE);
                    greetingSend.position(SIGNATURE_SIZE + 1);
                    // Socket type
                    greetingSend.put((byte) options.type);
                    outsize += 1;
                } else {
                    // If this is 3 or greater, we have a ZMTP 3.0 peer.
                    greetingSend.limit(V3_GREETING_SIZE);
                    greetingSend.position(SIGNATURE_SIZE + 1);
                    // Minor version number
                    greetingSend.put((byte) 0);
                    outsize += 1;
                    greetingSend.mark();
                    greetingSend.put(new byte[20]);
                    assert (mechanism == Mechanisms.NULL || mechanism == Mechanisms.PLAIN || mechanism == Mechanisms.CURVE || mechanism == Mechanisms.GSSAPI);
                    greetingSend.reset();
                    greetingSend.put(mechanism.name().getBytes(ZMQ.CHARSET));
                    greetingSend.reset();
                    greetingSend.position(greetingSend.position() + 20);
                    outsize += 20;
                    greetingSend.put(new byte[32]);
                    outsize += 32;
                    greetingSize = V3_GREETING_SIZE;
                }
            }
        }
        greetingSend.position(outpos);
    }
    // messages.
    if ((greetingRecv.get(0) & 0xff) != 0xff || (greetingRecv.get(9) & 0x01) == 0) {
        // If the least significant bit is 0, then the other peer is using ZMTP 1.0.
        if (session.zapEnabled()) {
            // reject ZMTP 1.0 connections if ZAP is enabled
            error(ErrorReason.PROTOCOL);
            return false;
        }
        zmtpVersion = Protocol.V0;
        encoder = new V1Encoder(errno, outBatchSize);
        decoder = new V1Decoder(errno, inBatchSize, options.maxMsgSize, options.allocator);
        // 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 headerSize = options.identitySize + 1 >= 255 ? 10 : 2;
        ByteBuffer tmp = ByteBuffer.allocate(headerSize);
        // Prepare the identity message and load it into encoder.
        // Then consume bytes we have already sent to the peer.
        Msg txMsg = new Msg(options.identitySize);
        txMsg.put(options.identity, 0, options.identitySize);
        encoder.loadMsg(txMsg);
        ValueReference<ByteBuffer> bufferp = new ValueReference<>(tmp);
        int bufferSize = encoder.encode(bufferp, headerSize);
        assert (bufferSize == headerSize);
        // Make sure the decoder sees the data we have already received.
        decodeDataAfterHandshake(0);
        // message into the incoming message stream.
        if (options.type == ZMQ.ZMQ_PUB || options.type == ZMQ.ZMQ_XPUB) {
            subscriptionRequired = true;
        }
        // We are sending our identity now and the next message
        // will come from the socket.
        nextMsg = pullMsgFromSession;
        // We are expecting identity message.
        processMsg = processIdentity;
    } else if (greetingRecv.get(revisionPos) == Protocol.V1.revision) {
        // ZMTP/1.0 framing.
        zmtpVersion = Protocol.V1;
        if (session.zapEnabled()) {
            // reject ZMTP 1.0 connections if ZAP is enabled
            error(ErrorReason.PROTOCOL);
            return false;
        }
        encoder = new V1Encoder(errno, outBatchSize);
        decoder = new V1Decoder(errno, inBatchSize, options.maxMsgSize, options.allocator);
        decodeDataAfterHandshake(V2_GREETING_SIZE);
    } else if (greetingRecv.get(revisionPos) == Protocol.V2.revision) {
        // ZMTP/2.0 framing.
        zmtpVersion = Protocol.V2;
        if (session.zapEnabled()) {
            // reject ZMTP 2.0 connections if ZAP is enabled
            error(ErrorReason.PROTOCOL);
            return false;
        }
        encoder = new V2Encoder(errno, outBatchSize);
        decoder = new V2Decoder(errno, inBatchSize, options.maxMsgSize, options.allocator);
        decodeDataAfterHandshake(V2_GREETING_SIZE);
    } else {
        zmtpVersion = Protocol.V3;
        encoder = new V2Encoder(errno, outBatchSize);
        decoder = new V2Decoder(errno, inBatchSize, options.maxMsgSize, options.allocator);
        greetingRecv.position(V2_GREETING_SIZE);
        if (mechanism.isMechanism(greetingRecv)) {
            this.mechanism = mechanism.create(session, peerAddress, options);
        } else {
            error(ErrorReason.PROTOCOL);
            return false;
        }
        nextMsg = nextHandshakeCommand;
        processMsg = processHandshakeCommand;
    }
    // Start polling for output if necessary.
    if (outsize == 0) {
        ioObject.setPollOut(handle);
    }
    // Handshaking was successful.
    // Switch into the normal message flow.
    handshaking = false;
    if (hasHandshakeTimer) {
        ioObject.cancelTimer(HANDSHAKE_TIMER_ID);
        hasHandshakeTimer = false;
    }
    socket.eventHandshaken(endpoint, zmtpVersion.ordinal());
    return true;
}
Also used : Msg(zmq.Msg) V1Encoder(zmq.io.coder.v1.V1Encoder) Mechanisms(zmq.io.mechanism.Mechanisms) V2Encoder(zmq.io.coder.v2.V2Encoder) V1Decoder(zmq.io.coder.v1.V1Decoder) V2Decoder(zmq.io.coder.v2.V2Decoder) ByteBuffer(java.nio.ByteBuffer) ValueReference(zmq.util.ValueReference)

Example 12 with ValueReference

use of zmq.util.ValueReference in project jeromq by zeromq.

the class StreamEngine method inEvent.

@Override
public void inEvent() {
    assert (!ioError);
    // If still handshaking, receive and process the greeting message.
    if (handshaking) {
        if (!handshake()) {
            return;
        }
    }
    assert (decoder != null);
    // If there has been an I/O error, stop polling.
    if (inputStopped) {
        ioObject.removeHandle(handle);
        handle = null;
        ioError = true;
        return;
    }
    // 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.
        inpos = decoder.getBuffer();
        int rc = read(inpos);
        if (rc == 0) {
            error(ErrorReason.CONNECTION);
        }
        if (rc == -1) {
            if (!errno.is(ZError.EAGAIN)) {
                error(ErrorReason.CONNECTION);
            }
            return;
        }
        // Adjust input size
        inpos.flip();
        insize = rc;
    }
    boolean rc = false;
    ValueReference<Integer> processed = new ValueReference<>(0);
    while (insize > 0) {
        // Push the data to the decoder.
        Step.Result result = decoder.decode(inpos, insize, processed);
        assert (processed.get() <= insize);
        insize -= processed.get();
        if (result == Step.Result.MORE_DATA) {
            rc = true;
            break;
        }
        if (result == Step.Result.ERROR) {
            rc = false;
            break;
        }
        Msg msg = decoder.msg();
        rc = processMsg.apply(msg);
        if (!rc) {
            break;
        }
    }
    // or the session has rejected the message.
    if (!rc) {
        if (!errno.is(ZError.EAGAIN)) {
            error(ErrorReason.PROTOCOL);
            return;
        }
        inputStopped = true;
        ioObject.resetPollIn(handle);
    }
    // Flush all messages the decoder may have produced.
    session.flush();
}
Also used : Msg(zmq.Msg) Step(zmq.io.coder.IDecoder.Step) ValueReference(zmq.util.ValueReference)

Example 13 with ValueReference

use of zmq.util.ValueReference in project jeromq by zeromq.

the class V1EncoderTest method testReaderLong.

@Test
public void testReaderLong() {
    Msg msg = readLongMessage1();
    ValueReference<ByteBuffer> ref = new ValueReference<>();
    int outsize = encoder.encode(ref, 0);
    assertThat(outsize, is(0));
    ByteBuffer out = ref.get();
    assertThat(out, nullValue());
    encoder.loadMsg(msg);
    outsize = encoder.encode(ref, 64);
    assertThat(outsize, is(64));
    out = ref.get();
    int position = out.position();
    int limit = out.limit();
    assertThat(limit, is(64));
    assertThat(position, is(64));
    ref.set(null);
    outsize = encoder.encode(ref, 64);
    assertThat(outsize, is(138));
    out = ref.get();
    position = out.position();
    limit = out.limit();
    assertThat(position, is(62));
    assertThat(limit, is(200));
}
Also used : Msg(zmq.Msg) ByteBuffer(java.nio.ByteBuffer) ValueReference(zmq.util.ValueReference) Test(org.junit.Test)

Example 14 with ValueReference

use of zmq.util.ValueReference in project jeromq by zeromq.

the class V2EncoderTest method testReaderLong.

@Test
public void testReaderLong() {
    Msg msg = readLongMessage1();
    ValueReference<ByteBuffer> ref = new ValueReference<>();
    int outsize = encoder.encode(ref, 0);
    assertThat(outsize, is(0));
    ByteBuffer out = ref.get();
    assertThat(out, nullValue());
    encoder.loadMsg(msg);
    outsize = encoder.encode(ref, 64);
    assertThat(outsize, is(64));
    out = ref.get();
    int position = out.position();
    int limit = out.limit();
    assertThat(limit, is(64));
    assertThat(position, is(64));
    ref.set(null);
    outsize = encoder.encode(ref, 64);
    assertThat(outsize, is(138));
    out = ref.get();
    position = out.position();
    limit = out.limit();
    assertThat(position, is(62));
    assertThat(limit, is(200));
}
Also used : Msg(zmq.Msg) ByteBuffer(java.nio.ByteBuffer) ValueReference(zmq.util.ValueReference) Test(org.junit.Test)

Example 15 with ValueReference

use of zmq.util.ValueReference in project jeromq by zeromq.

the class AbstractDecoderTest method testReaderMultipleMsg.

@Test
public void testReaderMultipleMsg() {
    ByteBuffer in = decoder.getBuffer();
    int insize = readShortMessage(in);
    assertThat(insize, is(7));
    readShortMessage(in);
    in.flip();
    ValueReference<Integer> processed = new ValueReference<>(0);
    decoder.decode(in, 14, processed);
    assertThat(processed.get(), is(7));
    assertThat(in.position(), is(7));
    assertThat(decoder.msg(), notNullValue());
    Step.Result result = decoder.decode(in, 6, processed);
    assertThat(processed.get(), is(6));
    assertThat(in.position(), is(13));
    assertThat(result, is(Step.Result.MORE_DATA));
    result = decoder.decode(in, 10, processed);
    assertThat(processed.get(), is(1));
    assertThat(in.position(), is(14));
    assertThat(result, is(Step.Result.DECODED));
    assertThat(decoder.msg(), notNullValue());
}
Also used : Step(zmq.io.coder.IDecoder.Step) ByteBuffer(java.nio.ByteBuffer) ValueReference(zmq.util.ValueReference) Test(org.junit.Test)

Aggregations

ValueReference (zmq.util.ValueReference)19 Msg (zmq.Msg)16 ByteBuffer (java.nio.ByteBuffer)11 Test (org.junit.Test)10 Pipe (zmq.pipe.Pipe)6 Blob (zmq.util.Blob)4 Step (zmq.io.coder.IDecoder.Step)3 Metadata (zmq.io.Metadata)2 IDecoder (zmq.io.coder.IDecoder)1 IEncoder (zmq.io.coder.IEncoder)1 V1Decoder (zmq.io.coder.v1.V1Decoder)1 V1Encoder (zmq.io.coder.v1.V1Encoder)1 V2Decoder (zmq.io.coder.v2.V2Decoder)1 V2Encoder (zmq.io.coder.v2.V2Encoder)1 Mechanisms (zmq.io.mechanism.Mechanisms)1 SelectorProviderChooser (zmq.io.net.SelectorProviderChooser)1 TcpAddressMask (zmq.io.net.tcp.TcpAddress.TcpAddressMask)1 MsgAllocator (zmq.msg.MsgAllocator)1 MsgAllocatorThreshold (zmq.msg.MsgAllocatorThreshold)1