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