// Check if already in middle of a kex
if( _inKeyExchange.getAndSet(true) ) { // Flip state flag entering kex
return; // Return if already in process of kex
}
Buffer kexBuffer = new Buffer(); // Use a separate packet and buffer since
Packet kexPacket = new Packet(kexBuffer); // kex may be invoked by user thread
try {
// Random instance for generating the kex cookie. The 'cookie' MUST
// be a random value generated by the sender. Its purpose is to make
// it impossible for either side to fully determine the keys and the
// session identifier.
final Random random = AlgorithmManager.getManager().createAlgorithm(Algorithms.RANDOM, _session);
// Construct the KEX INIT message packet
// byte SSH_MSG_KEXINIT(20)
// byte[16] cookie (random bytes)
// string kex_algorithms
// string server_host_key_algorithms
// string encryption_algorithms_client_to_server
// string encryption_algorithms_server_to_client
// string mac_algorithms_client_to_server
// string mac_algorithms_server_to_client
// string compression_algorithms_client_to_server
// string compression_algorithms_server_to_client
// string languages_client_to_server
// string languages_server_to_client
// byte boolean first_kex_packet_follows
// uint32 0 (reserved for future extension)
kexPacket.reset();
kexBuffer.putByte(SSH_MSG_KEXINIT);
random.fill(kexBuffer.getArray(), kexBuffer.getIndex(), KEX_COOKIE_LENGTH);
kexBuffer.skip(KEX_COOKIE_LENGTH); // Move index forward
kexBuffer.putString(_session.getConfig().getString(SessionConfig.KEX_ALGORITHMS));
kexBuffer.putString(_session.getConfig().getString(SessionConfig.KEX_SERVER_HOST_KEY));