Example #1
0
static void
postal_http_reply_devices (PostalHttp  *http,
                           SoupMessage *message,
                           guint        status,
                           GPtrArray   *devices)
{
   JsonGenerator *g;
   PostalDevice *device;
   JsonArray *ar;
   JsonNode *node;
   JsonNode *child;
   gchar *json_buf;
   gsize length;
   guint i;

   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(devices);

   ar = json_array_new();
   node = json_node_new(JSON_NODE_ARRAY);

   for (i = 0; i < devices->len; i++) {
      device = g_ptr_array_index(devices, i);
      if ((child = postal_device_save_to_json(device, NULL))) {
         json_array_add_element(ar, child);
      }
   }

   json_node_set_array(node, ar);
   json_array_unref(ar);

   g = json_generator_new();
   json_generator_set_root(g, node);
   json_node_free(node);
   json_generator_set_indent(g, 2);
   json_generator_set_pretty(g, TRUE);
   json_buf = json_generator_to_data(g, &length);
   g_object_unref(g);

   soup_message_set_response(message,
                             "application/json",
                             SOUP_MEMORY_TAKE,
                             json_buf,
                             length);
   soup_message_set_status(message, status ?: SOUP_STATUS_OK);
   soup_server_unpause_message(http->priv->server, message);
}
Example #2
0
static void
postal_http_handle_v1_users_user_devices (UrlRouter         *router,
                                          SoupServer        *server,
                                          SoupMessage       *message,
                                          const gchar       *path,
                                          GHashTable        *params,
                                          GHashTable        *query,
                                          SoupClientContext *client,
                                          gpointer           user_data)
{
   const gchar *user;
   PostalHttp *http = user_data;

   ENTRY;

   g_assert(router);
   g_assert(SOUP_IS_SERVER(server));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(path);
   g_assert(params);
   g_assert(g_hash_table_contains(params, "user"));
   g_assert(client);
   g_assert(POSTAL_IS_HTTP(http));

   user = g_hash_table_lookup(params, "user");
   soup_server_pause_message(server, message);

   if (message->method == SOUP_METHOD_GET) {
      postal_service_find_devices(http->priv->service,
                                  user,
                                  get_int_param(query, "offset"),
                                  get_int_param(query, "limit"),
                                  NULL, /* TODO */
                                  devices_get_cb,
                                  g_object_ref(message));
      EXIT;
   }

   soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);
   soup_server_unpause_message(server, message);

   EXIT;
}
Example #3
0
static void recv_headers(SoupMessage *from, gpointer data)
{
	SoupMessage *to = ((struct destination_info *) data)->msg;
	SoupServer *server = ((struct destination_info *) data)->server;

	g_print("[%p] HTTP/1.%d %d %s\n", to,
		soup_message_get_http_version(from),
		from->status_code, from->reason_phrase);

	soup_message_set_status_full(to,
		from->status_code, from->reason_phrase);

	soup_message_headers_foreach(from->response_headers,
		copy_header, to->response_headers);
	/* we remove it, because libsoup appending at the end */
	soup_message_headers_remove(to->response_headers, "Content-Length");

	soup_server_unpause_message(server, to);
}
Example #4
0
static void
postal_http_reply_error (PostalHttp   *http,
                         SoupMessage  *message,
                         const GError *error)
{
   JsonGenerator *g;
   JsonObject *obj;
   JsonNode *node;
   gchar *json_buf;
   gsize length;

   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(error);

   obj = json_object_new();
   json_object_set_string_member(obj, "message", error->message);
   json_object_set_string_member(obj, "domain", g_quark_to_string(error->domain));
   json_object_set_int_member(obj, "code", error->code);

   node = json_node_new(JSON_NODE_OBJECT);
   json_node_set_object(node, obj);
   json_object_unref(obj);

   g = json_generator_new();
   json_generator_set_indent(g, 2);
   json_generator_set_pretty(g, TRUE);
   json_generator_set_root(g, node);
   json_node_free(node);
   json_buf = json_generator_to_data(g, &length);
   g_object_unref(g);

   soup_message_set_response(message,
                             "application/json",
                             SOUP_MEMORY_TAKE,
                             json_buf,
                             length);
   soup_message_set_status(message, get_status_code(error));
   soup_server_unpause_message(http->priv->server, message);
}
Example #5
0
static gboolean
send_chunks (gpointer user_data)
{
  SoupMessage *msg = SOUP_MESSAGE (user_data);
  char *s;
  SoupBuffer *buf;

  s = g_strdup_printf ("%d %d %d %d\n",
                       server_count, server_count,
                       server_count, server_count);
  buf = soup_buffer_new (SOUP_MEMORY_TAKE, s, strlen (s));

  soup_message_body_append_buffer (msg->response_body, buf);
  soup_server_unpause_message (server, msg);

  if (++server_count == NUM_CHUNKS)
  {
    soup_message_body_complete (msg->response_body);
    return FALSE;
  } else {
    return TRUE;
  }
}
Example #6
0
static void
korva_upnp_file_server_handle_request (SoupServer        *server,
                                       SoupMessage       *msg,
                                       const char        *path,
                                       GHashTable        *query,
                                       SoupClientContext *client,
                                       gpointer           user_data)
{
    KorvaUPnPFileServer *self = KORVA_UPNP_FILE_SERVER (user_data);
    GMatchInfo *info;
    char *id;
    GFile *file;
    KorvaUPnPHostData *data;
    ServeData *serve_data;
    SoupRange *ranges = NULL;
    int length;
    const char *content_features;
    GError *error = NULL;
    goffset size;

    if (msg->method != SOUP_METHOD_HEAD &&
        msg->method != SOUP_METHOD_GET) {
        soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);

        return;
    }

    g_debug ("Got %s request for uri: %s", msg->method, path);
    soup_message_headers_foreach (msg->request_headers, print_header, NULL);

    soup_server_pause_message (server, msg);
    soup_message_set_status (msg, SOUP_STATUS_OK);

    if (!g_regex_match (self->priv->path_regex,
                        path,
                        0,
                        &info)) {
        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
        g_match_info_free (info);

        goto out;
    }

    id = g_match_info_fetch (info, 1);
    g_match_info_free (info);

    file = g_hash_table_lookup (self->priv->id_map, id);
    g_free (id);

    if (file == NULL) {
        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);

        goto out;
    }

    data = g_hash_table_lookup (self->priv->host_data, file);
    if (data == NULL) {
        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);

        goto out;
    }

    if (!korva_upnp_host_data_valid_for_peer (data, soup_client_context_get_host (client))) {
        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);

        goto out;
    }

    serve_data = g_slice_new0 (ServeData);
    serve_data->host_data = data;
    g_object_add_weak_pointer (G_OBJECT (data), (gpointer *) &(serve_data->host_data));
    korva_upnp_host_data_add_request (data);
    size = korva_upnp_host_data_get_size (data);
    if (soup_message_headers_get_ranges (msg->request_headers, size, &ranges, &length)) {
        goffset start, end;
        start = ranges[0].start;
        end = ranges[0].end;

        if (start > size || start > end || end > size) {
            soup_message_set_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
            g_slice_free (ServeData, serve_data);

            goto out;
        } else {
            soup_message_set_status (msg, SOUP_STATUS_PARTIAL_CONTENT);
            soup_message_headers_set_content_range (msg->response_headers, start, end, size);
        }
        serve_data->start = start;
        serve_data->end = end;
    } else {
        serve_data->start = 0;
        serve_data->end = size - 1;
        soup_message_set_status (msg, SOUP_STATUS_OK);
    }

    soup_message_headers_set_content_length (msg->response_headers,
                                             serve_data->end - serve_data->start + 1);
    soup_message_headers_set_content_type (msg->response_headers,
                                           korva_upnp_host_data_get_content_type (data),
                                           NULL);

    content_features = soup_message_headers_get_one (msg->request_headers,
                                                     "getContentFeatures.dlna.org");
    if (content_features != NULL && atol (content_features) == 1) {
        const GVariant *value;

        value = korva_upnp_host_data_lookup_meta_data (data, "DLNAProfile");
        if (value == NULL) {
            soup_message_headers_append (msg->response_headers,
                                         "contentFeatures.dlna.org", "*");
        } else {
            soup_message_headers_append (msg->response_headers,
                                         "contentFeatures.dlna.org",
                                         korva_upnp_host_data_get_protocol_info (data));
        }
    }

    soup_message_headers_append (msg->response_headers, "Connection", "close");

    g_debug ("Response headers:");
    soup_message_headers_foreach (msg->response_headers, print_header, NULL);

    if (g_ascii_strcasecmp (msg->method, "HEAD") == 0) {
        g_debug ("Handled HEAD request of %s: %d", path, msg->status_code);
        g_slice_free (ServeData, serve_data);

        goto out;
    }

    soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CONTENT_LENGTH);
    soup_message_body_set_accumulate (msg->response_body, FALSE);

    serve_data->stream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
    serve_data->server = server;
    if (error != NULL) {
        g_warning ("Failed to MMAP file %s: %s",
                   path,
                   error->message);

        g_error_free (error);
        g_slice_free (ServeData, serve_data);

        soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);

        goto out;
    }
    g_seekable_seek (G_SEEKABLE (serve_data->stream), serve_data->start, G_SEEK_SET, NULL, NULL);

    /* Drop timeout until the message is done */
    korva_upnp_host_data_cancel_timeout (data);

    g_signal_connect (msg,
                      "wrote-chunk",
                      G_CALLBACK (korva_upnp_file_server_on_wrote_chunk),
                      serve_data);
    g_signal_connect (msg,
                      "wrote-headers",
                      G_CALLBACK (korva_upnp_file_server_on_wrote_chunk),
                      serve_data);
    g_signal_connect (msg,
                      "finished",
                      G_CALLBACK (korva_upnp_file_server_on_finished),
                      serve_data);

out:
    if (ranges != NULL) {
        soup_message_headers_free_ranges (msg->request_headers, ranges);
    }

    soup_server_unpause_message (server, msg);
}
Example #7
0
void
restraint_append_message (SoupSession *session,
                          SoupMessage *msg,
                          gpointer msg_data,
                          MessageFinishCallback finish_callback,
                          GCancellable *cancellable,
                          gpointer user_data)
{
    ClientData *client_data = (ClientData *) msg_data;
    time_t result;
    result = time(NULL);
    static time_t transaction_id = 0;
    // calculate the transaction id. base it off of epoch
    // incase the host reboots we shouldn't collide
    if (transaction_id == 0) {
        transaction_id = result;
    }
    MessageData *message_data;
    message_data = g_slice_new0 (MessageData);
    message_data->msg = msg;
    message_data->user_data = user_data;
    message_data->finish_callback = finish_callback;

    if (client_data != NULL) {
        GString *body = g_string_new("");
        SoupURI *uri = soup_message_get_uri (msg);
        soup_message_headers_foreach (msg->request_headers, append_header,
                                      body);
        // if we are doing a POST transaction
        // increment transaction_id and add it to headers
        // populate Location header in msg->reponse_headers
        const gchar *path = soup_uri_get_path (uri);
        if (g_strcmp0 (msg->method, "POST") == 0) {
            g_string_append_printf (body,
                                    "transaction-id: %jd\n", (intmax_t) transaction_id);
            gchar *location_url = g_strdup_printf ("%s%jd", path, (intmax_t) transaction_id);
            soup_message_headers_append (msg->response_headers, "Location", location_url);
            g_free (location_url);
            transaction_id++;
        }
        soup_message_set_status (msg, SOUP_STATUS_OK);
        g_string_append_printf (body,
                                "rstrnt-path: %s\n"
                                "rstrnt-method: %s\n"
                                "Content-Length: %d\r\n\r\n",
                                path,
                                msg->method,
                                (guint) msg->request_body->length);
        SoupBuffer *request = soup_message_body_flatten (msg->request_body);
        body = g_string_append_len (body, request->data,
                                          request->length);
        g_string_append_printf (body,
                           "\r\n--cut-here\n");

        soup_buffer_free (request);

        soup_message_body_append (client_data->client_msg->response_body,
                                  SOUP_MEMORY_TAKE,
                                  body->str, body->len);

        g_string_free (body, FALSE);

        soup_server_unpause_message (client_data->server, client_data->client_msg);
    }

    if (finish_callback) {
        g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
                         message_finish,
                         message_data,
                         message_destroy);
    } else {
        g_object_unref (msg);
        message_destroy (message_data);
    }
}
Example #8
0
static void
postal_http_handle_v1_users_user_devices_device (UrlRouter         *router,
                                                 SoupServer        *server,
                                                 SoupMessage       *message,
                                                 const gchar       *path,
                                                 GHashTable        *params,
                                                 GHashTable        *query,
                                                 SoupClientContext *client,
                                                 gpointer           user_data)
{
   PostalDevice *pdev;
   const gchar *user;
   const gchar *device;
   PostalHttp *http = user_data;
   GError *error = NULL;
   JsonNode *node;

   ENTRY;

   g_assert(router);
   g_assert(SOUP_IS_SERVER(server));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(path);
   g_assert(params);
   g_assert(g_hash_table_contains(params, "device"));
   g_assert(g_hash_table_contains(params, "user"));
   g_assert(client);
   g_assert(POSTAL_IS_HTTP(http));

   device = g_hash_table_lookup(params, "device");
   user = g_hash_table_lookup(params, "user");

   if (message->method == SOUP_METHOD_GET) {
      postal_service_find_device(http->priv->service,
                                 user,
                                 device,
                                 NULL, /* TODO */
                                 postal_http_find_device_cb,
                                 g_object_ref(message));
      soup_server_pause_message(server, message);
      EXIT;
   } else if (message->method == SOUP_METHOD_DELETE) {
      pdev = g_object_new(POSTAL_TYPE_DEVICE,
                          "device-token", device,
                          "user", user,
                          NULL);
      postal_service_remove_device(http->priv->service,
                                   pdev,
                                   NULL, /* TODO */
                                   postal_http_remove_device_cb,
                                   g_object_ref(message));
      soup_server_pause_message(server, message);
      g_object_unref(pdev);
      EXIT;
   } else if (message->method == SOUP_METHOD_PUT) {
      if (!(node = postal_http_parse_body(message, &error))) {
         postal_http_reply_error(http, message, error);
         soup_server_unpause_message(server, message);
         g_error_free(error);
         EXIT;
      }
      pdev = postal_device_new();
      if (!postal_device_load_from_json(pdev, node, &error)) {
         postal_http_reply_error(http, message, error);
         soup_server_unpause_message(server, message);
         json_node_free(node);
         g_error_free(error);
         g_object_unref(pdev);
         EXIT;
      }
      postal_device_set_device_token(pdev, device);
      postal_device_set_user(pdev, user);
      json_node_free(node);
      g_object_set_data_full(G_OBJECT(message),
                             "device",
                             g_object_ref(pdev),
                             g_object_unref);
      postal_service_add_device(http->priv->service,
                                pdev,
                                NULL, /* TODO */
                                postal_http_add_device_cb,
                                g_object_ref(message));
      soup_server_pause_message(server, message);
      g_object_unref(pdev);
      EXIT;
   } else {
      soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);
      EXIT;
   }

   g_assert_not_reached();
}