[gtk+/broadway: 17/71] Add initial http server



commit ded9bc698bc822a939cad9155454e0c3e6754e3b
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Nov 18 13:17:23 2010 +0100

    Add initial http server

 gdk/broadway/gdkdisplay-broadway.c |  113 ++++++++++++++++++++++++++++++++++++
 gdk/broadway/gdkdisplay-broadway.h |    1 +
 2 files changed, 114 insertions(+), 0 deletions(-)
---
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
index a2d2d27..be618cf 100644
--- a/gdk/broadway/gdkdisplay-broadway.c
+++ b/gdk/broadway/gdkdisplay-broadway.c
@@ -122,6 +122,106 @@ _gdk_input_init (GdkDisplay *display)
   g_list_free (list);
 }
 
+typedef struct {
+  GdkDisplay *display;
+  GSocketConnection *connection;
+  GDataInputStream *data;
+  GString *request;
+} HttpRequest;
+
+static void
+http_request_free (HttpRequest *request)
+{
+  g_object_unref (request->connection);
+  g_object_unref (request->data);
+  g_string_free (request->request, TRUE);
+  g_free (request);
+}
+
+static void
+send_error (HttpRequest *request,
+	    int error_code,
+	    const char *reason)
+{
+  char *res;
+
+  res = g_strdup_printf ("HTTP/1.0 %d %s\r\n\r\n"
+			 "<html><head><title>%d %s</title></head>"
+			 "<body>%s</body></html>",
+			 error_code, reason,
+			 error_code, reason,
+			 reason);
+  /* TODO: This should really be async */
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+			     res, strlen (res), NULL, NULL, NULL);
+  g_free (res);
+  http_request_free (request);
+}
+
+static void
+got_request (HttpRequest *request)
+{
+  g_print ("got request:\n%s", request->request->str);
+  send_error (request, 404, "Not implemented yet");
+}
+
+static void
+got_http_request_line (GOutputStream *stream,
+		       GAsyncResult *result,
+		       HttpRequest *request)
+{
+  char *line;
+
+  line = g_data_input_stream_read_line_finish (G_DATA_INPUT_STREAM (stream), result, NULL, NULL);
+  if (line == NULL)
+    {
+      http_request_free (request);
+      g_printerr ("Error reading request lines\n");
+      return;
+    }
+  if (strlen (line) == 0)
+    got_request (request);
+  else
+    {
+      /* Protect against overflow in request length */
+      if (request->request->len > 1024 * 5)
+	{
+	  send_error (request, 400, "Request to long");
+	}
+      else
+	{
+	  g_string_append_printf (request->request, "%s\n", line);
+	  g_data_input_stream_read_line_async (request->data, 0, NULL,
+					       (GAsyncReadyCallback)got_http_request_line, request);
+	}
+    }
+  g_free (line);
+}
+
+static gboolean
+handle_incoming_connection (GSocketService    *service,
+			    GSocketConnection *connection,
+			    GObject           *source_object)
+{
+  HttpRequest *request;
+  GInputStream *in;
+
+  request = g_new0 (HttpRequest, 1);
+  request->connection = g_object_ref (connection);
+  request->display = (GdkDisplay *) source_object;
+  request->request = g_string_new ("");
+
+  in = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+
+  request->data = g_data_input_stream_new (in);
+  /* Be tolerant of input */
+  g_data_input_stream_set_newline_type (request->data, G_DATA_STREAM_NEWLINE_TYPE_ANY);
+
+  g_data_input_stream_read_line_async (request->data, 0, NULL,
+				       (GAsyncReadyCallback)got_http_request_line, request);
+  return TRUE;
+}
+
 GdkDisplay *
 gdk_display_open (const gchar *display_name)
 {
@@ -129,6 +229,7 @@ gdk_display_open (const gchar *display_name)
   GdkDisplayBroadway *display_broadway;
   const char *sm_client_id;
   int fd;
+  GError *error;
 
   fd = dup(STDOUT_FILENO);
   dup2(STDERR_FILENO, STDOUT_FILENO);
@@ -163,6 +264,18 @@ gdk_display_open (const gchar *display_name)
 
   _gdk_broadway_screen_setup (display_broadway->screens[0]);
 
+  display_broadway->service = g_socket_service_new ();
+  if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (display_broadway->service),
+					8080,
+					G_OBJECT (display),
+					&error))
+    {
+      g_printerr ("Unable to listen to port %d: %s\n", 8080, error->message);
+      g_error_free (error);
+      return NULL;
+    }
+  g_signal_connect (display_broadway->service, "incoming", G_CALLBACK (handle_incoming_connection), NULL);
+
   g_signal_emit_by_name (display, "opened");
   g_signal_emit_by_name (gdk_display_manager_get (), "display-opened", display);
 
diff --git a/gdk/broadway/gdkdisplay-broadway.h b/gdk/broadway/gdkdisplay-broadway.h
index e8a43de..3317b5b 100644
--- a/gdk/broadway/gdkdisplay-broadway.h
+++ b/gdk/broadway/gdkdisplay-broadway.h
@@ -74,6 +74,7 @@ struct _GdkDisplayBroadway
   /* The offscreen window that has the pointer in it (if any) */
   GdkWindow *active_offscreen_window;
 
+  GSocketService *service;
   BroadwayClient *connection;
 };
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]