Search in sources :

Example 1 with Mechanisms

use of zmq.io.mechanism.Mechanisms 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)

Aggregations

ByteBuffer (java.nio.ByteBuffer)1 Msg (zmq.Msg)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 ValueReference (zmq.util.ValueReference)1