Beispiel #1
0
gboolean xr_server_register_servlet(xr_server* server, xr_servlet_def* servlet)
{
  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p, servlet=%p)", server, servlet);

  g_return_val_if_fail(server != NULL, FALSE);
  g_return_val_if_fail(servlet != NULL, FALSE);

  if (_find_servlet_def(server, servlet->name))
    return FALSE;

  server->servlet_types = g_slist_append(server->servlet_types, servlet);
  return TRUE;
}
Beispiel #2
0
gboolean xr_client_open(xr_client_conn* conn, const char* uri, GError** err)
{
  GError* local_err = NULL;

  g_return_val_if_fail(conn != NULL, FALSE);
  g_return_val_if_fail(uri != NULL, FALSE);
  g_return_val_if_fail(!conn->is_open, FALSE);
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);

  xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p, uri=%s)", conn, uri);

  // parse URI format: http://host:8080/RES
  g_free(conn->host);
  g_free(conn->resource);
  conn->host = NULL;
  conn->resource = NULL;
  if (!_parse_uri(uri, &conn->secure, &conn->host, &conn->resource))
  {
    g_set_error(err, XR_CLIENT_ERROR, XR_CLIENT_ERROR_FAILED, "invalid URI format: %s", uri);
    return FALSE;
  }

  // enable/disable TLS
  if (conn->secure)
  {
    g_socket_client_set_tls(conn->client, TRUE);
    g_socket_client_set_tls_validation_flags(conn->client, G_TLS_CERTIFICATE_VALIDATE_ALL & ~G_TLS_CERTIFICATE_UNKNOWN_CA & ~G_TLS_CERTIFICATE_BAD_IDENTITY);
  }
  else
  {
    g_socket_client_set_tls(conn->client, FALSE);
  }

  conn->conn = g_socket_client_connect_to_host(conn->client, conn->host, 80, NULL, &local_err);
  if (local_err)
  {
    g_propagate_prefixed_error(err, local_err, "Connection failed: ");
    return FALSE;
  }

  xr_set_nodelay(g_socket_connection_get_socket(conn->conn));

  conn->http = xr_http_new(G_IO_STREAM(conn->conn));
  g_free(conn->session_id);
  conn->session_id = g_strdup_printf("%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int());
  conn->is_open = 1;

  xr_client_set_http_header(conn, "X-SESSION-ID", conn->session_id);

  return TRUE;
}
Beispiel #3
0
void xr_client_free(xr_client_conn* conn)
{
  xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p)", conn);

  if (conn == NULL)
    return;

  xr_client_close(conn);
  g_free(conn->host);
  g_free(conn->resource);
  g_free(conn->session_id);
  g_hash_table_destroy(conn->headers);
  g_free(conn);
}
Beispiel #4
0
gboolean xr_server_run(xr_server* server, GError** err)
{
  GError* local_err = NULL;

  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p, err=%p)", server, err);

  g_return_val_if_fail(server != NULL, FALSE);
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);

  g_socket_service_start(G_SOCKET_SERVICE(server->service));

  server->loop = g_main_loop_new(NULL, TRUE);
  g_main_loop_run(server->loop);

  return TRUE;
}
Beispiel #5
0
xr_client_conn* xr_client_new(GError** err)
{
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);

  xr_trace(XR_DEBUG_CLIENT_TRACE, "(err=%p)", err);

  xr_init();

  xr_client_conn* conn = g_new0(xr_client_conn, 1);
  conn->client = g_socket_client_new();

  conn->headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
  conn->transport = XR_CALL_XML_RPC;

  return conn;
}
Beispiel #6
0
void xr_client_close(xr_client_conn* conn)
{
  xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p)", conn);

  g_return_if_fail(conn != NULL);

  if (!conn->is_open)
    return;

  xr_http_free(conn->http);
  conn->http = NULL;
  if (conn->conn)
    g_object_unref(conn->conn);
  conn->conn = NULL;
  conn->is_open = FALSE;
}
Beispiel #7
0
void xr_server_free(xr_server* server)
{
  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p)", server);

  if (server == NULL)
    return;

  if (server->cert)
    g_object_unref(server->cert);
  g_object_unref(server->service);
  g_slist_free(server->servlet_types);
  g_thread_join(server->sessions_cleaner);
  g_hash_table_destroy(server->sessions);
  g_static_rw_lock_free(&server->sessions_lock);
  g_main_loop_unref(server->loop);
  g_free(server);
}
Beispiel #8
0
xr_server* xr_server_new(const char* cert, const char* privkey, int threads, GError** err)
{
  xr_trace(XR_DEBUG_SERVER_TRACE, "(cert=%s, threads=%d, err=%p)", cert, threads, err);
  GError* local_err = NULL;

  g_return_val_if_fail(threads > 0 && threads < 1000, NULL);
  g_return_val_if_fail (err == NULL || *err == NULL, NULL);

  xr_init();

  xr_server* server = g_new0(xr_server, 1);
  server->secure = !!cert;
  server->service = g_threaded_socket_service_new(threads);
  g_signal_connect(server->service, "run", (GCallback)_xr_server_service_run, server);

  if (cert)
  {
    gchar *cert_and_privkey = g_strconcat(cert, privkey, NULL);
    server->cert = g_tls_certificate_new_from_pem(cert_and_privkey, -1, &local_err);
    g_free(cert_and_privkey);

    if (local_err)
    {
      g_propagate_prefixed_error(err, local_err, "Certificate load failed: ");
      goto err0;
    }
  }

  server->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)xr_servlet_free_fini);
  g_static_rw_lock_init(&server->sessions_lock);
  server->sessions_cleaner = g_thread_create((GThreadFunc)sessions_cleaner_func, server, TRUE, NULL);
  if (server->sessions_cleaner == NULL)
    goto err1;

  return server;

err1:
  g_hash_table_destroy(server->sessions);
  g_static_rw_lock_free(&server->sessions_lock);
  if (server->cert)
    g_object_unref(server->cert);
err0:
  g_object_unref(server->service);
  g_free(server);
  return NULL;
}
Beispiel #9
0
gboolean xr_server_bind(xr_server* server, const char* bind_addr, GError** err)
{
  GError* local_err = NULL;
  char* addr = NULL;
  int port = 0;

  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p, bind_addr=%s, err=%p)", server, bind_addr, err);

  g_return_val_if_fail(server != NULL, FALSE);
  g_return_val_if_fail(bind_addr != NULL, FALSE);
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
  g_return_val_if_fail(_parse_addr(bind_addr, &addr, &port), FALSE);

  if (addr[0] == '*')
  {
    g_socket_listener_add_inet_port(G_SOCKET_LISTENER(server->service), (guint16)port, NULL, &local_err);
  }
  else
  {
    // build address
    GInetAddress* iaddr = g_inet_address_new_from_string(addr);
    if (!iaddr)
    {
      g_error_new(XR_SERVER_ERROR, XR_SERVER_ERROR_FAILED, "Invalid address: %s", bind_addr);
      g_free(addr);
      xr_server_stop(server);
      return FALSE;
    }

    GSocketAddress* isaddr = g_inet_socket_address_new(iaddr, (guint16)port);
    g_socket_listener_add_address(G_SOCKET_LISTENER(server->service), isaddr, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL, NULL, &local_err);
  }

  g_free(addr);

  if (local_err)
  {
    g_propagate_prefixed_error(err, local_err, "Port listen failed: ");
    xr_server_stop(server);
    return FALSE;
  }

  return TRUE;
}
Beispiel #10
0
static gboolean _xr_server_serve_request(xr_server* server, xr_server_conn* conn)
{
  const char* method;
  int version;

  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p, conn=%p)", server, conn);

  g_return_val_if_fail(server != NULL, FALSE);
  g_return_val_if_fail(conn != NULL, FALSE);

  if (!g_socket_connection_is_connected(conn->conn))
    return FALSE;

  /* receive HTTP request */
  if (!xr_http_read_header(conn->http, NULL))
    return FALSE;

  /* check if some dumb bunny sent us wrong message type */
  if (xr_http_get_message_type(conn->http) != XR_HTTP_REQUEST)
    return FALSE;

  method = xr_http_get_method(conn->http);
  if (method == NULL)
    return FALSE;

  version = xr_http_get_version(conn->http);

  if (!strcmp(method, "GET"))
    return _xr_server_serve_download(server, conn) && (version == 1);
  else if (!strcmp(method, "POST"))
  {
    int transport = _ctype_to_transport(xr_http_get_header(conn->http, "Content-Type"));

    if (transport >= 0)
    {
      xr_call* call;
      GString* request;
      char* buffer;
      int length;
      gboolean rs;

      request = xr_http_read_all(conn->http, NULL);
      if (request == NULL)
        return FALSE;

      /* parse request data into xr_call */
      call = xr_call_new(NULL);
      xr_call_set_transport(call, transport);

      rs = xr_call_unserialize_request(call, request->str, request->len);
      g_string_free(request, TRUE);

      /* run call */
      if (!rs)
        xr_call_set_error(call, -1, "Unserialize request failure.");
      else
        _xr_server_servlet_method_call(server, conn, call);

      /* generate response data from xr_call */
      xr_call_serialize_response(call, &buffer, &length);
      if (xr_debug_enabled & XR_DEBUG_CALL)
        xr_call_dump(call, 0);

      /* send HTTP response */
      xr_http_setup_response(conn->http, 200);
      xr_http_set_message_length(conn->http, length);
      rs = xr_http_write_all(conn->http, buffer, length, NULL);
      xr_call_free_buffer(call, buffer);
      xr_call_free(call);

      return rs && (version == 1);
    }
    else
      return _xr_server_serve_upload(server, conn) && (version == 1);
  }
  else
    return FALSE;

  return TRUE;
}
Beispiel #11
0
gboolean xr_client_call(xr_client_conn* conn, xr_call* call, GError** err)
{
  char* buffer;
  int length;
  gboolean rs;
  gboolean write_success;
  GString* response;

  xr_trace(XR_DEBUG_CLIENT_TRACE, "(conn=%p, call=%p)", conn, call);

  g_return_val_if_fail(conn != NULL, FALSE);
  g_return_val_if_fail(call != NULL, FALSE);
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);

  if (!conn->is_open)
  {
    g_set_error(err, XR_CLIENT_ERROR, XR_CLIENT_ERROR_CLOSED, "Can't perform RPC on closed connection.");
    return FALSE;
  }

  /* serialize nad send XML-RPC request */
  xr_call_set_transport(call, conn->transport);
  xr_call_serialize_request(call, &buffer, &length);
  xr_http_setup_request(conn->http, "POST", conn->resource, conn->host);
  g_hash_table_foreach(conn->headers, (GHFunc)_add_http_header, conn->http);
  if (conn->transport == XR_CALL_XML_RPC)
    xr_http_set_header(conn->http, "Content-Type", "text/xml");
#ifdef XR_JSON_ENABLED
  else if (conn->transport == XR_CALL_JSON_RPC)
    xr_http_set_header(conn->http, "Content-Type", "text/json");
#endif
  xr_http_set_message_length(conn->http, length);
  write_success = xr_http_write_all(conn->http, buffer, length, err);
  xr_call_free_buffer(call, buffer);
  if (!write_success)
  {
    xr_client_close(conn);
    return FALSE;
  }

  /* receive HTTP response header */
  if (!xr_http_read_header(conn->http, err))
    return FALSE;

  /* check if some dumb bunny sent us wrong message type */
  if (xr_http_get_message_type(conn->http) != XR_HTTP_RESPONSE)
    return FALSE;

  response = xr_http_read_all(conn->http, err);
  if (response == NULL)
  {
    xr_client_close(conn);
    return FALSE;
  }

  rs = xr_call_unserialize_response(call, response->str, response->len);
  g_string_free(response, TRUE);
  if (!rs)
  {
    g_set_error(err, 0, xr_call_get_error_code(call), "%s", xr_call_get_error_message(call));

    if (xr_debug_enabled & XR_DEBUG_CALL)
      xr_call_dump(call, 0);

    return FALSE;
  }

  if (xr_debug_enabled & XR_DEBUG_CALL)
    xr_call_dump(call, 0);

  return TRUE;
}
Beispiel #12
-1
void xr_server_stop(xr_server* server)
{
  xr_trace(XR_DEBUG_SERVER_TRACE, "(server=%p)", server);

  g_return_if_fail(server != NULL);

  g_socket_service_stop(G_SOCKET_SERVICE(server->service));
  g_main_loop_quit(server->loop);
}