Change to using enums for g_socket_new
[cascardo/gnio.git] / gnio / gsocket.c
1 /* GNIO - GLib Network Layer of GIO
2  *
3  * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Christian Kellner <gicmo@gnome.org>
21  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
22  */
23
24 #include <config.h>
25 #include <glib.h>
26 #include <gio/gio.h>
27 #include <gio/gasynchelper.h>
28
29 #include <string.h>
30 #ifndef G_OS_WIN32
31 # include <netinet/in.h>
32 # include <arpa/inet.h>
33 # include <netdb.h>
34 # include <fcntl.h>
35 # include <unistd.h>
36 # include <sys/types.h>
37 #else
38
39 #endif
40 #include <errno.h>
41
42 #include "ginetaddress.h"
43 #include "ginet4address.h"
44 #include "ginet6address.h"
45 #include "gsocket.h"
46 #include "gnioerror.h"
47 #include "ginetsocketaddress.h"
48
49 G_DEFINE_TYPE (GSocket, g_socket, G_TYPE_OBJECT);
50
51 enum
52 {
53   PROP_0,
54   PROP_FD,
55   PROP_BLOCKING
56 };
57
58 struct _GSocketPrivate
59 {
60   gint fd;
61   gboolean blocking;
62 };
63
64 static void
65 g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
66 {
67   GSocket *socket = G_SOCKET (object);
68
69   switch (prop_id)
70     {
71       case PROP_FD:
72         g_value_set_int (value, socket->priv->fd);
73         break;
74
75       case PROP_BLOCKING:
76         g_value_set_boolean (value, socket->priv->blocking);
77         break;
78
79       default:
80         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
81     }
82 }
83
84 static void
85 g_socket_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
86 {
87   GSocket *socket = G_SOCKET (object);
88
89   switch (prop_id)
90     {
91       case PROP_FD:
92         socket->priv->fd = g_value_get_int (value);
93         break;
94
95       case PROP_BLOCKING:
96         g_socket_set_blocking (socket, g_value_get_boolean (value));
97         break;
98
99       default:
100         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101     }
102 }
103
104 static void
105 g_socket_finalize (GObject *object)
106 {
107   GSocket *socket G_GNUC_UNUSED = G_SOCKET (object);
108
109   if (G_OBJECT_CLASS (g_socket_parent_class)->finalize)
110     (*G_OBJECT_CLASS (g_socket_parent_class)->finalize) (object);
111 }
112
113 static void
114 g_socket_dispose (GObject *object)
115 {
116   GSocket *socket G_GNUC_UNUSED = G_SOCKET (object);;
117
118   if (G_OBJECT_CLASS (g_socket_parent_class)->dispose)
119     (*G_OBJECT_CLASS (g_socket_parent_class)->dispose) (object);
120 }
121
122 static void
123 g_socket_class_init (GSocketClass *klass)
124 {
125   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
126
127   g_type_class_add_private (klass, sizeof (GSocketPrivate));
128
129   gobject_class->finalize = g_socket_finalize;
130   gobject_class->dispose = g_socket_dispose;
131   gobject_class->set_property = g_socket_set_property;
132   gobject_class->get_property = g_socket_get_property;
133
134   g_object_class_install_property (gobject_class, PROP_FD,
135                                    g_param_spec_int ("fd",
136                                                      "file descriptor",
137                                                      "the socket's file descriptor",
138                                                      G_MININT,
139                                                      G_MAXINT,
140                                                      -1,
141                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
142
143   g_object_class_install_property (gobject_class, PROP_BLOCKING,
144                                    g_param_spec_boolean ("blocking",
145                                                          "blocking",
146                                                          "whether or not this socket is blocking",
147                                                          TRUE,
148                                                          G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
149 }
150
151 static void
152 g_socket_init (GSocket *socket)
153 {
154   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, G_TYPE_SOCKET, GSocketPrivate);
155
156   socket->priv->fd = -1;
157   socket->priv->blocking = TRUE;
158 }
159
160 GSocket *
161 g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol, GError **error)
162 {
163   static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT;
164   gint fd, native_domain, native_type, native_protocol;
165
166   switch (domain)
167     {
168       case G_SOCKET_DOMAIN_INET:
169         native_domain = PF_INET;
170         break;
171
172       case G_SOCKET_DOMAIN_INET6:
173         native_domain = PF_INET6;
174         break;
175
176       case G_SOCKET_DOMAIN_UNIX:
177         native_domain = PF_UNIX;
178         break;
179
180       default:
181         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain");
182         return NULL;
183     }
184
185   switch (type)
186     {
187       case G_SOCKET_TYPE_STREAM:
188         native_type = SOCK_STREAM;
189         break;
190
191       case G_SOCKET_TYPE_DATAGRAM:
192         native_type = SOCK_DGRAM;
193         break;
194
195       case G_SOCKET_TYPE_SEQPACKET:
196         native_type = SOCK_SEQPACKET;
197         break;
198
199       default:
200         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type");
201         return NULL;
202     }
203
204   if (protocol == NULL)
205     native_protocol = 0;
206   else
207     {
208       struct protoent *ent;
209       g_static_mutex_lock (&getprotobyname_mutex);
210       if (!(ent = getprotobyname (protocol)))
211         {
212           g_static_mutex_unlock (&getprotobyname_mutex);
213           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol");
214           return NULL;
215         }
216       native_protocol = ent->p_proto;
217       g_static_mutex_unlock (&getprotobyname_mutex);
218     }
219
220   fd = socket(native_domain, native_type, native_protocol);
221
222   if (fd < 0)
223     {
224       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno));
225       return NULL;
226     }
227
228   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL));
229 }
230
231 GSocket *
232 g_socket_new_from_fd (gint fd)
233 {
234   glong arg;
235   gboolean blocking;
236
237   if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
238     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
239
240   blocking = ((arg & O_NONBLOCK) != 0);
241
242   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "blocking", blocking, "fd", fd, NULL));
243 }
244
245 void
246 g_socket_set_blocking (GSocket  *socket,
247                        gboolean  blocking)
248 {
249   glong arg;
250
251   g_return_if_fail (G_IS_SOCKET (socket));
252
253   if ((arg = fcntl (socket->priv->fd, F_GETFL, NULL)) < 0)
254     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
255
256   arg = blocking ? arg & ~O_NONBLOCK : arg | O_NONBLOCK;
257
258   if (fcntl (socket->priv->fd, F_SETFL, arg) < 0)
259     g_warning ("Error setting socket status flags: %s", g_strerror (errno));
260
261   socket->priv->blocking = blocking;
262 }
263
264 gboolean
265 g_socket_get_blocking (GSocket *socket)
266 {
267   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
268
269   return socket->priv->blocking;
270 }
271
272 GSocketAddress *
273 g_socket_get_peer_address (GSocket  *socket,
274                            GError  **error)
275 {
276   gchar buffer[256];
277   gsize len;
278
279   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
280
281   if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
282     {
283       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get peer address: %s", g_strerror (errno));
284       return NULL;
285     }
286
287   return g_socket_address_from_native (buffer, len);
288 }
289
290 void
291 g_socket_listen (GSocket *socket,
292                  gint     backlog)
293 {
294   g_return_if_fail (G_IS_SOCKET (socket));
295
296   listen (socket->priv->fd, backlog);
297 }
298
299 gboolean
300 g_socket_bind (GSocket         *socket,
301                GSocketAddress  *address,
302                GError         **error)
303 {
304   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
305
306   {
307     gchar addr[256];
308
309     if (!g_socket_address_to_native (address, addr))
310       return FALSE;
311
312     if (bind (socket->priv->fd, (struct sockaddr *) addr, g_socket_address_native_size (address)) < 0)
313       {
314         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error binding to address: %s", g_strerror (errno));
315         return FALSE;
316       }
317
318     g_object_unref (address);
319
320     return TRUE;
321   }
322 }
323
324 GSocket *
325 g_socket_accept (GSocket       *socket,
326                  GCancellable  *cancellable,
327                  GError       **error)
328 {
329   gint ret;
330
331   if (g_cancellable_set_error_if_cancelled (cancellable, error))
332     return NULL;
333
334   if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
335     {
336       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection");
337       return NULL;
338     }
339
340   if (g_cancellable_set_error_if_cancelled (cancellable, error))
341     {
342       close (ret);
343       return NULL;
344     }
345
346   return g_socket_new_from_fd (ret);
347 }
348
349 typedef struct {
350   GAsyncReadyCallback callback;
351   GCancellable *cancellable;
352   gpointer user_data;
353   GSocket *socket;
354 } AcceptData;
355
356 static gboolean
357 accept_callback (AcceptData *data,
358                  GIOCondition condition,
359                  gint fd)
360 {
361   GSocket *socket;
362   GSimpleAsyncResult *result;
363   gint ret;
364
365   socket = data->socket;
366
367   if (condition & G_IO_IN)
368     {
369       if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
370         {
371           if (errno == EAGAIN)
372             return TRUE;
373
374           result = g_simple_async_result_new_error (G_OBJECT (socket), data->callback, data->user_data, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection");
375         }
376       else
377         {
378           result = g_simple_async_result_new (G_OBJECT (socket), data->callback, data->user_data, g_socket_accept_async);
379
380           g_simple_async_result_set_op_res_gpointer (result, g_socket_new_from_fd (ret), g_object_unref);
381         }
382
383       g_simple_async_result_complete (result);
384
385       g_object_unref (result);
386     }
387
388   return FALSE;
389 }
390
391 void
392 g_socket_accept_async (GSocket             *socket,
393                        GCancellable        *cancellable,
394                        GAsyncReadyCallback  callback,
395                        gpointer             user_data)
396 {
397   GSource *source;
398   GSimpleAsyncResult *result;
399   AcceptData *data;
400   gint ret;
401
402   g_return_if_fail (G_IS_SOCKET (socket));
403
404   if (g_socket_get_blocking (socket))
405     g_socket_set_blocking (socket, FALSE);
406
407   if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
408     {
409       if (errno == EAGAIN)
410         {
411           source = _g_fd_source_new (socket->priv->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, cancellable);
412
413           data = g_new (AcceptData, 1);
414
415           data->socket = socket;
416           data->callback = callback;
417           data->cancellable = cancellable;
418           data->user_data = user_data;
419
420           g_source_set_callback (source, (GSourceFunc) accept_callback, data, g_free);
421
422           g_source_attach (source, NULL);
423         }
424       else
425         {
426           g_simple_async_report_error_in_idle (G_OBJECT (socket), callback, user_data, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection");
427         }
428     }
429   else
430     {
431       result = g_simple_async_result_new (G_OBJECT (socket), callback, user_data, g_socket_accept_async);
432
433       g_simple_async_result_set_op_res_gpointer (result, g_socket_new_from_fd (ret), g_object_unref);
434
435       g_simple_async_result_complete_in_idle (result);
436
437       g_object_unref (result);
438     }
439 }
440
441 GSocket *
442 g_socket_accept_finish (GSocket       *socket,
443                         GAsyncResult  *result,
444                         GError       **error)
445 {
446   GSocket *new_socket;
447   GSimpleAsyncResult *simple;
448
449   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
450
451   simple = G_SIMPLE_ASYNC_RESULT (result);
452
453   if (g_simple_async_result_propagate_error (simple, error))
454     return NULL;
455
456   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_accept_async);
457
458   new_socket = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
459
460   return new_socket;
461 }
462
463 gboolean
464 g_socket_connect (GSocket         *socket,
465                   GSocketAddress  *address,
466                   GCancellable    *cancellable,
467                   GError         **error)
468 {
469   gchar buffer[256];
470
471   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
472
473   g_socket_address_to_native (address, buffer);
474
475   if (connect (socket->priv->fd, (struct sockaddr *) buffer, g_socket_address_native_size (address)) < 0)
476     {
477       if (errno == EINPROGRESS)
478         g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, "connection in progress");
479       else
480         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno));
481       return FALSE;
482     }
483
484   return TRUE;
485 }
486
487 typedef struct {
488   GAsyncReadyCallback callback;
489   GCancellable *cancellable;
490   gpointer user_data;
491   GSocket *socket;
492   gchar address_buffer[256];
493   gsize address_length;
494 } ConnectData;
495
496 static gboolean
497 connect_callback (ConnectData *data,
498                   GIOCondition condition,
499                   gint fd)
500 {
501   GSocket *socket;
502   GSimpleAsyncResult *result = NULL;
503   gint sockerr = 0;
504   gsize sockerr_size = 1;
505
506   socket = data->socket;
507
508   if (condition & G_IO_OUT)
509     {
510       result = g_simple_async_result_new (G_OBJECT (socket), data->callback, data->user_data, g_socket_connect_async);
511     }
512   else if (condition & G_IO_ERR)
513     {
514       if (getsockopt (fd, SOL_SOCKET, SO_ERROR, (gpointer) &sockerr, &sockerr_size) < 0)
515         g_warning ("getsockopt: %s", g_strerror (errno));
516
517       if (sockerr != 0)
518         result = g_simple_async_result_new_error (G_OBJECT (socket), data->callback, data->user_data, G_IO_ERROR, g_io_error_from_errno (sockerr), "error connecting: %s", g_strerror (sockerr));
519       else
520         g_warning ("getsockopt SO_ERROR returned no error, with sockerr = %d", sockerr);
521     }
522
523   g_simple_async_result_complete (result);
524
525   g_object_unref (result);
526
527   return FALSE;
528 }
529
530 void
531 g_socket_connect_async (GSocket             *socket,
532                         GSocketAddress      *address,
533                         GCancellable        *cancellable,
534                         GAsyncReadyCallback  callback,
535                         gpointer             user_data)
536 {
537   GSource *source;
538   GSimpleAsyncResult *result;
539   ConnectData *data;
540   gint ret;
541   gchar buffer[256];
542   gsize len;
543
544   g_return_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address));
545
546   if (g_socket_get_blocking (socket))
547     g_socket_set_blocking (socket, FALSE);
548
549   g_socket_address_to_native (address, buffer);
550
551   len = g_socket_address_native_size (address);
552
553   if ((ret = connect (socket->priv->fd, (struct sockaddr *) buffer, len)) < 0)
554     {
555       if (errno == EINPROGRESS)
556         {
557           source = _g_fd_source_new (socket->priv->fd, G_IO_OUT | G_IO_ERR, cancellable);
558
559           data = g_new (ConnectData, 1);
560
561           data->socket = socket;
562           data->callback = callback;
563           data->cancellable = cancellable;
564           data->user_data = user_data;
565           data->address_length = len;
566           memcpy (data->address_buffer, buffer, len);
567
568           g_source_set_callback (source, (GSourceFunc) connect_callback, data, g_free);
569
570           g_source_attach (source, NULL);
571         }
572       else
573         {
574           g_simple_async_report_error_in_idle (G_OBJECT (socket), callback, user_data, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno));
575         }
576     }
577   else
578     {
579       result = g_simple_async_result_new (G_OBJECT (socket), callback, user_data, g_socket_connect_async);
580
581       g_simple_async_result_complete_in_idle (result);
582
583       g_object_unref (result);
584     }
585 }
586
587 gboolean
588 g_socket_connect_finish (GSocket       *socket,
589                          GAsyncResult  *result,
590                          GError       **error)
591 {
592   GSimpleAsyncResult *simple;
593
594   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
595
596   simple = G_SIMPLE_ASYNC_RESULT (result);
597
598   if (g_simple_async_result_propagate_error (simple, error))
599     return FALSE;
600
601   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_connect_async);
602
603   return TRUE;
604 }