Merge remote branch 'gvdb/master'
[platform/upstream/glib.git] / gio / tests / socket-server.c
1 #include <gio/gio.h>
2 #include <gio/gunixsocketaddress.h>
3 #include <glib.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "socket-common.c"
8
9 GMainLoop *loop;
10
11 int port = 7777;
12 gboolean verbose = FALSE;
13 gboolean dont_reuse_address = FALSE;
14 gboolean non_blocking = FALSE;
15 gboolean use_udp = FALSE;
16 gboolean use_source = FALSE;
17 int cancel_timeout = 0;
18 int read_timeout = 0;
19 int delay = 0;
20 gboolean unix_socket = FALSE;
21
22 static GOptionEntry cmd_entries[] = {
23   {"port", 'p', 0, G_OPTION_ARG_INT, &port,
24    "Local port to bind to", NULL},
25   {"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
26    "Cancel any op after the specified amount of seconds", NULL},
27   {"udp", 'u', 0, G_OPTION_ARG_NONE, &use_udp,
28    "Use udp instead of tcp", NULL},
29   {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
30    "Be verbose", NULL},
31   {"no-reuse", 0, 0, G_OPTION_ARG_NONE, &dont_reuse_address,
32    "Don't SOADDRREUSE", NULL},
33   {"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
34    "Enable non-blocking i/o", NULL},
35   {"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
36    "Use GSource to wait for non-blocking i/o", NULL},
37 #ifdef G_OS_UNIX
38   {"unix", 'U', 0, G_OPTION_ARG_NONE, &unix_socket,
39    "Use a unix socket instead of IP", NULL},
40 #endif
41   {"delay", 'd', 0, G_OPTION_ARG_INT, &delay,
42    "Delay responses by the specified number of seconds", NULL},
43   {"timeout", 't', 0, G_OPTION_ARG_INT, &read_timeout,
44    "Time out reads after the specified number of seconds", NULL},
45   {NULL}
46 };
47
48 static gboolean
49 source_ready (gpointer data,
50               GIOCondition condition)
51 {
52   g_main_loop_quit (loop);
53   return FALSE;
54 }
55
56 static void
57 ensure_condition (GSocket *socket,
58                   const char *where,
59                   GCancellable *cancellable,
60                   GIOCondition condition)
61 {
62   GError *error = NULL;
63   GSource *source;
64
65   if (!non_blocking)
66     return;
67
68   if (use_source)
69     {
70       source = g_socket_create_source (socket,
71                                        condition,
72                                        cancellable);
73       g_source_set_callback (source,
74                              (GSourceFunc) source_ready,
75                              NULL, NULL);
76       g_source_attach (source, NULL);
77       g_source_unref (source);
78       g_main_loop_run (loop);
79     }
80   else
81     {
82       if (!g_socket_condition_wait (socket, condition, cancellable, &error))
83         {
84           g_printerr ("condition wait error for %s: %s\n",
85                       where,
86                       error->message);
87           exit (1);
88         }
89     }
90 }
91
92 static gpointer
93 cancel_thread (gpointer data)
94 {
95   GCancellable *cancellable = data;
96
97   g_usleep (1000*1000*cancel_timeout);
98   g_print ("Cancelling\n");
99   g_cancellable_cancel (cancellable);
100   return NULL;
101 }
102
103 int
104 main (int argc,
105       char *argv[])
106 {
107   GSocket *socket, *new_socket, *recv_socket;
108   GSocketAddress *src_address;
109   GSocketAddress *address;
110   GSocketType socket_type;
111   GSocketFamily socket_family;
112   GError *error = NULL;
113   GOptionContext *context;
114   GCancellable *cancellable;
115   char *display_addr;
116
117   g_thread_init (NULL);
118
119   g_type_init ();
120
121   context = g_option_context_new (" - Test GSocket server stuff");
122   g_option_context_add_main_entries (context, cmd_entries, NULL);
123   if (!g_option_context_parse (context, &argc, &argv, &error))
124     {
125       g_printerr ("%s: %s\n", argv[0], error->message);
126       return 1;
127     }
128
129   if (unix_socket && argc != 2)
130     {
131       g_printerr ("%s: %s\n", argv[0], "Need to specify unix socket name");
132       return 1;
133     }
134
135   if (cancel_timeout)
136     {
137       cancellable = g_cancellable_new ();
138       g_thread_create (cancel_thread, cancellable, FALSE, NULL);
139     }
140   else
141     {
142       cancellable = NULL;
143     }
144
145   loop = g_main_loop_new (NULL, FALSE);
146
147   if (use_udp)
148     socket_type = G_SOCKET_TYPE_DATAGRAM;
149   else
150     socket_type = G_SOCKET_TYPE_STREAM;
151
152   if (unix_socket)
153     socket_family = G_SOCKET_FAMILY_UNIX;
154   else
155     socket_family = G_SOCKET_FAMILY_IPV4;
156
157   socket = g_socket_new (socket_family, socket_type, 0, &error);
158
159   if (socket == NULL)
160     {
161       g_printerr ("%s: %s\n", argv[0], error->message);
162       return 1;
163     }
164
165   if (non_blocking)
166     g_socket_set_blocking (socket, FALSE);
167
168   if (unix_socket)
169     {
170       src_address = socket_address_from_string (argv[1]);
171       if (src_address == NULL)
172         {
173           g_printerr ("%s: Could not parse '%s' as unix socket name\n", argv[0], argv[1]);
174           return 1;
175         }
176     }
177   else
178     {
179       src_address = g_inet_socket_address_new (g_inet_address_new_any (G_SOCKET_FAMILY_IPV4), port);
180     }
181
182   if (!g_socket_bind (socket, src_address, !dont_reuse_address, &error))
183     {
184       g_printerr ("Can't bind socket: %s\n", error->message);
185       return 1;
186     }
187   g_object_unref (src_address);
188
189   if (!use_udp)
190     {
191       if (!g_socket_listen (socket, &error))
192         {
193           g_printerr ("Can't listen on socket: %s\n", error->message);
194           return 1;
195         }
196
197       address = g_socket_get_local_address (socket, &error);
198       if (!address)
199         {
200           g_printerr ("Error getting local address: %s\n",
201                       error->message);
202           return 1;
203         }
204       display_addr = socket_address_to_string (address);
205       g_print ("listening on %s...\n", display_addr);
206       g_free (display_addr);
207
208       ensure_condition (socket, "accept", cancellable, G_IO_IN);
209       new_socket = g_socket_accept (socket, cancellable, &error);
210       if (!new_socket)
211         {
212           g_printerr ("Error accepting socket: %s\n",
213                       error->message);
214           return 1;
215         }
216
217       if (non_blocking)
218         g_socket_set_blocking (new_socket, FALSE);
219       if (read_timeout)
220         g_socket_set_timeout (new_socket, read_timeout);
221
222       address = g_socket_get_remote_address (new_socket, &error);
223       if (!address)
224         {
225           g_printerr ("Error getting remote address: %s\n",
226                       error->message);
227           return 1;
228         }
229
230       display_addr = socket_address_to_string (address);
231       g_print ("got a new connection from %s\n", display_addr);
232       g_free(display_addr);
233       g_object_unref (address);
234
235       recv_socket = new_socket;
236     }
237   else
238     {
239       recv_socket = socket;
240       new_socket = NULL;
241     }
242
243
244   while (TRUE)
245     {
246       gchar buffer[4096];
247       gssize size;
248       gsize to_send;
249
250       ensure_condition (recv_socket, "receive", cancellable, G_IO_IN);
251       if (use_udp)
252         size = g_socket_receive_from (recv_socket, &address,
253                                       buffer, sizeof buffer,
254                                       cancellable, &error);
255       else
256         size = g_socket_receive (recv_socket, buffer, sizeof buffer,
257                                  cancellable, &error);
258
259       if (size < 0)
260         {
261           g_printerr ("Error receiving from socket: %s\n",
262                       error->message);
263           return 1;
264         }
265
266       if (size == 0)
267         break;
268
269       g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size);
270       if (use_udp)
271         g_print (" from %s", socket_address_to_string (address));
272       g_print ("\n");
273
274       if (verbose)
275         g_print ("-------------------------\n"
276                  "%.*s\n"
277                  "-------------------------\n",
278                  (int)size, buffer);
279
280       to_send = size;
281
282       if (delay)
283         {
284           if (verbose)
285             g_print ("delaying %d seconds before response\n", delay);
286           g_usleep (1000 * 1000 * delay);
287         }
288
289       while (to_send > 0)
290         {
291           ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
292           if (use_udp)
293             size = g_socket_send_to (recv_socket, address,
294                                      buffer, to_send, cancellable, &error);
295           else
296             size = g_socket_send (recv_socket, buffer, to_send,
297                                   cancellable, &error);
298
299           if (size < 0)
300             {
301               if (g_error_matches (error,
302                                    G_IO_ERROR,
303                                    G_IO_ERROR_WOULD_BLOCK))
304                 {
305                   g_print ("socket send would block, handling\n");
306                   g_error_free (error);
307                   error = NULL;
308                   continue;
309                 }
310               else
311                 {
312                   g_printerr ("Error sending to socket: %s\n",
313                               error->message);
314                   return 1;
315                 }
316             }
317
318           g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size);
319
320           if (size == 0)
321             {
322               g_printerr ("Unexpected short write\n");
323               return 1;
324             }
325
326           to_send -= size;
327         }
328     }
329
330   g_print ("connection closed\n");
331
332   if (new_socket)
333     {
334       if (!g_socket_close (new_socket, &error))
335         {
336           g_printerr ("Error closing connection socket: %s\n",
337                       error->message);
338           return 1;
339         }
340
341       g_object_unref (G_OBJECT (new_socket));
342     }
343
344   if (!g_socket_close (socket, &error))
345     {
346       g_printerr ("Error closing master socket: %s\n",
347                   error->message);
348       return 1;
349     }
350
351   g_object_unref (G_OBJECT (socket));
352
353   return 0;
354 }