Пример #1
0
Variant f_call_user_func_rpc(int _argc, CStrRef host, int port, CStrRef auth,
                             int timeout, CVarRef function,
                             CArrRef _argv /* = null_array */) {
  string shost = host.data();
  if (!RuntimeOption::DebuggerRpcHostDomain.empty()) {
    unsigned int pos = shost.find(RuntimeOption::DebuggerRpcHostDomain);
    if (pos == string::npos ||
        pos != shost.length() - RuntimeOption::DebuggerRpcHostDomain.size()) {
      shost += RuntimeOption::DebuggerRpcHostDomain;
    }
  }

  string url = "http://";
  url += shost;
  url += ":";
  url += lexical_cast<string>(port);
  url += "/call_user_func_serialized?auth=";
  url += auth.data();

  Array blob = CREATE_MAP2("func", function, "args", _argv);
  String message = f_serialize(blob);

  vector<string> headers;
  LibEventHttpClientPtr http = LibEventHttpClient::Get(shost, port);
  if (!http->send(url, headers, timeout < 0 ? 0 : timeout, false,
                  message.data(), message.size())) {
    raise_error("Unable to send RPC request");
    return false;
  }

  int code = http->getCode();
  if (code <= 0) {
    raise_error("Server timed out or unable to find specified URL: %s",
                url.c_str());
    return false;
  }

  int len = 0;
  char *response = http->recv(len);
  String sresponse(response, len, AttachString);
  if (code != 200) {
    raise_error("Internal server error: %d %s", code,
                HttpProtocol::GetReasonString(code));
    return false;
  }

  // This double decoding can be avoided by modifying RPC server to directly
  // take PHP serialization format.
  Variant res = f_unserialize(f_json_decode(sresponse));
  if (!res.isArray()) {
    raise_error("Internal protocol error");
    return false;
  }

  if (res.toArray().exists("exception")) {
    throw res["exception"];
  }
  return res["ret"];
}
Пример #2
0
bool XboxServer::PostMessage(const String& message,
                             const String& host /* = "localhost" */) {
  if (isLocalHost(host)) {
    Lock l(s_dispatchMutex);
    if (!s_dispatcher) {
      return false;
    }

    XboxTransport *job = new XboxTransport(message.toCppString());
    job->incRefCount(); // paired with worker's decRefCount()
    assert(s_dispatcher);
    s_dispatcher->enqueue(job);
    return true;

  } else { // remote

    string url = "http://";
    url += host.data();
    url += "/xbox_post_message";

    std::vector<std::string> headers;
    std::string hostStr(host.data());
    LibEventHttpClientPtr http =
      LibEventHttpClient::Get(hostStr, RuntimeOption::XboxServerPort);
    if (http->send(url, headers, 0, false, message.data(), message.size())) {
      int code = http->getCode();
      if (code > 0) {
        int len = 0;
        char *response = http->recv(len);
        String sresponse(response, len, AttachString);
        if (code == 200 &&
            same(
              unserialize_from_string(
                sresponse,
                VariableUnserializer::Type::Internal
              ),
              true
            )
           ) {
          return true;
        }
      }
    }
  }

  return false;
}
Пример #3
0
bool XboxServer::SendMessage(const String& message,
                             Array& ret,
                             int timeout_ms,
                             const String& host /* = "localhost" */) {
  if (isLocalHost(host)) {
    XboxTransport *job;
    {
      Lock l(s_dispatchMutex);
      if (!s_dispatcher) {
        return false;
      }

      job = new XboxTransport(message);
      job->incRefCount(); // paired with worker's decRefCount()
      job->incRefCount(); // paired with decRefCount() at below
      assert(s_dispatcher);
      s_dispatcher->enqueue(job);
    }

    if (timeout_ms <= 0) {
      timeout_ms = RuntimeOption::XboxDefaultLocalTimeoutMilliSeconds;
    }

    int code = 0;
    String response = job->getResults(code, timeout_ms);
    job->decRefCount(); // i'm done with this job

    if (code > 0) {
      ret.set(s_code, code);
      if (code == 200) {
        ret.set(s_response, unserialize_from_string(response));
      } else {
        ret.set(s_error, response);
      }
      return true;
    }

  } else { // remote

    string url = "http://";
    url += host.data();
    url += '/';
    url += RuntimeOption::XboxProcessMessageFunc;

    int timeoutSeconds = timeout_ms / 1000;
    if (timeoutSeconds <= 0) {
      timeoutSeconds = RuntimeOption::XboxDefaultRemoteTimeoutSeconds;
    }

    string hostStr(host.data());
    std::vector<std::string> headers;
    LibEventHttpClientPtr http =
      LibEventHttpClient::Get(hostStr, RuntimeOption::XboxServerPort);
    if (http->send(url, headers, timeoutSeconds, false,
                   message.data(), message.size())) {
      int code = http->getCode();
      if (code > 0) {
        int len = 0;
        char *response = http->recv(len);
        String sresponse(response, len, AttachString);
        ret.set(s_code, code);
        if (code == 200) {
          ret.set(s_response, unserialize_from_string(sresponse));
        } else {
          ret.set(s_error, sresponse);
        }
        return true;
      }
      // code wasn't correctly set by http client, treat it as not found
      ret.set(s_code, 404);
      ret.set(s_error, "http client failed");
    }
  }

  return false;
}