summaryrefslogtreecommitdiff
path: root/libsoup/soup-message-server-io.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2003-08-29 22:24:54 +0000
committerDan Winship <danw@src.gnome.org>2003-08-29 22:24:54 +0000
commit1468fddca1027399c84834b968ccf2208394af26 (patch)
treecc678f3a0e1389e5d145307872aefa63ad215702 /libsoup/soup-message-server-io.c
parent3594d2168cfa7505f66ebb7991fb9f3a3d5edd41 (diff)
downloadlibsoup-1468fddca1027399c84834b968ccf2208394af26.tar.gz
Major rewrite. There is now only a single IO state object (instead of one
* libsoup/soup-message-io.c: Major rewrite. There is now only a single IO state object (instead of one for reading and one for writing), and the IO code handles switching back and forth between reading and writing as appropriate (including handling the extra switches needed for "Expect: 100-continue"). (soup_message_io_client, soup_message_io_server): The new entry points. (soup_message_io_cancel): If the caller cancels the IO when we were expecting to read more data, disconnect the socket. * libsoup/soup-message.h (SoupMessageFlags): add SOUP_MESSAGE_EXPECT_CONTINUE, to indicate that the IO code should do the special expect-continue handling. * libsoup/soup-message.c: Move all the signal stuff here. Remove the "done_reading" and "done_writing" signals and replace them with a single "finished" signal. (A single signal. Say that 10 times fast!) (soup_message_got_headers, etc): Functions to emit signals. (got_headers, got_chunk, got_body): Default signal methods that call soup_message_run_handlers. (finished): Default signal method that replaces soup_message_issue_callback. ([various]): s/soup_message_issue_callback/soup_message_finished/ (soup_message_requeue): There's no soup_message_set_read_callbacks any more, so if the caller requeues while it's still reading, just cancel the read. (soup_message_add_chunk, soup_message_add_final_chunk, soup_message_pop_chunk): Moved here from soup-server-message, although we don't actually quite support using chunked encoding for requests yet. * libsoup/soup-server-message.c (soup_server_message_new): No longer takes a socket argument. (soup_server_message_add_chunk, soup_server_message_get_chunk): Moved into SoupMessage. * libsoup/soup-message-handlers.c (global_handlers): Make these POST_BODY rather than PRE_BODY, so they won't mess up the IO channel when the requeue the message. (soup_message_run_handlers): Don't need to issue the message callback from here any more. (authorize_handler): Just leave the error as 401 or 407 (see soup-error.h change) * libsoup/soup-message-client-io.c (soup_message_send_request): Replaces soup_message_write_request and soup_message_read_response. * libsoup/soup-message-server-io.c: Parallel to soup-message-client-io.c, this defines the server-side header handling. (soup_message_read_request): Its entry point. * libsoup/soup-server.c: Lots of code moved into soup-message-server-io.c. Update for other changes. * libsoup/soup-queue.c: Update for changes * libsoup/soup-socket.c (read_from_network, soup_socket_write): Don't call soup_socket_disconnect() on an error, just return SOUP_SOCKET_ERROR. Otherwise soup_socket_disconnect() could emit signals that will mess up the caller of the read/write function. * libsoup/soup-connection.c (soup_connection_disconnect): When disconnecting the socket, disconnect from its signals first to prevent bad reentrancy. * libsoup/soup-error.h: Kill off SOUP_ERROR_CANT_AUTHENTICATE and SOUP_ERROR_CANT_AUTHENTICATE_PROXY, since they don't really say anything that SOUP_ERROR_UNATHORIZED and SOUP_ERROR_PROXY_UNAUTHORIZED don't say. (And now, all of the "transport" errors actually are transport-related.) * tests/auth-test.c (main): s/CANT_AUTHENTICATE/UNAUTHORIZED/ * tests/simple-proxy.c: Complicate this a bunch. In particular, use SOUP_MESSAGE_OVERWRITE_CHUNKS and the GOT_CHUNK signal, and pass the data back to the client in chunked format.
Diffstat (limited to 'libsoup/soup-message-server-io.c')
-rw-r--r--libsoup/soup-message-server-io.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c
new file mode 100644
index 00000000..1b9d5db1
--- /dev/null
+++ b/libsoup/soup-message-server-io.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-message-server-io.c: server-side request/response
+ *
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "soup-message-private.h"
+#include "soup-address.h"
+#include "soup-auth.h"
+#include "soup-context.h"
+#include "soup-headers.h"
+#include "soup-misc.h"
+#include "soup-private.h"
+#include "soup-server-message.h"
+#include "soup-server.h"
+#include "soup-socket.h"
+
+static SoupKnownErrorCode
+parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
+ SoupTransferEncoding *encoding, guint *content_len,
+ gpointer sock)
+{
+ SoupContext *ctx;
+ char *req_path = NULL, *url;
+ const char *length, *enc, *req_host;
+ SoupServer *server;
+
+ if (!soup_headers_parse_request (headers, headers_len,
+ msg->request_headers,
+ (char **) &msg->method,
+ &req_path,
+ &msg->priv->http_version))
+ return SOUP_ERROR_BAD_REQUEST;
+
+ /* Handle request body encoding */
+ length = soup_message_get_header (msg->request_headers,
+ "Content-Length");
+ enc = soup_message_get_header (msg->request_headers,
+ "Transfer-Encoding");
+
+ if (enc) {
+ if (g_strcasecmp (enc, "chunked") == 0)
+ *encoding = SOUP_TRANSFER_CHUNKED;
+ else {
+ g_warning ("Unknown encoding type in HTTP request.");
+ g_free (req_path);
+ return SOUP_ERROR_NOT_IMPLEMENTED;
+ }
+ } else if (length) {
+ int len;
+ *encoding = SOUP_TRANSFER_CONTENT_LENGTH;
+ len = atoi (length);
+ if (len < 0) {
+ g_free (req_path);
+ return SOUP_ERROR_BAD_REQUEST;
+ }
+ *content_len = len;
+ } else {
+ *encoding = SOUP_TRANSFER_CONTENT_LENGTH;
+ *content_len = 0;
+ }
+
+ /* Generate correct context for request */
+ server = soup_server_message_get_server (SOUP_SERVER_MESSAGE (msg));
+ req_host = soup_message_get_header (msg->request_headers, "Host");
+
+ if (*req_path != '/') {
+ /* Check for absolute URI */
+ SoupUri *absolute;
+
+ absolute = soup_uri_new (req_path);
+ if (absolute) {
+ url = g_strdup (req_path);
+ soup_uri_free (absolute);
+ } else {
+ g_free (req_path);
+ return SOUP_ERROR_BAD_REQUEST;
+ }
+ } else if (req_host) {
+ url = g_strdup_printf ("%s://%s:%d%s",
+ soup_server_get_protocol (server) == SOUP_PROTOCOL_HTTPS ? "https" : "http",
+ req_host, soup_server_get_port (server),
+ req_path);
+ } else if (msg->priv->http_version == SOUP_HTTP_1_0) {
+ /* No Host header, no AbsoluteUri */
+ SoupAddress *addr = soup_socket_get_local_address (sock);
+ const char *host = soup_address_get_physical (addr);
+
+ url = g_strdup_printf ("%s://%s:%d%s",
+ soup_server_get_protocol (server) == SOUP_PROTOCOL_HTTPS ? "https" : "http",
+ host, soup_server_get_port (server),
+ req_path);
+ } else {
+ g_free (req_path);
+ return SOUP_ERROR_BAD_REQUEST;
+ }
+
+ ctx = soup_context_get (url);
+ g_free (url);
+ g_free (req_path);
+
+ if (!ctx)
+ return SOUP_ERROR_BAD_REQUEST;
+
+ soup_message_set_context (msg, ctx);
+ g_object_unref (ctx);
+
+ return SOUP_ERROR_OK;
+}
+
+static void
+write_header (gpointer name, gpointer value, gpointer headers)
+{
+ g_string_append_printf (headers, "%s: %s\r\n",
+ (char *)name, (char *)value);
+}
+
+static void
+get_response_headers (SoupMessage *msg, GString *headers,
+ SoupTransferEncoding *encoding,
+ gpointer user_data)
+{
+ SoupServerMessage *smsg = SOUP_SERVER_MESSAGE (msg);
+
+ g_string_append_printf (headers, "HTTP/1.1 %d %s\r\n",
+ msg->errorcode, msg->errorphrase);
+
+ soup_message_foreach_header (msg->response_headers,
+ write_header, headers);
+
+ *encoding = soup_server_message_get_encoding (smsg);
+ if (*encoding == SOUP_TRANSFER_CONTENT_LENGTH) {
+ g_string_append_printf (headers, "Content-Length: %d\r\n",
+ msg->response.length);
+ } else if (*encoding == SOUP_TRANSFER_CHUNKED)
+ g_string_append (headers, "Transfer-Encoding: chunked\r\n");
+
+ g_string_append (headers, "\r\n");
+}
+
+void
+soup_message_read_request (SoupMessage *req, SoupSocket *sock)
+{
+ soup_message_io_server (req, sock,
+ get_response_headers,
+ parse_request_headers,
+ sock);
+}