use of zmq.io.coder.v2.V2Decoder 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;
}
Aggregations