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