/**
   * Handle the the non-blocking RPC request by forwarding it to the correct service/method.
   *
   * @throws RpcException If there was some error executing the RPC.
   */
  public void doRpc(
      SocketRpcProtos.Request rpcRequest, final RpcCallback<SocketRpcProtos.Response> rpcCallback)
      throws RpcException {

    // Get the service, first try BlockingService
    BlockingService blockingService = blockingServiceMap.get(rpcRequest.getServiceName());
    if (blockingService != null) {
      Response response = forwardToBlockingService(rpcRequest, blockingService);
      rpcCallback.run(response);
      return;
    }

    // Now try Service
    Service service = serviceMap.get(rpcRequest.getServiceName());
    if (service == null) {
      throw new RpcException(
          ErrorReason.SERVICE_NOT_FOUND,
          "Could not find service: " + rpcRequest.getServiceName(),
          null);
    }

    // Call service using wrapper around rpcCallback
    final SocketRpcController socketController = new SocketRpcController();
    RpcCallback<Message> callback =
        new RpcCallback<Message>() {
          @Override
          public void run(Message response) {
            rpcCallback.run(createRpcResponse(response, true, socketController));
          }
        };
    forwardToService(rpcRequest, callback, service, socketController);
  }
  /**
   * Handle the blocking RPC request by forwarding it to the correct service/method.
   *
   * @throws RpcException If there was some error executing the RPC.
   */
  public SocketRpcProtos.Response doBlockingRpc(SocketRpcProtos.Request rpcRequest)
      throws RpcException {
    // Get the service, first try BlockingService
    BlockingService blockingService = blockingServiceMap.get(rpcRequest.getServiceName());
    if (blockingService != null) {
      return forwardToBlockingService(rpcRequest, blockingService);
    }

    // Now try Service
    Service service = serviceMap.get(rpcRequest.getServiceName());
    if (service == null) {
      throw new RpcException(
          ErrorReason.SERVICE_NOT_FOUND,
          "Could not find service: " + rpcRequest.getServiceName(),
          null);
    }

    // Call service using an instant callback
    Callback<Message> callback = new Callback<Message>();
    SocketRpcController socketController = new SocketRpcController();
    forwardToService(rpcRequest, callback, service, socketController);

    // Build and return response (callback invocation is optional)
    return createRpcResponse(callback.response, callback.invoked, socketController);
  }
 /** Get matching method. */
 private MethodDescriptor getMethod(
     SocketRpcProtos.Request rpcRequest, ServiceDescriptor descriptor) throws RpcException {
   MethodDescriptor method = descriptor.findMethodByName(rpcRequest.getMethodName());
   if (method == null) {
     throw new RpcException(
         ErrorReason.METHOD_NOT_FOUND,
         String.format(
             "Could not find method %s in service %s",
             rpcRequest.getMethodName(), descriptor.getFullName()),
         null);
   }
   return method;
 }
 /** Get request protobuf for the RPC method. */
 private Message getRequestProto(SocketRpcProtos.Request rpcRequest, Message requestPrototype)
     throws RpcException {
   Message.Builder builder;
   try {
     builder = requestPrototype.newBuilderForType().mergeFrom(rpcRequest.getRequestProto());
     if (!builder.isInitialized()) {
       throw new RpcException(ErrorReason.BAD_REQUEST_PROTO, "Invalid request proto", null);
     }
   } catch (InvalidProtocolBufferException e) {
     throw new RpcException(ErrorReason.BAD_REQUEST_PROTO, "Invalid request proto", e);
   }
   return builder.build();
 }