public function process_handshake(AvroIOBinaryDecoder $decoder, AvroIOBinaryEncoder $encoder, Transceiver $transceiver)
  {
    if ($transceiver->is_connected()) 
      return $transceiver->get_remote();
    
    $handshake_request = $this->handshake_responder_reader->read($decoder);
    $client_hash = $handshake_request["clientHash"];
    $client_protocol = $handshake_request["clientProtocol"];
    $remote_protocol =  $this->get_protocol_cache($client_hash);
    
    if (is_null($remote_protocol) && !is_null($client_protocol)) {
      $remote_protocol = AvroProtocol::parse($client_protocol);
      $this->set_protocol_cache($client_hash, $remote_protocol);
    }
    
    $server_hash = $handshake_request["serverHash"];
    $handshake_response = array();
    
    if ($this->local_hash == $server_hash)
      $handshake_response['match'] = (is_null($remote_protocol)) ? 'NONE' : 'BOTH';
    else
      $handshake_response['match'] = (is_null($remote_protocol)) ? 'NONE' : 'CLIENT';

    $handshake_response["meta"] = null;
    if ($handshake_response['match'] != 'BOTH') {
      $handshake_response["serverProtocol"] = $this->local_protocol->__toString();
      $handshake_response["serverHash"] = $this->local_hash;
    } else {
      $handshake_response["serverProtocol"] = null;
      $handshake_response["serverHash"] = null;
    }
    
    $this->handshake_responder_writer->write($handshake_response, $encoder);
    
    if ($handshake_response['match'] != 'NONE')
      $transceiver->set_remote($remote_protocol);

    return $remote_protocol;
  }