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