summaryrefslogtreecommitdiff
path: root/libsoup/server/soup-server-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/server/soup-server-io.c')
-rw-r--r--libsoup/server/soup-server-io.c473
1 files changed, 317 insertions, 156 deletions
diff --git a/libsoup/server/soup-server-io.c b/libsoup/server/soup-server-io.c
index 4556635f..e94a366e 100644
--- a/libsoup/server/soup-server-io.c
+++ b/libsoup/server/soup-server-io.c
@@ -15,34 +15,115 @@
#include "soup-body-input-stream.h"
#include "soup-body-output-stream.h"
#include "soup-filter-input-stream.h"
-#include "soup-message-private.h"
+#include "soup-server-message-private.h"
#include "soup-misc.h"
#include "soup-socket-private.h"
+struct _SoupServerMessageIOData {
+ SoupMessageIOData base;
+
+ GBytes *write_chunk;
+ goffset write_body_offset;
+
+ GSource *unpause_source;
+};
+
#define RESPONSE_BLOCK_SIZE 8192
#define HEADER_SIZE_LIMIT (64 * 1024)
+void
+soup_server_message_io_data_free (SoupServerMessageIOData *io)
+{
+ if (!io)
+ return;
+
+ soup_message_io_data_cleanup (&io->base);
+
+ if (io->unpause_source) {
+ g_source_destroy (io->unpause_source);
+ g_source_unref (io->unpause_source);
+ io->unpause_source = NULL;
+ }
+
+ g_clear_pointer (&io->write_chunk, g_bytes_unref);
+
+ g_slice_free (SoupServerMessageIOData, io);
+}
+
+void
+soup_server_message_io_finished (SoupServerMessage *msg)
+{
+ SoupServerMessageIOData *io;
+ SoupMessageIOCompletionFn completion_cb;
+ gpointer completion_data;
+ SoupMessageIOCompletion completion;
+
+ io = soup_server_message_get_io_data (msg);
+ if (!io)
+ return;
+
+ completion_cb = io->base.completion_cb;
+ completion_data = io->base.completion_data;
+
+ if ((io->base.read_state >= SOUP_MESSAGE_IO_STATE_FINISHING &&
+ io->base.write_state >= SOUP_MESSAGE_IO_STATE_FINISHING))
+ completion = SOUP_MESSAGE_IO_COMPLETE;
+ else
+ completion = SOUP_MESSAGE_IO_INTERRUPTED;
+
+ g_object_ref (msg);
+ soup_server_message_set_io_data (msg, NULL);
+ if (completion_cb)
+ completion_cb (G_OBJECT (msg), completion, completion_data);
+ g_object_unref (msg);
+}
+
+GIOStream *
+soup_server_message_io_steal (SoupServerMessage *msg)
+{
+ SoupServerMessageIOData *io;
+ SoupMessageIOCompletionFn completion_cb;
+ gpointer completion_data;
+ GIOStream *iostream;
+
+ io = soup_server_message_get_io_data (msg);
+ if (!io || !io->base.iostream)
+ return NULL;
+
+ iostream = g_object_ref (io->base.iostream);
+ completion_cb = io->base.completion_cb;
+ completion_data = io->base.completion_data;
+
+ g_object_ref (msg);
+ soup_server_message_set_io_data (msg, NULL);
+ if (completion_cb)
+ completion_cb (G_OBJECT (msg), SOUP_MESSAGE_IO_STOLEN, completion_data);
+ g_object_unref (msg);
+
+ return iostream;
+}
+
static void
closed_async (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GOutputStream *body_ostream = G_OUTPUT_STREAM (source);
- SoupMessage *msg = user_data;
- SoupMessageIOData *io;
+ SoupServerMessage *msg = user_data;
+ SoupServerMessageIOData *io;
GCancellable *async_wait;
- io = soup_message_get_io_data (msg);
- if (!io || !io->async_wait || io->body_ostream != body_ostream) {
+ io = soup_server_message_get_io_data (msg);
+ if (!io || !io->base.async_wait || io->base.body_ostream != body_ostream) {
g_object_unref (msg);
return;
}
- g_output_stream_close_finish (body_ostream, result, &io->async_error);
- g_clear_object (&io->body_ostream);
+ g_output_stream_close_finish (body_ostream, result, &io->base.async_error);
+ g_clear_object (&io->base.body_ostream);
- async_wait = io->async_wait;
- io->async_wait = NULL;
+ async_wait = io->base.async_wait;
+ io->base.async_wait = NULL;
g_cancellable_cancel (async_wait);
g_object_unref (async_wait);
@@ -76,12 +157,19 @@ closed_async (GObject *source,
*/
static void
-handle_partial_get (SoupMessage *msg)
+handle_partial_get (SoupServerMessage *msg)
{
SoupRange *ranges;
int nranges;
GBytes *full_response;
guint status;
+ SoupMessageHeaders *request_headers;
+ SoupMessageHeaders *response_headers;
+ SoupMessageBody *response_body;
+
+ request_headers = soup_server_message_get_request_headers (msg);
+ response_headers = soup_server_message_get_response_headers (msg);
+ response_body = soup_server_message_get_response_body (msg);
/* Make sure the message is set up right for us to return a
* partial response; it has to be a GET, the status must be
@@ -89,50 +177,50 @@ handle_partial_get (SoupMessage *msg)
* Content), and the SoupServer must have already filled in
* the response body
*/
- if (msg->method != SOUP_METHOD_GET ||
- msg->status_code != SOUP_STATUS_OK ||
- soup_message_headers_get_encoding (msg->response_headers) !=
+ if (soup_server_message_get_method (msg) != SOUP_METHOD_GET ||
+ soup_server_message_get_status (msg, NULL) != SOUP_STATUS_OK ||
+ soup_message_headers_get_encoding (response_headers) !=
SOUP_ENCODING_CONTENT_LENGTH ||
- msg->response_body->length == 0 ||
- !soup_message_body_get_accumulate (msg->response_body))
+ response_body->length == 0 ||
+ !soup_message_body_get_accumulate (response_body))
return;
/* Oh, and there has to have been a valid Range header on the
* request, of course.
*/
- status = soup_message_headers_get_ranges_internal (msg->request_headers,
- msg->response_body->length,
+ status = soup_message_headers_get_ranges_internal (request_headers,
+ response_body->length,
TRUE,
&ranges, &nranges);
if (status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) {
- soup_message_set_status (msg, status);
- soup_message_body_truncate (msg->response_body);
+ soup_server_message_set_status (msg, status, NULL);
+ soup_message_body_truncate (response_body);
return;
} else if (status != SOUP_STATUS_PARTIAL_CONTENT)
return;
- full_response = soup_message_body_flatten (msg->response_body);
+ full_response = soup_message_body_flatten (response_body);
if (!full_response) {
- soup_message_headers_free_ranges (msg->request_headers, ranges);
+ soup_message_headers_free_ranges (request_headers, ranges);
return;
}
- soup_message_set_status (msg, SOUP_STATUS_PARTIAL_CONTENT);
- soup_message_body_truncate (msg->response_body);
+ soup_server_message_set_status (msg, SOUP_STATUS_PARTIAL_CONTENT, NULL);
+ soup_message_body_truncate (response_body);
if (nranges == 1) {
GBytes *range_buf;
/* Single range, so just set Content-Range and fix the body. */
- soup_message_headers_set_content_range (msg->response_headers,
+ soup_message_headers_set_content_range (response_headers,
ranges[0].start,
ranges[0].end,
g_bytes_get_size (full_response));
range_buf = g_bytes_new_from_bytes (full_response,
ranges[0].start,
ranges[0].end - ranges[0].start + 1);
- soup_message_body_append_bytes (msg->response_body, range_buf);
+ soup_message_body_append_bytes (response_body, range_buf);
g_bytes_unref (range_buf);
} else {
SoupMultipart *multipart;
@@ -147,7 +235,7 @@ handle_partial_get (SoupMessage *msg)
*/
multipart = soup_multipart_new ("multipart/byteranges");
- content_type = soup_message_headers_get_one (msg->response_headers,
+ content_type = soup_message_headers_get_one (response_headers,
"Content-Type");
for (i = 0; i < nranges; i++) {
part_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
@@ -169,52 +257,62 @@ handle_partial_get (SoupMessage *msg)
g_bytes_unref (part_body);
}
- soup_multipart_to_message (multipart, msg->response_headers, &body);
- soup_message_body_append_bytes (msg->response_body, body);
+ soup_multipart_to_message (multipart, response_headers, &body);
+ soup_message_body_append_bytes (response_body, body);
g_bytes_unref (body);
soup_multipart_free (multipart);
}
g_bytes_unref (full_response);
- soup_message_headers_free_ranges (msg->request_headers, ranges);
+ soup_message_headers_free_ranges (request_headers, ranges);
}
static void
-write_headers (SoupMessage *msg,
- GString *headers,
- SoupEncoding *encoding)
+write_headers (SoupServerMessage *msg,
+ GString *headers,
+ SoupEncoding *encoding)
{
SoupEncoding claimed_encoding;
SoupMessageHeadersIter iter;
const char *name, *value;
+ guint status_code;
+ const char *reason_phrase;
+ const char *method;
+ SoupMessageHeaders *response_headers;
+ SoupMessageBody *response_body;
- if (msg->status_code == 0)
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ if (soup_server_message_get_status (msg, NULL) == 0)
+ soup_server_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL);
handle_partial_get (msg);
+ status_code = soup_server_message_get_status (msg, &reason_phrase);
+
g_string_append_printf (headers, "HTTP/1.%c %d %s\r\n",
- soup_message_get_http_version (msg) == SOUP_HTTP_1_0 ? '0' : '1',
- msg->status_code, msg->reason_phrase);
-
- claimed_encoding = soup_message_headers_get_encoding (msg->response_headers);
- if ((msg->method == SOUP_METHOD_HEAD ||
- msg->status_code == SOUP_STATUS_NO_CONTENT ||
- msg->status_code == SOUP_STATUS_NOT_MODIFIED ||
- SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) ||
- (msg->method == SOUP_METHOD_CONNECT &&
- SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)))
+ soup_server_message_get_http_version (msg) == SOUP_HTTP_1_0 ? '0' : '1',
+ status_code, reason_phrase);
+
+ method = soup_server_message_get_method (msg);
+ response_headers = soup_server_message_get_response_headers (msg);
+ claimed_encoding = soup_message_headers_get_encoding (response_headers);
+ if ((method == SOUP_METHOD_HEAD ||
+ status_code == SOUP_STATUS_NO_CONTENT ||
+ status_code == SOUP_STATUS_NOT_MODIFIED ||
+ SOUP_STATUS_IS_INFORMATIONAL (status_code)) ||
+ (method == SOUP_METHOD_CONNECT &&
+ SOUP_STATUS_IS_SUCCESSFUL (status_code)))
*encoding = SOUP_ENCODING_NONE;
else
*encoding = claimed_encoding;
+ response_body = soup_server_message_get_response_body (msg);
if (claimed_encoding == SOUP_ENCODING_CONTENT_LENGTH &&
- !soup_message_headers_get_content_length (msg->response_headers)) {
- soup_message_headers_set_content_length (msg->response_headers,
- msg->response_body->length);
+ !soup_message_headers_get_content_length (response_headers)) {
+ soup_message_headers_set_content_length (response_headers,
+ response_body->length);
}
- soup_message_headers_iter_init (&iter, msg->response_headers);
+ soup_message_headers_iter_init (&iter, response_headers);
while (soup_message_headers_iter_next (&iter, &name, &value))
g_string_append_printf (headers, "%s: %s\r\n", name, value);
g_string_append (headers, "\r\n");
@@ -227,13 +325,15 @@ write_headers (SoupMessage *msg,
* socket not writable, write is complete, etc).
*/
static gboolean
-io_write (SoupMessage *msg,
- GCancellable *cancellable,
- GError **error)
+io_write (SoupServerMessage *msg,
+ GCancellable *cancellable,
+ GError **error)
{
- SoupMessageIOData *io = soup_message_get_io_data (msg);
+ SoupServerMessageIOData *server_io = soup_server_message_get_io_data (msg);
+ SoupMessageIOData *io = &server_io->base;
GBytes *chunk;
gssize nwrote;
+ guint status_code;
if (io->async_error) {
g_propagate_error (error, io->async_error);
@@ -248,11 +348,12 @@ io_write (SoupMessage *msg,
switch (io->write_state) {
case SOUP_MESSAGE_IO_STATE_HEADERS:
- if (io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING && msg->status_code == 0) {
+ status_code = soup_server_message_get_status (msg, NULL);
+ if (io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING && status_code == 0) {
/* Client requested "Expect: 100-continue", and
* server did not set an error.
*/
- soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
+ soup_server_message_set_status (msg, SOUP_STATUS_CONTINUE, NULL);
}
if (!io->write_buf->len)
@@ -272,8 +373,9 @@ io_write (SoupMessage *msg,
io->written = 0;
g_string_truncate (io->write_buf, 0);
- if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
- if (msg->status_code == SOUP_STATUS_CONTINUE) {
+ status_code = soup_server_message_get_status (msg, NULL);
+ if (SOUP_STATUS_IS_INFORMATIONAL (status_code)) {
+ if (status_code == SOUP_STATUS_CONTINUE) {
/* Stop and wait for the body now */
io->write_state =
SOUP_MESSAGE_IO_STATE_BLOCKING;
@@ -288,20 +390,20 @@ io_write (SoupMessage *msg,
*/
}
- soup_message_wrote_informational (msg);
+ soup_server_message_wrote_informational (msg);
/* If this was "101 Switching Protocols", then
* the server probably stole the connection...
*/
- if (io != soup_message_get_io_data (msg))
+ if (server_io != soup_server_message_get_io_data (msg))
return FALSE;
- soup_message_cleanup_response (msg);
+ soup_server_message_cleanup_response (msg);
break;
}
if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH)
- io->write_length = soup_message_headers_get_content_length (msg->response_headers);
+ io->write_length = soup_message_headers_get_content_length (soup_server_message_get_response_headers (msg));
io->write_state = SOUP_MESSAGE_IO_STATE_BODY_START;
/* If the client was waiting for a Continue
@@ -311,7 +413,7 @@ io_write (SoupMessage *msg,
if (io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
- soup_message_wrote_headers (msg);
+ soup_server_message_wrote_headers (msg);
break;
case SOUP_MESSAGE_IO_STATE_BODY_START:
@@ -329,51 +431,53 @@ io_write (SoupMessage *msg,
break;
}
- if (!io->write_chunk) {
- io->write_chunk = soup_message_body_get_chunk (msg->response_body, io->write_body_offset);
- if (!io->write_chunk) {
- soup_message_io_pause (msg);
+ if (!server_io->write_chunk) {
+ server_io->write_chunk = soup_message_body_get_chunk (soup_server_message_get_response_body (msg),
+ server_io->write_body_offset);
+ if (!server_io->write_chunk) {
+ soup_server_message_io_pause (msg);
return FALSE;
}
- if (!g_bytes_get_size (io->write_chunk)) {
+ if (!g_bytes_get_size (server_io->write_chunk)) {
io->write_state = SOUP_MESSAGE_IO_STATE_BODY_FLUSH;
break;
}
}
nwrote = g_pollable_stream_write (io->body_ostream,
- (guchar*)g_bytes_get_data (io->write_chunk, NULL) + io->written,
- g_bytes_get_size (io->write_chunk) - io->written,
+ (guchar*)g_bytes_get_data (server_io->write_chunk, NULL) + io->written,
+ g_bytes_get_size (server_io->write_chunk) - io->written,
FALSE,
cancellable, error);
if (nwrote == -1)
return FALSE;
- chunk = g_bytes_new_from_bytes (io->write_chunk, io->written, nwrote);
+ chunk = g_bytes_new_from_bytes (server_io->write_chunk, io->written, nwrote);
io->written += nwrote;
if (io->write_length)
io->write_length -= nwrote;
- if (io->written == g_bytes_get_size (io->write_chunk))
+ if (io->written == g_bytes_get_size (server_io->write_chunk))
io->write_state = SOUP_MESSAGE_IO_STATE_BODY_DATA;
- soup_message_wrote_body_data (msg, chunk);
+ soup_server_message_wrote_body_data (msg, g_bytes_get_size (chunk));
g_bytes_unref (chunk);
break;
case SOUP_MESSAGE_IO_STATE_BODY_DATA:
io->written = 0;
- if (g_bytes_get_size (io->write_chunk) == 0) {
+ if (g_bytes_get_size (server_io->write_chunk) == 0) {
io->write_state = SOUP_MESSAGE_IO_STATE_BODY_FLUSH;
break;
}
- soup_message_body_wrote_chunk (msg->response_body, io->write_chunk);
- io->write_body_offset += g_bytes_get_size (io->write_chunk);
- g_clear_pointer (&io->write_chunk, g_bytes_unref);
+ soup_message_body_wrote_chunk (soup_server_message_get_response_body (msg),
+ server_io->write_chunk);
+ server_io->write_body_offset += g_bytes_get_size (server_io->write_chunk);
+ g_clear_pointer (&server_io->write_chunk, g_bytes_unref);
io->write_state = SOUP_MESSAGE_IO_STATE_BODY;
- soup_message_wrote_chunk (msg);
+ soup_server_message_wrote_chunk (msg);
break;
case SOUP_MESSAGE_IO_STATE_BODY_FLUSH:
@@ -397,7 +501,7 @@ io_write (SoupMessage *msg,
case SOUP_MESSAGE_IO_STATE_BODY_DONE:
io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
- soup_message_wrote_body (msg);
+ soup_server_message_wrote_body (msg);
break;
case SOUP_MESSAGE_IO_STATE_FINISHING:
@@ -435,55 +539,52 @@ parse_connect_authority (const char *req_path)
}
static guint
-parse_headers (SoupMessage *msg,
- char *headers,
- guint headers_len,
- SoupEncoding *encoding,
- SoupSocket *sock,
- GError **error)
+parse_headers (SoupServerMessage *msg,
+ char *headers,
+ guint headers_len,
+ SoupEncoding *encoding,
+ GError **error)
{
char *req_method, *req_path, *url;
SoupHTTPVersion version;
+ SoupSocket *sock;
const char *req_host;
guint status;
SoupURI *uri;
+ SoupMessageHeaders *request_headers;
+
+ request_headers = soup_server_message_get_request_headers (msg);
status = soup_headers_parse_request (headers, headers_len,
- msg->request_headers,
+ request_headers,
&req_method,
&req_path,
&version);
- if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
- if (status == SOUP_STATUS_MALFORMED) {
- g_set_error_literal (error, SOUP_REQUEST_ERROR,
- SOUP_REQUEST_ERROR_PARSING,
- _("Could not parse HTTP request"));
- }
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
return status;
- }
- g_object_set (G_OBJECT (msg),
- SOUP_MESSAGE_METHOD, req_method,
- SOUP_MESSAGE_HTTP_VERSION, version,
- NULL);
+ soup_server_message_set_method (msg, req_method);
+ soup_server_message_set_http_version (msg, version);
g_free (req_method);
/* Handle request body encoding */
- *encoding = soup_message_headers_get_encoding (msg->request_headers);
+ *encoding = soup_message_headers_get_encoding (request_headers);
if (*encoding == SOUP_ENCODING_UNRECOGNIZED) {
- if (soup_message_headers_get_list (msg->request_headers, "Transfer-Encoding"))
+ if (soup_message_headers_get_list (request_headers, "Transfer-Encoding"))
return SOUP_STATUS_NOT_IMPLEMENTED;
else
return SOUP_STATUS_BAD_REQUEST;
}
/* Generate correct context for request */
- req_host = soup_message_headers_get_one (msg->request_headers, "Host");
+ req_host = soup_message_headers_get_one (request_headers, "Host");
if (req_host && strchr (req_host, '/')) {
g_free (req_path);
return SOUP_STATUS_BAD_REQUEST;
}
+ sock = soup_server_message_get_soup_socket (msg);
+
if (!strcmp (req_path, "*") && req_host) {
/* Eg, "OPTIONS * HTTP/1.1" */
url = g_strdup_printf ("%s://%s",
@@ -493,7 +594,7 @@ parse_headers (SoupMessage *msg,
if (uri)
soup_uri_set_path (uri, "*");
g_free (url);
- } else if (msg->method == SOUP_METHOD_CONNECT) {
+ } else if (soup_server_message_get_method (msg) == SOUP_METHOD_CONNECT) {
/* Authority */
uri = parse_connect_authority (req_path);
} else if (*req_path != '/') {
@@ -505,7 +606,7 @@ parse_headers (SoupMessage *msg,
req_host, req_path);
uri = soup_uri_new (url);
g_free (url);
- } else if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) {
+ } else if (soup_server_message_get_http_version (msg) == SOUP_HTTP_1_0) {
/* No Host header, no AbsoluteUri */
GInetSocketAddress *addr = soup_socket_get_local_address (sock);
GInetAddress *inet_addr = g_inet_socket_address_get_address (addr);
@@ -530,7 +631,7 @@ parse_headers (SoupMessage *msg,
return SOUP_STATUS_BAD_REQUEST;
}
- soup_message_set_uri (msg, uri);
+ soup_server_message_set_uri (msg, uri);
soup_uri_free (uri);
return SOUP_STATUS_OK;
@@ -543,27 +644,33 @@ parse_headers (SoupMessage *msg,
* socket not readable, read is complete, etc).
*/
static gboolean
-io_read (SoupMessage *msg,
- GCancellable *cancellable,
- GError **error)
+io_read (SoupServerMessage *msg,
+ GCancellable *cancellable,
+ GError **error)
{
- SoupMessageIOData *io = soup_message_get_io_data (msg);
+ SoupServerMessageIOData *server_io = soup_server_message_get_io_data (msg);
+ SoupMessageIOData *io = &server_io->base;
gssize nread;
guint status;
+ SoupMessageHeaders *request_headers;
switch (io->read_state) {
case SOUP_MESSAGE_IO_STATE_HEADERS:
- if (!soup_message_io_read_headers (msg, io->istream, io->read_header_buf, FALSE, cancellable, error))
+ if (!soup_message_io_data_read_headers (io, FALSE, cancellable, error)) {
+ if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT))
+ soup_server_message_set_status (msg, SOUP_STATUS_MALFORMED, NULL);
return FALSE;
+ }
status = parse_headers (msg,
(char *)io->read_header_buf->data,
io->read_header_buf->len,
&io->read_encoding,
- io->sock,
error);
g_byte_array_set_size (io->read_header_buf, 0);
+ request_headers = soup_server_message_get_request_headers (msg);
+
if (status != SOUP_STATUS_OK) {
/* Either we couldn't parse the headers, or they
* indicated something that would mean we wouldn't
@@ -572,14 +679,13 @@ io_read (SoupMessage *msg,
* reading, and make sure the connection gets
* closed when we're done.
*/
- soup_message_set_status (msg, status);
- soup_message_headers_append (msg->request_headers,
- "Connection", "close");
+ soup_server_message_set_status (msg, status, NULL);
+ soup_message_headers_append (request_headers, "Connection", "close");
io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
break;
}
- if (soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
+ if (soup_message_headers_get_expectations (request_headers) & SOUP_EXPECTATION_CONTINUE) {
/* We must return a status code and response
* headers to the client; either an error to
* be set by a got-headers handler below, or
@@ -591,11 +697,11 @@ io_read (SoupMessage *msg,
io->read_state = SOUP_MESSAGE_IO_STATE_BODY_START;
if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH)
- io->read_length = soup_message_headers_get_content_length (msg->request_headers);
+ io->read_length = soup_message_headers_get_content_length (request_headers);
else
io->read_length = -1;
- soup_message_got_headers (msg);
+ soup_server_message_got_headers (msg);
break;
case SOUP_MESSAGE_IO_STATE_BODY_START:
@@ -618,10 +724,13 @@ io_read (SoupMessage *msg,
FALSE,
cancellable, error);
if (nread > 0) {
- if (msg->request_body) {
+ SoupMessageBody *request_body;
+
+ request_body = soup_server_message_get_request_body (msg);
+ if (request_body) {
GBytes *bytes = g_bytes_new (buf, nread);
- soup_message_body_got_chunk (msg->request_body, bytes);
- soup_message_got_chunk (msg, bytes);
+ soup_message_body_got_chunk (request_body, bytes);
+ soup_server_message_got_chunk (msg, bytes);
g_bytes_unref (bytes);
}
break;
@@ -637,7 +746,7 @@ io_read (SoupMessage *msg,
case SOUP_MESSAGE_IO_STATE_BODY_DONE:
io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
- soup_message_got_body (msg);
+ soup_server_message_got_body (msg);
break;
case SOUP_MESSAGE_IO_STATE_FINISHING:
@@ -653,13 +762,14 @@ io_read (SoupMessage *msg,
}
static gboolean
-io_run_until (SoupMessage *msg,
+io_run_until (SoupServerMessage *msg,
SoupMessageIOState read_state,
SoupMessageIOState write_state,
GCancellable *cancellable,
GError **error)
{
- SoupMessageIOData *io = soup_message_get_io_data (msg);
+ SoupServerMessageIOData *server_io = soup_server_message_get_io_data (msg);
+ SoupMessageIOData *io = &server_io->base;
gboolean progress = TRUE, done;
GError *my_error = NULL;
@@ -674,7 +784,7 @@ io_run_until (SoupMessage *msg,
g_object_ref (msg);
- while (progress && soup_message_get_io_data (msg) == io && !io->paused && !io->async_wait &&
+ while (progress && soup_server_message_get_io_data (msg) == server_io && !io->paused && !io->async_wait &&
(io->read_state < read_state || io->write_state < write_state)) {
if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
@@ -689,7 +799,7 @@ io_run_until (SoupMessage *msg,
g_propagate_error (error, my_error);
g_object_unref (msg);
return FALSE;
- } else if (soup_message_get_io_data (msg) != io) {
+ } else if (soup_server_message_get_io_data (msg) != server_io) {
g_set_error_literal (error, G_IO_ERROR,
G_IO_ERROR_CANCELLED,
_("Operation was cancelled"));
@@ -716,22 +826,22 @@ io_run_until (SoupMessage *msg,
return done;
}
-static void io_run (SoupMessage *msg);
+static void io_run (SoupServerMessage *msg);
static gboolean
-io_run_ready (SoupMessage *msg,
- gpointer user_data)
+io_run_ready (SoupServerMessage *msg,
+ gpointer user_data)
{
io_run (msg);
return FALSE;
}
static void
-io_run (SoupMessage *msg)
+io_run (SoupServerMessage *msg)
{
- SoupMessageIOData *io = soup_message_get_io_data (msg);
+ SoupServerMessageIOData *server_io = soup_server_message_get_io_data (msg);
+ SoupMessageIOData *io = &server_io->base;
GError *error = NULL;
- GCancellable *cancellable;
if (io->io_source) {
g_source_destroy (io->io_source);
@@ -740,58 +850,109 @@ io_run (SoupMessage *msg)
}
g_object_ref (msg);
- cancellable = io->cancellable ? g_object_ref (io->cancellable) : NULL;
-
if (io_run_until (msg,
SOUP_MESSAGE_IO_STATE_DONE,
SOUP_MESSAGE_IO_STATE_DONE,
- cancellable, &error)) {
- soup_message_io_finished (msg);
+ NULL, &error)) {
+ soup_server_message_io_finished (msg);
} else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
g_clear_error (&error);
- io->io_source = soup_message_io_get_source (msg, NULL, io_run_ready, msg);
+ io->io_source = soup_message_io_data_get_source (io, G_OBJECT (msg), NULL,
+ (SoupMessageIOSourceFunc)io_run_ready,
+ NULL);
g_source_attach (io->io_source, io->async_context);
} else {
- if (soup_message_get_io_data (msg) == io) {
- if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code) &&
+ if (soup_server_message_get_io_data (msg) == server_io) {
+ if (!SOUP_STATUS_IS_TRANSPORT_ERROR (soup_server_message_get_status (msg, NULL)) &&
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
+ soup_server_message_set_status (msg, SOUP_STATUS_IO_ERROR, NULL);
}
- soup_message_io_finished (msg);
+ soup_server_message_io_finished (msg);
}
g_error_free (error);
}
-
g_object_unref (msg);
- g_clear_object (&cancellable);
}
void
-soup_message_read_request (SoupMessage *msg,
- SoupSocket *sock,
- SoupMessageCompletionFn completion_cb,
- gpointer user_data)
+soup_server_message_read_request (SoupServerMessage *msg,
+ SoupMessageIOCompletionFn completion_cb,
+ gpointer user_data)
{
- SoupMessageIOData *io;
+ SoupServerMessageIOData *io;
+ SoupSocket *sock;
- io = g_slice_new0 (SoupMessageIOData);
- io->completion_cb = completion_cb;
- io->completion_data = user_data;
+ io = g_slice_new0 (SoupServerMessageIOData);
+ io->base.completion_cb = completion_cb;
+ io->base.completion_data = user_data;
- io->sock = sock;
- io->iostream = g_object_ref (soup_socket_get_iostream (io->sock));
- io->istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->iostream));
- io->ostream = g_io_stream_get_output_stream (io->iostream);
- io->async_context = g_main_context_ref_thread_default ();
+ sock = soup_server_message_get_soup_socket (msg);
+ io->base.iostream = g_object_ref (soup_socket_get_iostream (sock));
+ io->base.istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->base.iostream));
+ io->base.ostream = g_io_stream_get_output_stream (io->base.iostream);
+ io->base.async_context = g_main_context_ref_thread_default ();
- io->read_header_buf = g_byte_array_new ();
- io->write_buf = g_string_new (NULL);
+ io->base.read_header_buf = g_byte_array_new ();
+ io->base.write_buf = g_string_new (NULL);
- io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
- io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
+ io->base.read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
+ io->base.write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
- soup_message_set_io_data (msg, io);
+ soup_server_message_set_io_data (msg, io);
io_run (msg);
}
+
+void
+soup_server_message_io_pause (SoupServerMessage *msg)
+{
+ SoupServerMessageIOData *io = soup_server_message_get_io_data (msg);
+
+ g_return_if_fail (io != NULL);
+
+ if (io->unpause_source) {
+ g_source_destroy (io->unpause_source);
+ g_source_unref (io->unpause_source);
+ io->unpause_source = NULL;
+ }
+
+ soup_message_io_data_pause (&io->base);
+}
+
+static gboolean
+io_unpause_internal (gpointer msg)
+{
+ SoupServerMessageIOData *io = soup_server_message_get_io_data (msg);
+
+ g_return_val_if_fail (io != NULL, FALSE);
+
+ g_clear_pointer (&io->unpause_source, g_source_unref);
+ soup_message_io_data_unpause (&io->base);
+ if (io->base.io_source)
+ return FALSE;
+
+ io_run (msg);
+ return FALSE;
+}
+
+void
+soup_server_message_io_unpause (SoupServerMessage *msg)
+{
+ SoupServerMessageIOData *io = soup_server_message_get_io_data (msg);
+
+ g_return_if_fail (io != NULL);
+
+ if (!io->unpause_source) {
+ io->unpause_source = soup_add_completion_reffed (io->base.async_context,
+ io_unpause_internal, msg, NULL);
+ }
+}
+
+gboolean
+soup_server_message_is_io_paused (SoupServerMessage *msg)
+{
+ SoupServerMessageIOData *io = soup_server_message_get_io_data (msg);
+
+ return io && io->base.paused;
+}