Exemple #1
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
		 const char *path, GHashTable *query,
		 SoupClientContext *context, gpointer data)
{
	SlowData *sd;

	if (msg->method != SOUP_METHOD_GET) {
		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
		return;
	}

	soup_message_set_status (msg, SOUP_STATUS_OK);
	if (!strcmp (path, "/fast")) {
		soup_message_set_response (msg, "text/plain",
					   SOUP_MEMORY_STATIC, "OK\r\n", 4);
		return;
	}

	soup_message_headers_set_encoding (msg->response_headers,
					   SOUP_ENCODING_CHUNKED);
	g_object_ref (msg);
	soup_server_pause_message (server, msg);

	sd = g_new (SlowData, 1);
	sd->server = server;
	sd->msg = msg;
	sd->timeout = soup_add_timeout (
		soup_server_get_async_context (server),
		200, add_body_chunk, sd);
	g_signal_connect (msg, "finished",
			  G_CALLBACK (request_failed), sd);
}
Exemple #2
0
static void
snra_server_client_wrote_headers (SoupMessage * msg, SnraServerClient * client)
{
    GList *cur;

    /* Pause the message so Soup doesn't do any more responding */
    soup_server_pause_message (client->soup, msg);

    g_print ("client %u ready for traffic\n", client->conn_id);

    client->io = g_io_channel_unix_new (soup_socket_get_fd (client->socket));
    g_io_channel_set_encoding (client->io, NULL, NULL);
    g_io_channel_set_buffered (client->io, FALSE);
    client->io_watch = g_io_add_watch (client->io, G_IO_IN | G_IO_HUP,
                                       (GIOFunc) (snra_server_client_io_cb), client);

    /* Send any pending messages */
    while ((cur = client->pending_msgs)) {
        GList *next;
        PendingMsg *msg = (PendingMsg *) (cur->data);

        next = g_list_next (cur);

        snra_server_client_send_message (client, msg->body, msg->len);
        client->pending_msgs = g_list_delete_link (client->pending_msgs, cur);
        g_free (msg->body);
        g_free (msg);

        cur = next;
    }
}
Exemple #3
0
static void
korva_upnp_file_server_on_wrote_chunk (SoupMessage *msg,
                                       gpointer     user_data)
{
    ServeData *data = (ServeData *) user_data;
    int chunk_size;
    char *file_buffer;
    GError *error = NULL;
    gsize bytes_read;

    soup_server_pause_message (data->server, msg);

    chunk_size = MIN (data->end - data->start + 1, G_MAXUINT16 + 1);

    if (chunk_size <= 0) {
        soup_message_body_complete (msg->response_body);
        soup_server_unpause_message (data->server, msg);

        return;
    }

    file_buffer = g_malloc0 (chunk_size);
    g_input_stream_read_all (data->stream,
                             (void *) file_buffer,
                             chunk_size,
                             &bytes_read,
                             NULL,
                             &error);

    data->start += chunk_size;
    soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE, file_buffer, chunk_size);

    soup_server_unpause_message (data->server, msg);
}
void
gss_transaction_delay (GssTransaction * t, int msec)
{
  GssTransaction *new_t;

  /* FIXME this is pure evil */

  new_t = g_malloc0 (sizeof (GssTransaction));
  memcpy (new_t, t, sizeof (GssTransaction));

  soup_server_pause_message (t->soupserver, t->msg);
  g_timeout_add (msec, unpause, new_t);
}
Exemple #5
0
void trex_callback(SoupServer *server, SoupMessage *msg,
	const char *path, GHashTable *query, const char *dest)
{
	SoupMessage *new_msg;
	SoupSession *session;
	char *uri_str;

	struct destination_info *to = malloc(sizeof(struct destination_info));
	to->server = server;
	to->msg = msg;

	session = soup_session_async_new();

	uri_str = soup_uri_to_string(soup_message_get_uri(msg), true);
	/*
	 * TODO Memory Leak :-)
	*/
	uri_str = g_strjoin(NULL, dest, uri_str, NULL);

	g_print("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uri_str,
		soup_message_get_http_version(msg));

	/* build new request */
	new_msg = soup_message_new(msg->method, uri_str);
	soup_message_headers_foreach(msg->request_headers, copy_header,
		new_msg->request_headers);
	soup_message_headers_remove(new_msg->request_headers, "Host");
	if (msg->request_body->length) {
		SoupBuffer *request =
			soup_message_body_flatten(msg->request_body);
		soup_message_body_append_buffer(new_msg->request_body,
			request);
		soup_buffer_free(request);
	}
	soup_message_headers_set_encoding(msg->response_headers,
		SOUP_ENCODING_CHUNKED);

	soup_server_pause_message(server, msg);

	g_signal_connect(new_msg, "got_headers",
		G_CALLBACK(recv_headers), to);
	g_signal_connect(new_msg, "got_chunk",
		G_CALLBACK(recv_chunk), to);

	soup_session_queue_message(session, new_msg, finish_msg, to);

	g_object_ref(msg);

	g_object_unref(session);
}
Exemple #6
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
                 const char *path, GHashTable *query,
                 SoupClientContext *client, gpointer user_data)
{
  if (g_str_equal (path, "/stream")) {
    soup_message_set_status (msg, SOUP_STATUS_OK);
    soup_message_headers_set_encoding (msg->response_headers,
                                       SOUP_ENCODING_CHUNKED);
    soup_server_pause_message (server, msg);

    server_count = 1;
    g_idle_add (send_chunks, msg);
  }
}
Exemple #7
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
		 const char *path, GHashTable *query,
		 SoupClientContext *context, gpointer data)
{
	SoupMessage *msg2;
	char *uristr;

	uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
	printf ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
		soup_message_get_http_version (msg));

	if (msg->method == SOUP_METHOD_CONNECT) {
		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
		return;
	}

	msg2 = soup_message_new (msg->method, uristr);
        msg2 = soup_message_new (msg->method, uristr);
	soup_message_headers_foreach (msg->request_headers, copy_header,
				      msg2->request_headers);
	soup_message_headers_remove (msg2->request_headers, "Host");
	soup_message_headers_remove (msg2->request_headers, "Connection");

	if (msg->request_body->length) {
		SoupBuffer *request = soup_message_body_flatten (msg->request_body);
		soup_message_body_append_buffer (msg2->request_body, request);
		soup_buffer_free (request);
	}
	soup_message_headers_set_encoding (msg->response_headers,
					   SOUP_ENCODING_CHUNKED);

	g_signal_connect (msg2, "got_headers",
			  G_CALLBACK (send_headers), msg);
	g_signal_connect (msg2, "got_chunk",
			  G_CALLBACK (send_chunk), msg);

	g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);

	soup_session_queue_message (session, msg2, finish_msg, msg);

	g_object_ref (msg);
	soup_server_pause_message (server, msg);
}
Exemple #8
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;
}
Exemple #9
0
static void
try_tunnel (SoupServer *server, SoupMessage *msg, SoupClientContext *context)
{
	Tunnel *tunnel;
	SoupURI *dest_uri;
	GSocketClient *sclient;

	soup_server_pause_message (server, msg);

	tunnel = g_new0 (Tunnel, 1);
	tunnel->self = g_object_ref (server);
	tunnel->msg = g_object_ref (msg);
	tunnel->context = context;

	dest_uri = soup_message_get_uri (msg);
	sclient = g_socket_client_new ();
	g_socket_client_connect_to_host_async (sclient, dest_uri->host, dest_uri->port,
					       NULL, tunnel_connected_cb, tunnel);
	g_object_unref (sclient);
}
Exemple #10
0
static void
server_handler (SoupServer        *server,
		SoupMessage       *msg, 
		const char        *path,
		GHashTable        *query,
		SoupClientContext *client,
		gpointer           user_data)
{
	soup_message_set_status (msg, SOUP_STATUS_OK);
	soup_message_set_response (msg, "text/plain",
				   SOUP_MEMORY_STATIC,
				   "ok\r\n", 4);

	if (!strcmp (path, "/slow")) {
		soup_server_pause_message (server, msg);
		g_object_set_data (G_OBJECT (msg), "server", server);
		soup_add_timeout (soup_server_get_async_context (server),
				  1100, timeout_finish_message, msg);
	}
}
Exemple #11
0
SnraServerClient *
snra_server_client_new_single (SoupServer * soup, SoupMessage * msg,
                               G_GNUC_UNUSED SoupClientContext * context)
{
    SnraServerClient *client = g_object_new (SNRA_TYPE_SERVER_CLIENT, NULL);

    client->soup = soup;
    client->event_pipe = msg;
    client->host = g_strdup (soup_client_context_get_host (context));

    client->net_event_sig = g_signal_connect (msg, "network-event",
                            G_CALLBACK (snra_server_client_network_event), client);
    client->disco_sig = g_signal_connect (msg, "finished",
                                          G_CALLBACK (snra_server_client_disconnect), client);

    client->type = SNRA_SERVER_CLIENT_SINGLE;
    client->need_body_complete = TRUE;

    soup_message_set_status (msg, SOUP_STATUS_OK);
    soup_server_pause_message (client->soup, msg);

    return client;
}
void
dacp_share_ctrl_int (DMAPShare * share,
		     SoupServer * server,
		     SoupMessage * message,
		     const char *path,
		     GHashTable * query, SoupClientContext * context)
{
	const char *rest_of_path;

	DACPShare *dacp_share = DACP_SHARE (share);

	g_debug ("Path is %s.", path);
	if (query) {
		g_hash_table_foreach (query, debug_param, NULL);
	}

	rest_of_path = strchr (path + 1, '/');

	/* If calling /ctrl-int without args, the client doesnt need a 
	 * session-id, otherwise it does and it should be validated. */
	if ((rest_of_path != NULL)
	    &&
	    (!_dmap_share_session_id_validate
	     (share, context, message, query, NULL))) {
		soup_message_set_status (message, SOUP_STATUS_FORBIDDEN);
		return;
	}

	if (rest_of_path == NULL) {
		/* CACI control-int
		 *      MSTT status
		 *      MUTY update type
		 *      MTCO specified total count
		 *      MRCO returned count
		 *      MLCL listing
		 *              MLIT listing item
		 *                      MIID item id
		 *                      CMIK Unknown (TRUE)
		 *                      CMSP Unknown (TRUE)
		 *                      CMSV Unknown (TRUE)
		 *                      CASS Unknown (TRUE)
		 *                      CASU Unknown (TRUE)
		 *                      CASG Unknown (TRUE)
		 */

		GNode *caci;
		GNode *mlcl;
		GNode *mlit;

		// dacp.controlint
		caci = dmap_structure_add (NULL, DMAP_CC_CACI);
		// dmap.status
		dmap_structure_add (caci, DMAP_CC_MSTT,
				    (gint32) DMAP_STATUS_OK);
		// dmap.updatetype
		dmap_structure_add (caci, DMAP_CC_MUTY, 0);
		// dmap.specifiedtotalcount
		dmap_structure_add (caci, DMAP_CC_MTCO, (gint32) 1);
		// dmap.returnedcount
		dmap_structure_add (caci, DMAP_CC_MRCO, (gint32) 1);
		// dmap.listing
		mlcl = dmap_structure_add (caci, DMAP_CC_MLCL);
		// dmap.listingitem
		mlit = dmap_structure_add (mlcl, DMAP_CC_MLIT);
		// dmap.itemid
		dmap_structure_add (mlit, DMAP_CC_MIID, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CMIK, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CMSP, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CMSV, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CASS, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CASU, (gint32) 1);
		// Unknown (TRUE)
		dmap_structure_add (mlit, DMAP_CC_CASG, (gint32) 1);

		_dmap_share_message_set_from_dmap_structure (share, message,
							     caci);
		dmap_structure_destroy (caci);
	} else if (g_ascii_strcasecmp ("/1/getproperty", rest_of_path) == 0) {
		gchar *properties_query, **properties, **property;
		GNode *cmgt;

		properties_query = g_hash_table_lookup (query, "properties");

		if (!properties_query) {
			g_warning ("No property specified");
			return;
		}

		cmgt = dmap_structure_add (NULL, DMAP_CC_CMGT);
		dmap_structure_add (cmgt, DMAP_CC_MSTT, DMAP_STATUS_OK);

		properties = g_strsplit (properties_query, ",", -1);
		for (property = properties; *property; property++) {
			if (g_ascii_strcasecmp (*property, "dmcp.volume") ==
			    0) {
				gulong volume;

				g_object_get (dacp_share->priv->player,
					      "volume", &volume, NULL);
				//g_debug ("Sending volume: %lu", volume);
				dmap_structure_add (cmgt, DMAP_CC_CMVO,
						    volume);
			} else {
				g_warning ("Unhandled property %s",
					   *property);
			}
		}

		g_strfreev (properties);

		_dmap_share_message_set_from_dmap_structure (share, message,
							     cmgt);
		dmap_structure_destroy (cmgt);
	} else if (g_ascii_strcasecmp ("/1/setproperty", rest_of_path) == 0) {
		if (g_hash_table_lookup (query, "dmcp.volume")) {
			gdouble volume =
				strtod (g_hash_table_lookup
					(query, "dmcp.volume"), NULL);
			g_object_set (dacp_share->priv->player, "volume",
				      (gulong) volume, NULL);
		}
		soup_message_set_status (message, SOUP_STATUS_NO_CONTENT);
	} else if (g_ascii_strcasecmp ("/1/getspeakers", rest_of_path) == 0) {
		GNode *casp;

		casp = dmap_structure_add (NULL, DMAP_CC_CASP);
		dmap_structure_add (casp, DMAP_CC_MSTT,
				    (gint32) DMAP_STATUS_OK);
		dmap_structure_add (casp, DMAP_CC_MDCL);

		dmap_structure_add (casp, DMAP_CC_CAIA, TRUE);
		dmap_structure_add (casp, DMAP_CC_MINM, "Computer");
		dmap_structure_add (casp, DMAP_CC_MSMA, (gint32) 0);

		_dmap_share_message_set_from_dmap_structure (share, message,
							     casp);
		dmap_structure_destroy (casp);
	} else if (g_ascii_strcasecmp ("/1/playstatusupdate", rest_of_path) ==
		   0) {
		gchar *revision =
			g_hash_table_lookup (query, "revision-number");
		gint revision_number = atoi (revision);

		if (revision_number >= dacp_share->priv->current_revision) {
			g_object_ref (message);
			dacp_share->priv->update_queue =
				g_slist_prepend (dacp_share->
						 priv->update_queue, message);
			g_signal_connect_object (message, "finished",
						 G_CALLBACK
						 (status_update_message_finished),
						 dacp_share, 0);
			soup_server_pause_message (server, message);
		} else {
			dacp_share_fill_playstatusupdate (dacp_share,
							  message);
		}
	} else if (g_ascii_strcasecmp ("/1/playpause", rest_of_path) == 0) {
		dacp_player_play_pause (dacp_share->priv->player);
		soup_message_set_status (message, SOUP_STATUS_NO_CONTENT);
	} else if (g_ascii_strcasecmp ("/1/pause", rest_of_path) == 0) {
		dacp_player_pause (dacp_share->priv->player);
		soup_message_set_status (message, SOUP_STATUS_NO_CONTENT);
	} else if (g_ascii_strcasecmp ("/1/nextitem", rest_of_path) == 0) {
		dacp_player_next_item (dacp_share->priv->player);
		soup_message_set_status (message, SOUP_STATUS_NO_CONTENT);
	} else if (g_ascii_strcasecmp ("/1/previtem", rest_of_path) == 0) {
		dacp_player_prev_item (dacp_share->priv->player);
		soup_message_set_status (message, SOUP_STATUS_NO_CONTENT);
	} else if (g_ascii_strcasecmp ("/1/nowplayingartwork", rest_of_path)
		   == 0) {
		guint width = 320;
		guint height = 320;
		gchar *artwork_filename;
		gchar *buffer;
		gsize buffer_len;

		if (g_hash_table_lookup (query, "mw"))
			width = atoi (g_hash_table_lookup (query, "mw"));
		if (g_hash_table_lookup (query, "mh"))
			height = atoi (g_hash_table_lookup (query, "mh"));
		artwork_filename =
			dacp_player_now_playing_artwork (dacp_share->
							 priv->player, width,
							 height);
		if (!artwork_filename) {
			g_debug ("No artwork for currently playing song");
			soup_message_set_status (message,
						 SOUP_STATUS_NOT_FOUND);
			return;
		}
#ifdef HAVE_GDKPIXBUF
		GdkPixbuf *artwork =
			gdk_pixbuf_new_from_file_at_scale (artwork_filename,
							   width, height,
							   TRUE, NULL);

		if (!artwork) {
			g_debug ("Error loading image file");
			g_free (artwork_filename);
			soup_message_set_status (message,
						 SOUP_STATUS_INTERNAL_SERVER_ERROR);
			return;
		}
		if (!gdk_pixbuf_save_to_buffer
		    (artwork, &buffer, &buffer_len, "png", NULL, NULL)) {
			g_debug ("Error saving artwork to PNG");
			g_object_unref (artwork);
			g_free (artwork_filename);
			soup_message_set_status (message,
						 SOUP_STATUS_INTERNAL_SERVER_ERROR);
			return;
		}
		g_object_unref (artwork);
#else
		if (!g_file_get_contents
		    (artwork_filename, &buffer, &buffer_len, NULL)) {
			g_debug ("Error getting artwork data");
			g_free (artwork_filename);
			soup_message_set_status (message,
						 SOUP_STATUS_INTERNAL_SERVER_ERROR);
			return;
		}
#endif
		g_free (artwork_filename);
		soup_message_set_status (message, SOUP_STATUS_OK);
		soup_message_set_response (message, "image/png",
					   SOUP_MEMORY_TAKE, buffer,
					   buffer_len);
	} else if (g_ascii_strcasecmp ("/1/cue", rest_of_path) == 0) {
		gchar *command;

		command = g_hash_table_lookup (query, "command");

		if (!command) {
			g_debug ("No CUE command specified");
			soup_message_set_status (message,
						 SOUP_STATUS_NO_CONTENT);
			return;
		} else if (g_ascii_strcasecmp ("clear", command) == 0) {
			dacp_player_cue_clear (dacp_share->priv->player);
			soup_message_set_status (message,
						 SOUP_STATUS_NO_CONTENT);
		} else if (g_ascii_strcasecmp ("play", command) == 0) {
			GNode *cacr;
			gchar *record_query;
			gchar *sort_by;
			GHashTable *records;
			GList *sorted_records;
			GSList *filter_def;
			DMAPDb *db;
			gint index =
				atoi (g_hash_table_lookup (query, "index"));

			g_object_get (share, "db", &db, NULL);
			record_query = g_hash_table_lookup (query, "query");
			filter_def = _dmap_share_build_filter (record_query);
			records = dmap_db_apply_filter (db, filter_def);
			sorted_records = g_hash_table_get_values (records);
			sort_by = g_hash_table_lookup (query, "sort");
			if (g_strcmp0 (sort_by, "album") == 0) {
				sorted_records =
					g_list_sort_with_data (sorted_records,
							       (GCompareDataFunc)
							       daap_record_cmp_by_album,
							       db);
			} else if (sort_by != NULL) {
				g_warning ("Unknown sort column: %s",
					   sort_by);
			}

			dacp_player_cue_play (dacp_share->priv->player,
					      sorted_records, index);

			g_list_free (sorted_records);
			g_hash_table_unref (records);
			dmap_share_free_filter (filter_def);

			cacr = dmap_structure_add (NULL, DMAP_CC_CACR);
			dmap_structure_add (cacr, DMAP_CC_MSTT,
					    DMAP_STATUS_OK);
			dmap_structure_add (cacr, DMAP_CC_MIID, index);

			_dmap_share_message_set_from_dmap_structure (share,
								     message,
								     cacr);
			dmap_structure_destroy (cacr);
		} else {
			g_warning ("Unhandled cue command: %s", command);
			soup_message_set_status (message,
						 SOUP_STATUS_NO_CONTENT);
			return;
		}
	} else {
		g_warning ("Unhandled ctrl-int command: %s", rest_of_path);
		soup_message_set_status (message, SOUP_STATUS_BAD_REQUEST);
	}
}
Exemple #13
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);
}
Exemple #14
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
		 const char *path, GHashTable *query,
		 SoupClientContext *context, gpointer data)
{
	SoupURI *uri = soup_message_get_uri (msg);
	const char *server_protocol = data;

	soup_message_headers_append (msg->response_headers,
				     "X-Handled-By", "server_callback");

	if (!strcmp (path, "*")) {
		debug_printf (1, "    default server_callback got request for '*'!\n");
		errors++;
		soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
		return;
	}

	if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
		return;
	}

	if (!strcmp (path, "/redirect")) {
		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/");
		return;
	}

	if (!strcmp (path, "/alias-redirect")) {
		SoupURI *redirect_uri;
		char *redirect_string;
		const char *redirect_protocol;

		redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol");

		redirect_uri = soup_uri_copy (uri);
		soup_uri_set_scheme (redirect_uri, "foo");
		if (!g_strcmp0 (redirect_protocol, "https"))
			soup_uri_set_port (redirect_uri, ssl_base_uri->port);
		else
			soup_uri_set_port (redirect_uri, base_uri->port);
		soup_uri_set_path (redirect_uri, "/alias-redirected");
		redirect_string = soup_uri_to_string (redirect_uri, FALSE);

		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string);
		g_free (redirect_string);
		soup_uri_free (redirect_uri);
		return;
	} else if (!strcmp (path, "/alias-redirected")) {
		soup_message_set_status (msg, SOUP_STATUS_OK);
		soup_message_headers_append (msg->response_headers,
					     "X-Redirected-Protocol",
					     server_protocol);
		return;
	}

	if (!strcmp (path, "/slow")) {
		soup_server_pause_message (server, msg);
		g_object_set_data (G_OBJECT (msg), "server", server);
		soup_add_timeout (soup_server_get_async_context (server),
				  1000, timeout_finish_message, msg);
	}

	soup_message_set_status (msg, SOUP_STATUS_OK);
	if (!strcmp (uri->host, "foo")) {
		soup_message_set_response (msg, "text/plain",
					   SOUP_MEMORY_STATIC, "foo-index", 9);
		return;
	} else {
		soup_message_set_response (msg, "text/plain",
					   SOUP_MEMORY_STATIC, "index", 5);
		return;
	}
}
Exemple #15
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();
}
static void
gss_adaptive_resource_get_content (GssTransaction * t, GssAdaptive * adaptive)
{
  const char *stream;
  const char *start_time_str;
  const char *bitrate_str;
  guint64 start_time;
  guint64 bitrate;
  gboolean is_init;
  GssAdaptiveLevel *level;
  GssIsomFragment *fragment;
  gboolean ret;

  //GST_ERROR ("content request");

  if (t->query == NULL) {
    gss_transaction_error_not_found (t, "no smooth streaming query");
    return;
  }

  stream = g_hash_table_lookup (t->query, "stream");
  if (stream == NULL) {
    gss_transaction_error_not_found (t, "missing stream parameterr");
    return;
  }
  start_time_str = g_hash_table_lookup (t->query, "start_time");
  if (start_time_str == NULL) {
    gss_transaction_error_not_found (t, "missing start_time parameter");
    return;
  }
  bitrate_str = g_hash_table_lookup (t->query, "bitrate");
  if (bitrate_str == NULL) {
    gss_transaction_error_not_found (t, "missing bitrate parameter");
    return;
  }

  ret = parse_guint64 (bitrate_str, &bitrate);
  if (!ret) {
    gss_transaction_error_not_found (t, "bitrate is not a number");
    return;
  }

  if (strcmp (start_time_str, "init") == 0) {
    is_init = TRUE;
    start_time = 0;
  } else {
    is_init = FALSE;
    ret = parse_guint64 (start_time_str, &start_time);
    if (!ret) {
      gss_transaction_error_not_found (t,
          "start_time is not a number or \"init\"");
      return;
    }
  }

  if (strcmp (stream, "audio") != 0 && strcmp (stream, "video") != 0) {
    gss_transaction_error_not_found (t, "stream is not \"audio\" or \"video\"");
    return;
  }

  level = gss_adaptive_get_level (adaptive, (stream[0] == 'v'), bitrate);
  if (level == NULL) {
    gss_transaction_error_not_found (t,
        "level not found for stream and bitrate");
    return;
  }

  soup_message_headers_replace (t->msg->response_headers, "Content-Type",
      (stream[0] == 'v') ? "video/mp4" : "audio/mp4");

  if (is_init) {
    soup_message_body_append (t->msg->response_body, SOUP_MEMORY_COPY,
        level->track->ccff_header_data, level->track->ccff_header_size);
  } else {
    GssAdaptiveQuery *query;

    fragment = gss_isom_track_get_fragment_by_timestamp (level->track,
        start_time);
    if (fragment == NULL) {
      gss_transaction_error_not_found (t, "fragment not found for start_time");
      return;
    }
    //GST_ERROR ("frag %s %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT,
    //    level->filename, fragment->offset, fragment->size);

    soup_server_pause_message (t->soupserver, t->msg);

    query = g_malloc0 (sizeof (GssAdaptiveQuery));
    query->adaptive = adaptive;
    query->level = level;
    query->fragment = fragment;

    gss_transaction_process_async (t, gss_adaptive_async_assemble_chunk,
        gss_adaptive_async_assemble_chunk_finish, query);
  }
}
static void
gss_adaptive_resource_get_dash_range_fragment (GssTransaction * t,
    GssAdaptive * adaptive, const char *path)
{
  gboolean have_range;
  SoupRange *ranges;
  int n_ranges;
  int index;
  GssAdaptiveLevel *level;
  gsize start, end;

  /* skip over content/ */
  path += 8;

  if (path[0] != 'a' && path[0] != 'v') {
    GST_ERROR ("bad path: %s", path);
    return;
  }
  index = strtoul (path + 1, NULL, 10);

  level = NULL;
  if (path[0] == 'a') {
    if (index < adaptive->n_audio_levels) {
      level = &adaptive->audio_levels[index];
    }
  } else {
    if (index < adaptive->n_video_levels) {
      level = &adaptive->video_levels[index];
    }
  }

  if (level == NULL) {
    GST_ERROR ("bad level: %c%d from path %s", path[0], index, path);
    return;
  }

  if (t->msg->method == SOUP_METHOD_HEAD) {
    GST_DEBUG ("%s: HEAD", path);
    soup_message_headers_set_content_length (t->msg->response_headers,
        level->track->dash_size);
    return;
  }

  have_range = soup_message_headers_get_ranges (t->msg->request_headers,
      level->track->dash_size, &ranges, &n_ranges);

  if (have_range) {
    if (n_ranges != 1) {
      GST_ERROR ("too many ranges");
    }
    start = ranges[0].start;
    end = ranges[0].end + 1;
  } else {
    start = 0;
    end = level->track->dash_size;
  }
  GST_DEBUG ("%s: range: %ld-%ld", path, start, end);
  t->start = start;
  t->end = end;

  if (have_range) {
    soup_message_headers_set_content_range (t->msg->response_headers,
        ranges[0].start, ranges[0].end, level->track->dash_size);

    soup_message_set_status (t->msg, SOUP_STATUS_PARTIAL_CONTENT);

    soup_message_headers_free_ranges (t->msg->response_headers, ranges);
  } else {
    soup_message_set_status (t->msg, SOUP_STATUS_OK);
  }

  soup_message_headers_replace (t->msg->response_headers, "Content-Type",
      (path[0] == 'v') ? "video/mp4" : "audio/mp4");

  {
    GssAdaptiveQuery *query;

    soup_server_pause_message (t->soupserver, t->msg);

    query = g_malloc0 (sizeof (GssAdaptiveQuery));
    query->adaptive = adaptive;
    query->level = level;

    gss_transaction_process_async (t, gss_adaptive_dash_range_async,
        gss_adaptive_dash_range_async_finish, query);
  }
}
Exemple #18
0
static void
postal_http_handle_v1_users_user_badge (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;
   JsonNode *node = NULL;
   GError *error = NULL;
   guint badge;

   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");

   if (message->method == SOUP_METHOD_PUT) {
      if (!(node = postal_http_parse_body(message, &error)) ||
          !JSON_NODE_HOLDS_VALUE(node)) {
         if (!error) {
            error = g_error_new(JSON_PARSER_ERROR,
                                JSON_PARSER_ERROR_UNKNOWN,
                                _("JSON must contain integer."));
         }
         postal_http_reply_error(http, message, error);
         GOTO(cleanup);
      }
      badge = json_node_get_int(node);
      g_object_set_data(G_OBJECT(message), "http", http);
      postal_service_set_user_badge(http->priv->service,
                                    user,
                                    badge,
                                    NULL,
                                    postal_http_set_user_badge_cb,
                                    g_object_ref(message));
      soup_server_pause_message(server, message);
      EXIT;
   }

   soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);

cleanup:
   g_clear_error(&error);
   if (node) {
      json_node_free(node);
   }

   EXIT;
}
Exemple #19
0
static void
postal_http_handle_v1_notify (UrlRouter         *router,
                              SoupServer        *server,
                              SoupMessage       *message,
                              const gchar       *path,
                              GHashTable        *params,
                              GHashTable        *query,
                              SoupClientContext *client,
                              gpointer           user_data)
{
   PostalNotification *notif;
   const gchar *collapse_key = NULL;
   const gchar *str;
   PostalHttp *http = user_data;
   JsonObject *aps;
   JsonObject *c2dm;
   JsonObject *gcm;
   JsonObject *object;
   JsonArray *devices;
   JsonArray *users;
   GPtrArray *devices_ptr;
   GPtrArray *users_ptr;
   JsonNode *node;
   GError *error = NULL;
   guint count;
   guint i;

   g_assert(SOUP_IS_SERVER(server));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(path);
   g_assert(client);
   g_assert(POSTAL_IS_HTTP(http));

   if (message->method != SOUP_METHOD_POST) {
      soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);
      return;
   }

   soup_server_pause_message(server, message);

   if (!(node = postal_http_parse_body(message, &error))) {
      postal_http_reply_error(http, message, error);
      g_error_free(error);
      return;
   }

   if (!JSON_NODE_HOLDS_OBJECT(node) ||
       !(object = json_node_get_object(node)) ||
       !json_object_has_member(object, "aps") ||
       !(node = json_object_get_member(object, "aps")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(aps = json_object_get_object_member(object, "aps")) ||
       !json_object_has_member(object, "c2dm") ||
       !(node = json_object_get_member(object, "c2dm")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(c2dm = json_object_get_object_member(object, "c2dm")) ||
       !json_object_has_member(object, "gcm") ||
       !(node = json_object_get_member(object, "gcm")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(gcm = json_object_get_object_member(object, "gcm")) ||
       !json_object_has_member(object, "users") ||
       !(node = json_object_get_member(object, "users")) ||
       !JSON_NODE_HOLDS_ARRAY(node) ||
       !(users = json_object_get_array_member(object, "users")) ||
       !json_object_has_member(object, "devices") ||
       !(node = json_object_get_member(object, "devices")) ||
       !JSON_NODE_HOLDS_ARRAY(node) ||
       !(devices = json_object_get_array_member(object, "devices"))) {
      error = g_error_new(postal_json_error_quark(), 0,
                          "Missing or invalid fields in JSON payload.");
      postal_http_reply_error(http, message, error);
      json_node_free(node);
      g_error_free(error);
      return;
   }

   if (json_object_has_member(object, "collapse_key") &&
       (node = json_object_get_member(object, "collapse_key")) &&
       JSON_NODE_HOLDS_VALUE(node)) {
      collapse_key = json_node_get_string(node);
   }

   notif = g_object_new(POSTAL_TYPE_NOTIFICATION,
                        "aps", aps,
                        "c2dm", c2dm,
                        "collapse-key", collapse_key,
                        "gcm", gcm,
                        NULL);

   count = json_array_get_length(users);
   users_ptr = g_ptr_array_sized_new(count);
   for (i = 0; i < count; i++) {
      node = json_array_get_element(users, i);
      if (json_node_get_value_type(node) == G_TYPE_STRING) {
         str = json_node_get_string(node);
         g_ptr_array_add(users_ptr, (gchar *)str);
      }
   }
   g_ptr_array_add(users_ptr, NULL);

   count = json_array_get_length(devices);
   devices_ptr = g_ptr_array_sized_new(count);
   g_ptr_array_set_free_func(devices_ptr, g_free);
   for (i = 0; i < count; i++) {
      node = json_array_get_element(devices, i);
      if (json_node_get_value_type(node) == G_TYPE_STRING) {
         str = json_node_get_string(node);
         g_ptr_array_add(devices_ptr, g_strdup(str));
      }
   }
   g_ptr_array_add(devices_ptr, NULL);

   postal_service_notify(http->priv->service,
                         notif,
                         (gchar **)users_ptr->pdata,
                         (gchar **)devices_ptr->pdata,
                         NULL, /* TODO: Cancellable/Timeout? */
                         postal_http_notify_cb,
                         g_object_ref(message));

   g_ptr_array_unref(devices_ptr);
   g_ptr_array_unref(users_ptr);
   json_node_free(node);
   g_object_unref(notif);
}