示例#1
0
SnraServerClient *
snra_server_client_new (SoupServer * soup, SoupMessage * msg,
                        SoupClientContext * context)
{
    SnraServerClient *client = g_object_new (SNRA_TYPE_SERVER_CLIENT, NULL);
    const gchar *accept_challenge;
    gchar *accept_reply;

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

    if (!is_websocket_client (client)) {
        client->type = SNRA_SERVER_CLIENT_CHUNKED;
        client->need_body_complete = TRUE;

        soup_message_headers_set_encoding (msg->response_headers,
                                           SOUP_ENCODING_CHUNKED);
        soup_message_set_status (msg, SOUP_STATUS_OK);
        return client;
    }

    /* Otherwise, it's a websocket client */
    client->type = SNRA_SERVER_CLIENT_WEBSOCKET;
    client->need_body_complete = FALSE;

    client->socket = soup_client_context_get_socket (context);
    client->in_bufptr = client->in_buf = g_new0 (gchar, 1024);
    client->in_bufsize = 1024;
    client->in_bufavail = 0;

    accept_challenge =
        soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Key");
    accept_reply = calc_websocket_challenge_reply (accept_challenge);

    soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_EOF);

    soup_message_set_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS);
    soup_message_headers_replace (msg->response_headers, "Upgrade", "websocket");
    soup_message_headers_replace (msg->response_headers, "Connection", "Upgrade");
    soup_message_headers_replace (msg->response_headers, "Sec-WebSocket-Accept",
                                  accept_reply);
    soup_message_headers_replace (msg->response_headers, "Sec-WebSocket-Protocol",
                                  "aurena");

    g_free (accept_reply);

    client->wrote_info_sig = g_signal_connect (msg, "wrote-informational",
                             G_CALLBACK (snra_server_client_wrote_headers), client);

    return client;
}
示例#2
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);
}
示例#3
0
/* For real request testing */
static void
server_callback(SoupServer* server, SoupMessage* msg,
                const char* path, GHashTable* query,
                SoupClientContext* context, gpointer data)
{
    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 (g_str_equal(path, "/test_loading_status") || g_str_equal(path, "/test_loading_status2"))
        soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
    else if (g_str_equal(path, "/test_load_error")) {
        soup_message_set_status(msg, SOUP_STATUS_CANT_CONNECT);
    } else if (g_str_equal(path, "/test_loading_cancelled")) {
        soup_message_headers_set_encoding(msg->response_headers, SOUP_ENCODING_CHUNKED);
        soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
        soup_server_unpause_message(server, msg);
        return;
    }

    soup_message_body_complete(msg->response_body);
}
示例#4
0
static void
send_chunked_file (SoupServer * server, SoupMessage * message,
		   DPAPRecord * record, guint64 filesize)
{
	GInputStream *stream;
	const char *location;
	GError *error = NULL;
	ChunkData *cd = g_new (ChunkData, 1);

	g_object_get (record, "location", &location, NULL);

	cd->server = server;

	stream = G_INPUT_STREAM (dpap_record_read (record, &error));

	if (error != NULL) {
		g_warning ("Couldn't open %s: %s.", location, error->message);
		g_error_free (error);
		soup_message_set_status (message,
					 SOUP_STATUS_INTERNAL_SERVER_ERROR);
		g_free (cd);
		return;
	}

	cd->stream = stream;

	if (cd->stream == NULL) {
		g_warning ("Could not set up input stream");
		g_free (cd);
		return;
	}

	soup_message_headers_set_encoding (message->response_headers,
					   SOUP_ENCODING_CONTENT_LENGTH);
	soup_message_headers_set_content_length (message->response_headers,
						 filesize);

	soup_message_headers_append (message->response_headers, "Connection",
				     "Close");
	soup_message_headers_append (message->response_headers,
				     "Content-Type",
				     "application/x-dmap-tagged");

	g_signal_connect (message, "wrote_headers",
			  G_CALLBACK (dmap_write_next_chunk), cd);
	g_signal_connect (message, "wrote_chunk",
			  G_CALLBACK (dmap_write_next_chunk), cd);
	g_signal_connect (message, "finished",
			  G_CALLBACK (dmap_chunked_message_finished), cd);
	/* NOTE: cd g_free'd by chunked_message_finished(). */
}
示例#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);
}
示例#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);
  }
}
示例#7
0
static void
vod_resource_chunked (GssTransaction * t)
{
  GssProgram *program = (GssProgram *) t->resource->priv;
  GssVOD *vod;
  char *chunk;
  int len;
  char *s;

  vod = g_malloc0 (sizeof (GssVOD));
  vod->msg = t->msg;
  vod->client = t->client;
  vod->server = t->server;

  s = g_strdup_printf ("%s/%s", t->server->archive_dir,
      GSS_OBJECT_NAME (program));
  vod->fd = open (s, O_RDONLY);
  if (vod->fd < 0) {
    GST_WARNING_OBJECT (program, "file not found %s", s);
    g_free (s);
    g_free (vod);
    soup_message_set_status (t->msg, SOUP_STATUS_NOT_FOUND);
    return;
  }
  g_free (s);

  soup_message_set_status (t->msg, SOUP_STATUS_OK);

  soup_message_headers_set_encoding (t->msg->response_headers,
      SOUP_ENCODING_CHUNKED);

  chunk = g_malloc (SIZE);
  len = read (vod->fd, chunk, 65536);
  if (len < 0) {
    GST_ERROR_OBJECT (program, "read error");
  }

  soup_message_body_append (t->msg->response_body, SOUP_MEMORY_TAKE, chunk,
      len);

  g_signal_connect (t->msg, "wrote-chunk", G_CALLBACK (vod_wrote_chunk), vod);
  g_signal_connect (t->msg, "finished", G_CALLBACK (vod_finished), vod);

}
示例#8
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);
}
static void
restarted_streaming (SoupMessage *msg, gpointer user_data)
{
	PutTestData *ptd = user_data;

	debug_printf (2, "  --restarting--\n");

	/* We're streaming, and we had to restart. So the data need
	 * to be regenerated.
	 */
	setup_request_body (ptd);

	/* The 302 redirect will turn it into a GET request and
	 * reset the body encoding back to "NONE". Fix that.
	 */
	soup_message_headers_set_encoding (msg->request_headers,
					   SOUP_ENCODING_CHUNKED);
	msg->method = SOUP_METHOD_PUT;
}
示例#10
0
static void
restarted_streaming_hack (SoupMessage *msg, gpointer user_data)
{
	PutTestData *ptd = user_data;

	/* We're streaming, and we had to restart. So the data need
	   to be regenerated. That's the *point* of this test; we don't
	   *want* it to accumulate in the request body */
	make_put_chunk (&ptd->chunks[0], "one\r\n");
	make_put_chunk (&ptd->chunks[1], "two\r\n");
	make_put_chunk (&ptd->chunks[2], "three\r\n");
	ptd->next = ptd->nwrote = ptd->nfreed = 0;

	debug_printf (2, "  truncating request body on restart\n");
	soup_message_body_truncate (msg->request_body);

	/* The redirect will turn it into a GET request. Fix that... */
	soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED);
	msg->method = SOUP_METHOD_PUT;
}
static void
do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags)
{
	SoupURI *uri = base_uri;
	PutTestData ptd;
	SoupMessage *msg;
	const char *client_md5, *server_md5;
	GChecksum *check;
	int i, length;

	debug_printf (1, "PUT");
	if (flags & HACKY_STREAMING)
		debug_printf (1, " w/ hacky streaming");
	else if (flags & PROPER_STREAMING)
		debug_printf (1, " w/ proper streaming");
	if (flags & RESTART) {
		debug_printf (1, " and restart");
		uri = soup_uri_copy (base_uri);
		soup_uri_set_path (uri, "/redirect");
	}
	debug_printf (1, "\n");

	ptd.session = session;
	setup_request_body (&ptd);
	ptd.streaming = flags & (HACKY_STREAMING | PROPER_STREAMING);

	check = g_checksum_new (G_CHECKSUM_MD5);
	length = 0;
	for (i = 0; i < 3; i++) {
		g_checksum_update (check, (guchar *)ptd.chunks[i]->data,
				   ptd.chunks[i]->length);
		length += ptd.chunks[i]->length;
	}
	client_md5 = g_checksum_get_string (check);

	msg = soup_message_new_from_uri ("PUT", uri);
	soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED);
	soup_message_body_set_accumulate (msg->request_body, FALSE);
	soup_message_set_chunk_allocator (msg, error_chunk_allocator, NULL, NULL);
	if (flags & HACKY_STREAMING) {
		g_signal_connect (msg, "wrote_chunk",
				  G_CALLBACK (write_next_chunk_streaming_hack), &ptd);
		if (flags & RESTART) {
			g_signal_connect (msg, "restarted",
					  G_CALLBACK (restarted_streaming_hack), &ptd);
		}
	} else {
		g_signal_connect (msg, "wrote_chunk",
				  G_CALLBACK (write_next_chunk), &ptd);
	}

	if (flags & PROPER_STREAMING) {
		soup_message_set_flags (msg, SOUP_MESSAGE_CAN_REBUILD);
		if (flags & RESTART) {
			g_signal_connect (msg, "restarted",
					  G_CALLBACK (restarted_streaming), &ptd);
		}
	}

	g_signal_connect (msg, "wrote_headers",
			  G_CALLBACK (write_next_chunk), &ptd);
	g_signal_connect (msg, "wrote_body_data",
			  G_CALLBACK (wrote_body_data), &ptd);
	soup_session_send_message (session, msg);

	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
		debug_printf (1, "  message failed: %d %s\n",
			      msg->status_code, msg->reason_phrase);
		errors++;
	}

	if (msg->request_body->data) {
		debug_printf (1, "  msg->request_body set!\n");
		errors++;
	}
	if (msg->request_body->length != length || length != ptd.nwrote) {
		debug_printf (1, "  sent length mismatch: %d vs %d vs %d\n",
			      (int)msg->request_body->length, length, ptd.nwrote);
		errors++;
	}

	server_md5 = soup_message_headers_get_one (msg->response_headers,
						   "Content-MD5");
	if (!server_md5 || strcmp (client_md5, server_md5) != 0) {
		debug_printf (1, "  client/server data mismatch: %s vs %s\n",
			      client_md5, server_md5 ? server_md5 : "(null)");
		errors++;
	}

	g_object_unref (msg);
	g_checksum_free (check);

	if (uri != base_uri)
		soup_uri_free (uri);
}
示例#12
0
static void
redirect_handler (SoupMessage *msg, gpointer user_data)
{
	SoupSession *session = user_data;
	const char *new_loc;
	SoupURI *new_uri;

	new_loc = soup_message_headers_get_one (msg->response_headers,
						"Location");
	g_return_if_fail (new_loc != NULL);

	if (msg->status_code == SOUP_STATUS_SEE_OTHER ||
	    (msg->status_code == SOUP_STATUS_FOUND &&
	     !SOUP_METHOD_IS_SAFE (msg->method))) {
		/* Redirect using a GET */
		g_object_set (msg,
			      SOUP_MESSAGE_METHOD, SOUP_METHOD_GET,
			      NULL);
		soup_message_set_request (msg, NULL,
					  SOUP_MEMORY_STATIC, NULL, 0);
		soup_message_headers_set_encoding (msg->request_headers,
						   SOUP_ENCODING_NONE);
	} else if (msg->status_code == SOUP_STATUS_MOVED_PERMANENTLY ||
		   msg->status_code == SOUP_STATUS_TEMPORARY_REDIRECT ||
		   msg->status_code == SOUP_STATUS_FOUND) {
		/* Don't redirect non-safe methods */
		if (!SOUP_METHOD_IS_SAFE (msg->method))
			return;
	} else {
		/* Three possibilities:
		 *
		 *   1) This was a non-3xx response that happened to
		 *      have a "Location" header
		 *   2) It's a non-redirecty 3xx response (300, 304,
		 *      305, 306)
		 *   3) It's some newly-defined 3xx response (308+)
		 *
		 * We ignore all of these cases. In the first two,
		 * redirecting would be explicitly wrong, and in the
		 * last case, we have no clue if the 3xx response is
		 * supposed to be redirecty or non-redirecty. Plus,
		 * 2616 says unrecognized status codes should be
		 * treated as the equivalent to the x00 code, and we
		 * don't redirect on 300, so therefore we shouldn't
		 * redirect on 308+ either.
		 */
		return;
	}

	/* Location is supposed to be an absolute URI, but some sites
	 * are lame, so we use soup_uri_new_with_base().
	 */
	new_uri = soup_uri_new_with_base (soup_message_get_uri (msg), new_loc);
	if (!new_uri) {
		soup_message_set_status_full (msg,
					      SOUP_STATUS_MALFORMED,
					      "Invalid Redirect URL");
		return;
	}

	soup_message_set_uri (msg, new_uri);
	soup_uri_free (new_uri);

	soup_session_requeue_message (session, msg);
}
示例#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);
}
示例#14
0
static void
server_callback (SoupServer *server, SoupMessage *msg,
		 const char *path, GHashTable *query,
		 SoupClientContext *context, gpointer data)
{
	const char *accept_encoding, *options;
	GSList *codings;
	char *file = NULL, *contents;
	gsize length;

	options = soup_message_headers_get_one (msg->request_headers,
						"X-Test-Options");
	if (!options)
		options = "";

	accept_encoding = soup_message_headers_get_list (msg->request_headers,
							 "Accept-Encoding");
	if (accept_encoding && !soup_header_contains (options, "force-encode"))
		codings = soup_header_parse_quality_list (accept_encoding, NULL);
	else
		codings = NULL;

	if (codings) {
		gboolean claim_deflate, claim_gzip;
		const char *file_path = NULL, *encoding = NULL;

		claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL;
		claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL;

		if (claim_gzip && (!claim_deflate ||
				   (!soup_header_contains (options, "prefer-deflate-zlib") &&
				    !soup_header_contains (options, "prefer-deflate-raw")))) {
			file_path = SRCDIR "/resources%s.gz";
			encoding = "gzip";
		} else if (claim_deflate) {
			if (soup_header_contains (options, "prefer-deflate-raw")) {
				file_path = SRCDIR "/resources%s.raw";
				encoding = "deflate";
			} else {
				file_path = SRCDIR "/resources%s.zlib";
				encoding = "deflate";
			}
		}
		if (file_path && encoding) {
			file = g_strdup_printf (file_path, path);
			if (g_file_test (file, G_FILE_TEST_EXISTS)) {
				soup_message_headers_append (msg->response_headers,
							     "Content-Encoding",
							     encoding);
			} else {
				g_free (file);
				file = NULL;
			}
		}
	}

	soup_header_free_list (codings);

	if (!file)
		file = g_strdup_printf (SRCDIR "/resources%s", path);
	if (!g_file_get_contents (file, &contents, &length, NULL)) {
		/* If path.gz exists but can't be read, we'll send back
		 * the error with "Content-Encoding: gzip" but there's
		 * no body, so, eh.
		 */
		g_free (file);
		soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
		return;
	}
	g_free (file);

	if (soup_header_contains (options, "force-encode")) {
		const gchar *encoding = "gzip";

		if (soup_header_contains (options, "prefer-deflate-zlib") ||
		    soup_header_contains (options, "prefer-deflate-raw"))
			encoding = "deflate";

		soup_message_headers_replace (msg->response_headers,
					      "Content-Encoding",
					      encoding);
	}

	/* Content-Type matches the "real" format, not the sent format */
	if (g_str_has_suffix (path, ".gz")) {
		soup_message_headers_append (msg->response_headers,
					     "Content-Type",
					     "application/gzip");
	} else {
		soup_message_headers_append (msg->response_headers,
					     "Content-Type",
					     "text/plain");
	}

	soup_message_set_status (msg, SOUP_STATUS_OK);
	soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED);

	if (!soup_header_contains (options, "empty")) {
		soup_message_body_append (msg->response_body,
					  SOUP_MEMORY_TAKE, contents, length);
	} else
		g_free (contents);

	if (soup_header_contains (options, "trailing-junk")) {
		soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY,
					  options, strlen (options));
	}
	soup_message_body_complete (msg->response_body);
}
示例#15
0
static void
send_chunked_file (SoupServer * server, SoupMessage * message,
		   DAAPRecord * record, guint64 filesize, guint64 offset,
		   const gchar * transcode_mimetype)
{
	gchar *format = NULL;
	gchar *location = NULL;
	GInputStream *stream = NULL;
	gboolean has_video;
	GError *error = NULL;
	ChunkData *cd = NULL;

	cd = g_new (ChunkData, 1);
	if (NULL == cd) {
		g_warning ("Error allocating chunk\n");
		goto _error;
	}

	g_object_get (record, "location", &location, "has-video", &has_video, NULL);
	if (NULL == location) {
		g_warning ("Error getting location from record\n");
		goto _error;
	}

	/* FIXME: This crashes on powerpc-440fp-linux-gnu:
	 * g_debug ("Sending %s chunked from offset %" G_GUINT64_FORMAT ".", location, offset);
	 */

	cd->server = server;

	stream = G_INPUT_STREAM (daap_record_read (record, &error));
	if (error != NULL) {
		g_warning ("Couldn't open %s: %s.", location, error->message);
		goto _error;
	}

	g_object_get (record, "format", &format, NULL);
	if (NULL == format) {
		g_warning ("Error getting format from record\n");
		goto _error;
	}

	// Not presently transcoding videos (see also same comments elsewhere).
	if (should_transcode (format, has_video, transcode_mimetype)) {
#ifdef HAVE_GSTREAMERAPP
		cd->stream = dmap_gst_input_stream_new (transcode_mimetype, stream);
#else
		g_warning ("Transcode format %s not supported", transcode_mimetype);
		cd->stream = stream;
#endif /* HAVE_GSTREAMERAPP */
	} else {
		g_debug ("Not transcoding %s", location);
		cd->stream = stream;
	}

	if (cd->stream == NULL) {
		g_warning ("Could not set up input stream");
		goto _error;
	}

	if (offset != 0) {
		if (g_seekable_seek (G_SEEKABLE (cd->stream), offset, G_SEEK_SET, NULL, &error) == FALSE) {
			g_warning ("Error seeking: %s.", error->message);
			goto _error;
		}
		filesize -= offset;
	}

	/* Free memory after each chunk sent out over network. */
	soup_message_body_set_accumulate (message->response_body, FALSE);

	if (! should_transcode (format, has_video, transcode_mimetype)) {
	        /* NOTE: iTunes seems to require this or it stops reading 
	         * video data after about 2.5MB. Perhaps this is so iTunes
	         * knows how much data to buffer.
	         */
		g_debug ("Using HTTP 1.1 content length encoding.");
		soup_message_headers_set_encoding (message->response_headers, SOUP_ENCODING_CONTENT_LENGTH);

	        /* NOTE: iTunes 8 (and other versions?) will not seek
	         * properly without a Content-Length header.
	         */
		g_debug ("Content length is %" G_GUINT64_FORMAT ".", filesize);
		soup_message_headers_set_content_length (message->response_headers, filesize);
	} else if (soup_message_get_http_version (message) == SOUP_HTTP_1_0) {
		/* NOTE: Roku clients support only HTTP 1.0. */
#ifdef HAVE_ENCODING_EOF
		g_debug ("Using HTTP 1.0 encoding.");
		soup_message_headers_set_encoding (message->response_headers, SOUP_ENCODING_EOF);
#else
		g_warning ("Received HTTP 1.0 request, but not built with HTTP 1.0 support");
		soup_message_headers_set_encoding (message->response_headers, SOUP_ENCODING_CHUNKED);
#endif
	} else {
		/* NOTE: Can not provide Content-Length when performing
		 * real-time transcoding.
		 */
		g_debug ("Using HTTP 1.1 chunked encoding.");
		soup_message_headers_set_encoding (message->response_headers, SOUP_ENCODING_CHUNKED);
	}

	soup_message_headers_append (message->response_headers, "Connection",
				     "Close");
	soup_message_headers_append (message->response_headers,
				     "Content-Type",
				     "application/x-dmap-tagged");

	g_signal_connect (message, "wrote_headers",
			  G_CALLBACK (dmap_write_next_chunk), cd);
	g_signal_connect (message, "wrote_chunk",
			  G_CALLBACK (dmap_write_next_chunk), cd);
	g_signal_connect (message, "finished",
			  G_CALLBACK (dmap_chunked_message_finished), cd);
	/* NOTE: cd g_free'd by chunked_message_finished(). */

	return;
_error:
	soup_message_set_status (message, SOUP_STATUS_INTERNAL_SERVER_ERROR);

	if (NULL != cd) {
		g_free (cd);
	}

	if (NULL != format) {
		g_free (format);
	}

	if (NULL != location) {
		g_free (location);
	}

	if (NULL != error) {
		g_error_free (error);
	}
	
	if (NULL != cd->stream) {
		g_input_stream_close (cd->stream, NULL, NULL);
	}
	
	if (NULL != stream) {
		g_input_stream_close (cd->stream, NULL, NULL);
	}

	return;
}
示例#16
0
static void
do_request_test (SoupSession *session, SoupURI *base_uri, int test)
{
	SoupURI *uri = base_uri;
	PutTestData ptd;
	SoupMessage *msg;
	const char *client_md5, *server_md5;
	GChecksum *check;
	int i, length;
	gboolean streaming = FALSE;

	switch (test) {
	case 0:
		debug_printf (1, "PUT\n");
		break;

	case 1:
		debug_printf (1, "PUT w/ streaming\n");
		streaming = TRUE;
		break;

	case 2:
		debug_printf (1, "PUT w/ streaming and restart\n");
		streaming = TRUE;
		uri = soup_uri_copy (base_uri);
		soup_uri_set_path (uri, "/redirect");
		break;
	}

	ptd.session = session;
	make_put_chunk (&ptd.chunks[0], "one\r\n");
	make_put_chunk (&ptd.chunks[1], "two\r\n");
	make_put_chunk (&ptd.chunks[2], "three\r\n");
	ptd.next = ptd.nwrote = ptd.nfreed = 0;
	ptd.streaming = streaming;

	check = g_checksum_new (G_CHECKSUM_MD5);
	length = 0;
	for (i = 0; i < 3; i++) {
		g_checksum_update (check, (guchar *)ptd.chunks[i]->data,
				   ptd.chunks[i]->length);
		length += ptd.chunks[i]->length;
	}
	client_md5 = g_checksum_get_string (check);

	msg = soup_message_new_from_uri ("PUT", uri);
	soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED);
	soup_message_body_set_accumulate (msg->request_body, FALSE);
	soup_message_set_chunk_allocator (msg, error_chunk_allocator, NULL, NULL);
	if (streaming) {
		g_signal_connect (msg, "wrote_chunk",
				  G_CALLBACK (write_next_chunk_streaming_hack), &ptd);
		g_signal_connect (msg, "restarted",
				  G_CALLBACK (restarted_streaming_hack), &ptd);
	} else {
		g_signal_connect (msg, "wrote_chunk",
				  G_CALLBACK (write_next_chunk), &ptd);
	}
	g_signal_connect (msg, "wrote_headers",
			  G_CALLBACK (write_next_chunk), &ptd);
	g_signal_connect (msg, "wrote_body_data",
			  G_CALLBACK (wrote_body_data), &ptd);
	soup_session_send_message (session, msg);

	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
		debug_printf (1, "  message failed: %d %s\n",
			      msg->status_code, msg->reason_phrase);
		errors++;
	}

	if (msg->request_body->data) {
		debug_printf (1, "  msg->request_body set!\n");
		errors++;
	}
	if (msg->request_body->length != length || length != ptd.nwrote) {
		debug_printf (1, "  sent length mismatch: %d vs %d vs %d\n",
			      (int)msg->request_body->length, length, ptd.nwrote);
		errors++;
	}

	server_md5 = soup_message_headers_get_one (msg->response_headers,
						   "Content-MD5");
	if (!server_md5 || strcmp (client_md5, server_md5) != 0) {
		debug_printf (1, "  client/server data mismatch: %s vs %s\n",
			      client_md5, server_md5 ? server_md5 : "(null)");
		errors++;
	}

	g_object_unref (msg);
	g_checksum_free (check);

	if (uri != base_uri)
		soup_uri_free (uri);
}
示例#17
0
void SoupServer_path_stulist(SoupServer *server, SoupMessage *msg,
		const char *path, GHashTable *query, SoupClientContext *client,
		gpointer user_data)
{

	if(!g_sql_connect_run_query(dbclient,"SELECT * from student",-1))
	{
		soup_message_set_status(msg,SOUP_STATUS_BAD_REQUEST);
		return ;
	}

	HtmlNode * html = htmlnode_new(NULL,"html",NULL);

	htmlnode_new_head(html,"http-equiv=\"content-type\"","content=\"text/html;charset=utf-8\"",NULL);


	GSQLResult * result = g_sql_connect_use_result(dbclient);

	HtmlNode * body = htmlnode_new_body(html,"background=\"eg_bg_06.gif\"",0);

	HtmlNode * body_div = htmlnode_new(body,"div",0);

	HtmlNode * body_div_table = htmlnode_new(body_div,"table",0);

	HtmlNode * tr = htmlnode_new(body_div_table,"tr",0);

	htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s","专业");
	htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s","班级");
	htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s","学号");
	htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s","姓名");

	htmlnode_new(body_div,"br",0);

	if(result) //数据库有内容
	{
		g_object_ref(result);
		tr = htmlnode_new(body_div_table,"tr",0);

		//循环获得每一行
		while(g_sql_result_fetch_row(result))
		{
			//构建页面

			const gchar * ID = g_sql_result_colum_by_name(result,"ID");

			const gchar * name = g_sql_result_colum_by_name(result,"name");

			const gchar * mj = g_sql_result_colum_by_name(result,"mj");

			const gchar * class = g_sql_result_colum_by_name(result,"class");


			htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s",mj);
			htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s",class);
			htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s",ID);
			htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"%s",name);


			//有成绩嘛就显示成绩

			gchar * sql ;
			GSQLResult * res;

			sql = g_strdup_printf("select * from lesson where stuid='%s'",ID);

			g_sql_connect_run_query(dbclient,sql,-1);

			if((res =g_sql_connect_use_result(dbclient)))
			{
				while(g_sql_result_fetch_row(res))
				{
					htmlnode_new_text_printf(htmlnode_new(tr,"td",0),"科目:%s	分数:%s",
							g_sql_result_colum_by_name(res,"name"),g_sql_result_colum_by_name(res,"score"));
				}
				g_object_unref(res);
			}

			g_free(sql);

			tr = htmlnode_new(body_div_table,"tr",0);
		}


		g_object_unref(result);
	}


	soup_message_set_status(msg,SOUP_STATUS_OK);
	soup_message_headers_set_encoding(msg->response_headers,SOUP_ENCODING_CONTENT_LENGTH);

	htmlnode_to_plane_text_and_free(html,
			(htmlnode_appender) soup_message_body_appender, msg->response_body);

	soup_message_body_complete(msg->response_body);
}