All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.async.rmi.messages.HandshakeManager Maven / Gradle / Ivy

package org.async.rmi.messages;

import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.ByteOrder;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

import static io.netty.buffer.Unpooled.buffer;

/**
 * Created by Barak Bar Orion
 * 12/4/14.
 */
public class HandshakeManager {
    @SuppressWarnings("UnusedDeclaration")
    private static final Logger logger = LoggerFactory.getLogger(HandshakeManager.class);

    private static final byte [] HANDSHAKE_PREFIX = new byte[]{97, 115, 121, 110, 99, 114, 109, 105};
    private byte challenge;
    private UUID clientId;


    public HandshakeManager(UUID clientId) {
        this.clientId = clientId;
    }

    public HandshakeManager() {
    }

    /**
     * Called by the client to initiate protocol handshake.
     *
     * @return the handshake initial message of the server.
     */
    public ByteBuf handshakeRequest() {
        challenge = (byte) (Math.random() * Byte.MAX_VALUE);
        ByteBuf buffer = buffer(29);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.writeBytes(HANDSHAKE_PREFIX);
        buffer.writeByte(challenge);
        buffer.writeInt(0);
        buffer.writeLong(clientId.getLeastSignificantBits());
        buffer.writeLong(clientId.getMostSignificantBits());
        return buffer;
    }

    /**
     * Called by the Server to verify client handshake initial message.
     *
     * @param request the client message
     * @param filters stack of network filters encoded as long.
     * @return The message that should be return to the client (the response).
     * @throws IOException if the verification fail.
     */
    public ByteBuf verifyRequest(ByteBuf request, int filters) throws NoSuchAlgorithmException, IOException {
        request.order(ByteOrder.BIG_ENDIAN);
        if (!isPrefixBytes(request.slice(0, 8))) {
            throw new IOException("Invalid protocol handshake request, prefix is not match");
        }
        int challenge = request.getByte(8);
        request.getInt(9);
        long lsb = request.getLong(13);
        long msb = request.getLong(21);
        clientId = new UUID(msb, lsb);
        ByteBuf reply = buffer(29);
        reply.order(ByteOrder.BIG_ENDIAN);
        reply.writeBytes(HANDSHAKE_PREFIX);
        reply.writeByte((byte) (challenge + 1));
        reply.writeInt(filters);
        reply.writeLong(0);
        reply.writeLong(0);
        return reply;
    }

    private boolean isPrefixBytes(ByteBuf bytes) {
        for(int i = 0; i < 8; ++i){
            if(HANDSHAKE_PREFIX[i] != bytes.getByte(i)){
                return false;
            }
        }
        return true;
    }

    /**
     * Called by the client to verify that the server response is according to the protocol.
     *
     * @param response the response from the server.
     * @return required network filters encoded as int.
     */
    public int verifyResponse(ByteBuf response) throws IOException, NoSuchAlgorithmException {
        response.order(ByteOrder.BIG_ENDIAN);
        if (!isPrefixBytes(response.slice(0, 8))) {
            throw new IOException("Invalid protocol handshake request, prefix is not match");
        }
        byte challenge = response.getByte(8);
        if (challenge != (byte) (this.challenge + 1)) {
            throw new IOException("Invalid protocol handshake response, number is not match");

        }
        return response.getInt(9);
    }

    public UUID getClientId() {
        return clientId;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy