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); }
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; }
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); }
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); }
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; } }
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); }
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); } }
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(); }