Git init
[profile/ivi/libsoup2.4.git] / tests / simple-proxy.c
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.h>
18
19 /* WARNING: this is really really really not especially compliant with
20  * RFC 2616. But it does work for basic stuff.
21  */
22
23 static SoupSession *session;
24 static SoupServer *server;
25
26 static void
27 copy_header (const char *name, const char *value, gpointer dest_headers)
28 {
29         soup_message_headers_append (dest_headers, name, value);
30 }
31
32 static void
33 send_headers (SoupMessage *from, SoupMessage *to)
34 {
35         printf ("[%p] HTTP/1.%d %d %s\n", to,
36                 soup_message_get_http_version (from),
37                 from->status_code, from->reason_phrase);
38
39         soup_message_set_status_full (to, from->status_code,
40                                       from->reason_phrase);
41         soup_message_headers_foreach (from->response_headers, copy_header,
42                                       to->response_headers);
43         soup_message_headers_remove (to->response_headers, "Content-Length");
44         soup_server_unpause_message (server, to);
45 }
46
47 static void
48 send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to)
49 {
50         printf ("[%p]   writing chunk of %lu bytes\n", to,
51                 (unsigned long)chunk->length);
52
53         soup_message_body_append_buffer (to->response_body, chunk);
54         soup_server_unpause_message (server, to);
55 }
56
57 static void
58 client_msg_failed (SoupMessage *msg, gpointer msg2)
59 {
60         soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR);
61 }
62
63 static void
64 finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data)
65 {
66         SoupMessage *msg = data;
67
68         printf ("[%p]   done\n\n", msg);
69         g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2);
70
71         soup_message_body_complete (msg->response_body);
72         soup_server_unpause_message (server, msg);
73         g_object_unref (msg);
74 }
75
76 static void
77 server_callback (SoupServer *server, SoupMessage *msg,
78                  const char *path, GHashTable *query,
79                  SoupClientContext *context, gpointer data)
80 {
81         SoupMessage *msg2;
82         char *uristr;
83
84         uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
85         printf ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
86                 soup_message_get_http_version (msg));
87
88         if (msg->method == SOUP_METHOD_CONNECT) {
89                 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
90                 return;
91         }
92
93         msg2 = soup_message_new (msg->method, uristr);
94         soup_message_headers_foreach (msg->request_headers, copy_header,
95                                       msg2->request_headers);
96         soup_message_headers_remove (msg2->request_headers, "Host");
97         soup_message_headers_remove (msg2->request_headers, "Connection");
98
99         if (msg->request_body->length) {
100                 SoupBuffer *request = soup_message_body_flatten (msg->request_body);
101                 soup_message_body_append_buffer (msg2->request_body, request);
102                 soup_buffer_free (request);
103         }
104         soup_message_headers_set_encoding (msg->response_headers,
105                                            SOUP_ENCODING_CHUNKED);
106
107         g_signal_connect (msg2, "got_headers",
108                           G_CALLBACK (send_headers), msg);
109         g_signal_connect (msg2, "got_chunk",
110                           G_CALLBACK (send_chunk), msg);
111
112         g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);
113
114         soup_session_queue_message (session, msg2, finish_msg, msg);
115
116         g_object_ref (msg);
117         soup_server_pause_message (server, msg);
118 }
119
120 static gboolean
121 auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
122                const char *username, const char *password, gpointer data)
123 {
124         return !strcmp (username, "user") && !strcmp (password, "password");
125 }
126
127 static void
128 quit (int sig)
129 {
130         /* Exit cleanly on ^C in case we're valgrinding. */
131         exit (0);
132 }
133
134 int
135 main (int argc, char **argv)
136 {
137         GMainLoop *loop;
138         int opt;
139         int port = SOUP_ADDRESS_ANY_PORT;
140         SoupAuthDomain *auth_domain = NULL;
141
142         g_thread_init (NULL);
143         g_type_init ();
144         signal (SIGINT, quit);
145
146         while ((opt = getopt (argc, argv, "ap:")) != -1) {
147                 switch (opt) {
148                 case 'a':
149                         auth_domain = soup_auth_domain_basic_new (
150                                 SOUP_AUTH_DOMAIN_REALM, "simple-proxy",
151                                 SOUP_AUTH_DOMAIN_PROXY, TRUE,
152                                 SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
153                                 NULL);
154                         break;
155                 case 'p':
156                         port = atoi (optarg);
157                         break;
158                 default:
159                         fprintf (stderr, "Usage: %s [-p port] [-n]\n",
160                                  argv[0]);
161                         exit (1);
162                 }
163         }
164
165         server = soup_server_new (SOUP_SERVER_PORT, port,
166                                   NULL);
167         if (!server) {
168                 fprintf (stderr, "Unable to bind to server port %d\n", port);
169                 exit (1);
170         }
171         soup_server_add_handler (server, NULL,
172                                  server_callback, NULL, NULL);
173         if (auth_domain) {
174                 soup_server_add_auth_domain (server, auth_domain);
175                 g_object_unref (auth_domain);
176         }
177
178         printf ("\nStarting proxy on port %d\n",
179                 soup_server_get_port (server));
180         soup_server_run_async (server);
181
182         session = soup_session_async_new ();
183
184         printf ("\nWaiting for requests...\n");
185
186         loop = g_main_loop_new (NULL, TRUE);
187         g_main_loop_run (loop);
188         g_main_loop_unref (loop);
189
190         return 0;
191 }