public void callMethod(
      MethodDescriptor method,
      RpcController controller,
      Message request,
      Message responsePrototype,
      RpcCallback<Message> done) {
    ClientRpcController rpcController = (ClientRpcController) controller;

    int correlationId = getNextCorrelationId();
    rpcController.setCorrelationId(correlationId);

    PendingClientCallState state =
        new PendingClientCallState(rpcController, method, responsePrototype, request, done);
    registerPendingRequest(correlationId, state);

    RpcRequest rpcRequest =
        RpcRequest.newBuilder()
            .setCorrelationId(correlationId)
            .setServiceIdentifier(state.getServiceIdentifier())
            .setMethodIdentifier(state.getMethodIdentifier())
            .setRequestBytes(request.toByteString())
            .build();

    if (channel.isConnected()) {
      if (LOGGER.isDebugEnabled())
        //				LOGGER.debug("Sending ["+rpcRequest.getCorrelationId()+"]RpcRequest.");
        LOGGER.debug(
            "Sending [" + rpcRequest.getCorrelationId() + "]RpcRequest. signature {}",
            state.getMethodDesc().getFullName());
      WirePayload payload = WirePayload.newBuilder().setRpcRequest(rpcRequest).build();
      channel.write(payload);
    } else {
      LOGGER.error("Sending [" + rpcRequest.getCorrelationId() + "]RpcRequest. FAILURE");
      String errorMessage = "Session [" + channel + "]closed";
      RpcError rpcError =
          RpcError.newBuilder()
              .setCorrelationId(correlationId)
              .setErrorMessage(errorMessage)
              .build();
      error(rpcError);
      doLog(state, rpcError, errorMessage);
    }
  }
  void startCancel(int correlationId) {
    PendingClientCallState state = removePendingRequest(correlationId);
    if (state != null) {
      RpcCancel rpcCancel = RpcCancel.newBuilder().setCorrelationId(correlationId).build();
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("Sending [" + rpcCancel.getCorrelationId() + "]RpcCancel.");
      WirePayload payload = WirePayload.newBuilder().setRpcCancel(rpcCancel).build();
      channel.write(payload).awaitUninterruptibly();

      String errorMessage = "Cancel";

      doLog(state, rpcCancel, errorMessage);

      state.handleFailure(errorMessage);

    } else {
      // this can happen if the server call completed in the meantime.
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("No PendingClientCallState found for correlationId " + correlationId);
    }
  }