source: trunk/third/libsoup/tests/simple-proxy.c @ 21108

Revision 21108, 4.2 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21107, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 2001-2003, Ximian, Inc.
4 */
5
6#include <ctype.h>
7#include <fcntl.h>
8#include <errno.h>
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16#include <glib.h>
17#include <libsoup/soup-address.h>
18#include <libsoup/soup-message.h>
19#include <libsoup/soup-server.h>
20#include <libsoup/soup-server-message.h>
21#include <libsoup/soup-session-async.h>
22
23/* WARNING: this is really really really not especially compliant with
24 * RFC 2616. But it does work for basic stuff.
25 */
26
27SoupSession *session;
28
29static void
30copy_header (gpointer name, gpointer value, gpointer dest_headers)
31{
32        soup_message_add_header (dest_headers, name, value);
33}
34
35static void
36send_headers (SoupMessage *from, SoupMessage *to)
37{
38        printf ("[%p] HTTP/1.%d %d %s\n", to,
39                soup_message_get_http_version (from),
40                from->status_code, from->reason_phrase);
41
42        soup_message_set_status_full (to, from->status_code,
43                                      from->reason_phrase);
44        soup_message_foreach_header (from->response_headers, copy_header,
45                                     to->response_headers);
46        soup_message_remove_header (to->response_headers, "Content-Length");
47        soup_message_io_unpause (to);
48}
49
50static void
51send_chunk (SoupMessage *from, SoupMessage *to)
52{
53        printf ("[%p]   writing chunk of %d bytes\n", to, from->response.length);
54
55        soup_message_add_chunk (to, SOUP_BUFFER_USER_OWNED,
56                                from->response.body, from->response.length);
57        soup_message_io_unpause (to);
58}
59
60static void
61client_msg_failed (SoupMessage *msg, gpointer msg2)
62{
63        /* FIXME
64        soup_message_cancel (msg2);
65        */
66}
67
68static void
69finish_msg (SoupMessage *msg2, gpointer msg)
70{
71        printf ("[%p]   done\n\n", msg);
72        g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2);
73
74        soup_message_add_final_chunk (msg);
75        soup_message_io_unpause (msg);
76        g_object_unref (msg);
77}
78
79static void
80server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
81{
82        SoupMessage *msg2;
83        char *uristr;
84
85        uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
86        printf ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
87                soup_message_get_http_version (msg));
88
89        if (soup_method_get_id (msg->method) == SOUP_METHOD_ID_CONNECT) {
90                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
91                return;
92        }
93
94        msg2 = soup_message_new (msg->method, uristr);
95        soup_message_foreach_header (msg->request_headers, copy_header,
96                                     msg2->request_headers);
97        soup_message_remove_header (msg2->request_headers, "Host");
98        soup_message_remove_header (msg2->request_headers, "Connection");
99
100        if (msg->request.length) {
101                msg2->request.owner = SOUP_BUFFER_USER_OWNED;
102                msg2->request.body = msg->request.body;
103                msg2->request.length = msg->request.length;
104        }
105        soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg),
106                                          SOUP_TRANSFER_CHUNKED);
107
108        g_signal_connect (msg2, "got_headers",
109                          G_CALLBACK (send_headers), msg);
110        g_signal_connect (msg2, "got_chunk",
111                          G_CALLBACK (send_chunk), msg);
112        soup_message_set_flags (msg2, SOUP_MESSAGE_OVERWRITE_CHUNKS);
113
114        g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);
115
116        soup_session_queue_message (session, msg2, finish_msg, msg);
117
118        g_object_ref (msg);
119        soup_message_io_pause (msg);
120}
121
122static void
123quit (int sig)
124{
125        /* Exit cleanly on ^C in case we're valgrinding. */
126        exit (0);
127}
128
129int
130main (int argc, char **argv)
131{
132        GMainLoop *loop;
133        int opt;
134        int port = SOUP_ADDRESS_ANY_PORT;
135        SoupServer *server;
136
137        g_type_init ();
138        signal (SIGINT, quit);
139
140        while ((opt = getopt (argc, argv, "p:s:")) != -1) {
141                switch (opt) {
142                case 'p':
143                        port = atoi (optarg);
144                        break;
145                default:
146                        fprintf (stderr, "Usage: %s [-p port] [-n]\n",
147                                 argv[0]);
148                        exit (1);
149                }
150        }
151
152        server = soup_server_new (SOUP_SERVER_PORT, port,
153                                  NULL);
154        if (!server) {
155                fprintf (stderr, "Unable to bind to server port %d\n", port);
156                exit (1);
157        }
158        soup_server_add_handler (server, NULL, NULL,
159                                 server_callback, NULL, NULL);
160
161        printf ("\nStarting proxy on port %d\n",
162                soup_server_get_port (server));
163        soup_server_run_async (server);
164
165        session = soup_session_async_new ();
166
167        printf ("\nWaiting for requests...\n");
168
169        loop = g_main_loop_new (NULL, TRUE);
170        g_main_loop_run (loop);
171        g_main_loop_unref (loop);
172
173        return 0;
174}
Note: See TracBrowser for help on using the repository browser.