Add reuse_address as a gobject property
[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   PROP_BACKLOG,
57   PROP_REUSE_ADDRESS,
58   PROP_LOCAL_ADDRESS,
59   PROP_REMOTE_ADDRESS
60 };
61
62 struct _GSocketPrivate
63 {
64   gint fd;
65   gboolean blocking;
66   gint backlog;
67   gboolean reuse_address;
68   GSocketAddress *local_address;
69   GSocketAddress *remote_address;
70 };
71
72 static void
73 g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
74 {
75   GSocket *socket = G_SOCKET (object);
76
77   switch (prop_id)
78     {
79       case PROP_FD:
80         g_value_set_int (value, socket->priv->fd);
81         break;
82
83       case PROP_BLOCKING:
84         g_value_set_boolean (value, socket->priv->blocking);
85         break;
86
87       case PROP_BACKLOG:
88         g_value_set_int (value, socket->priv->backlog);
89         break;
90
91       case PROP_REUSE_ADDRESS:
92         g_value_set_boolean (value, socket->priv->reuse_address);
93         break;
94
95       case PROP_LOCAL_ADDRESS:
96         g_value_set_object (value, socket->priv->local_address);
97         break;
98
99       case PROP_REMOTE_ADDRESS:
100         g_value_set_object (value, socket->priv->remote_address);
101         break;
102
103       default:
104         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105     }
106 }
107
108 static void
109 g_socket_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
110 {
111   GSocket *socket = G_SOCKET (object);
112
113   switch (prop_id)
114     {
115       case PROP_FD:
116         socket->priv->fd = g_value_get_int (value);
117         break;
118
119       case PROP_BLOCKING:
120         g_socket_set_blocking (socket, g_value_get_boolean (value));
121         break;
122
123       case PROP_BACKLOG:
124         socket->priv->backlog = g_value_get_int (value);
125         break;
126
127       case PROP_REUSE_ADDRESS:
128         g_socket_set_reuse_address (socket, g_value_get_boolean (value));
129         break;
130
131       default:
132         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
133     }
134 }
135
136 static void
137 g_socket_finalize (GObject *object)
138 {
139   GSocket *socket = G_SOCKET (object);
140
141   if (socket->priv->local_address)
142     g_object_unref (socket->priv->local_address);
143
144   if (socket->priv->remote_address)
145     g_object_unref (socket->priv->remote_address);
146
147   if (G_OBJECT_CLASS (g_socket_parent_class)->finalize)
148     (*G_OBJECT_CLASS (g_socket_parent_class)->finalize) (object);
149 }
150
151 static void
152 g_socket_dispose (GObject *object)
153 {
154   GSocket *socket = G_SOCKET (object);
155
156   g_socket_close (socket);
157
158   if (G_OBJECT_CLASS (g_socket_parent_class)->dispose)
159     (*G_OBJECT_CLASS (g_socket_parent_class)->dispose) (object);
160 }
161
162 static void
163 g_socket_class_init (GSocketClass *klass)
164 {
165   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
166
167   // TODO: WSAStartup
168
169   g_type_class_add_private (klass, sizeof (GSocketPrivate));
170
171   gobject_class->finalize = g_socket_finalize;
172   gobject_class->dispose = g_socket_dispose;
173   gobject_class->set_property = g_socket_set_property;
174   gobject_class->get_property = g_socket_get_property;
175
176   g_object_class_install_property (gobject_class, PROP_FD,
177                                    g_param_spec_int ("fd",
178                                                      "file descriptor",
179                                                      "the socket's file descriptor",
180                                                      G_MININT,
181                                                      G_MAXINT,
182                                                      -1,
183                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
184
185   g_object_class_install_property (gobject_class, PROP_BLOCKING,
186                                    g_param_spec_boolean ("blocking",
187                                                          "blocking",
188                                                          "whether or not this socket is blocking",
189                                                          TRUE,
190                                                          G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
191
192   g_object_class_install_property (gobject_class, PROP_BACKLOG,
193                                    g_param_spec_int ("backlog",
194                                                      "listen backlog",
195                                                      "outstanding connections in the listen queue",
196                                                      0,
197                                                      SOMAXCONN,
198                                                      10,
199                                                      G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
200
201   g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
202                                    g_param_spec_object ("local-address",
203                                                         "local address",
204                                                         "the local address the socket is bound to",
205                                                         G_TYPE_SOCKET_ADDRESS,
206                                                         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
207
208   g_object_class_install_property (gobject_class, PROP_REMOTE_ADDRESS,
209                                    g_param_spec_object ("remote-address",
210                                                         "remote address",
211                                                         "the remote address the socket is connected to",
212                                                         G_TYPE_SOCKET_ADDRESS,
213                                                         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
214 }
215
216 static void
217 g_socket_init (GSocket *socket)
218 {
219   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, G_TYPE_SOCKET, GSocketPrivate);
220
221   socket->priv->fd = -1;
222   socket->priv->blocking = TRUE;
223   socket->priv->backlog = 10;
224   socket->priv->remote_address = NULL;
225   socket->priv->local_address = NULL;
226 }
227
228 GSocket *
229 g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol, GError **error)
230 {
231   static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT;
232   gint fd, native_domain, native_type, native_protocol;
233
234   switch (domain)
235     {
236       case G_SOCKET_DOMAIN_INET:
237         native_domain = PF_INET;
238         break;
239
240       case G_SOCKET_DOMAIN_INET6:
241         native_domain = PF_INET6;
242         break;
243
244       case G_SOCKET_DOMAIN_UNIX:
245         native_domain = PF_UNIX;
246         break;
247
248       default:
249         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain");
250         return NULL;
251     }
252
253   switch (type)
254     {
255       case G_SOCKET_TYPE_STREAM:
256         native_type = SOCK_STREAM;
257         break;
258
259       case G_SOCKET_TYPE_DATAGRAM:
260         native_type = SOCK_DGRAM;
261         break;
262
263       case G_SOCKET_TYPE_SEQPACKET:
264         native_type = SOCK_SEQPACKET;
265         break;
266
267       default:
268         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type");
269         return NULL;
270     }
271
272   if (protocol == NULL)
273     native_protocol = 0;
274   else
275     {
276       struct protoent *ent;
277       g_static_mutex_lock (&getprotobyname_mutex);
278       if (!(ent = getprotobyname (protocol)))
279         {
280           g_static_mutex_unlock (&getprotobyname_mutex);
281           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol");
282           return NULL;
283         }
284       native_protocol = ent->p_proto;
285       g_static_mutex_unlock (&getprotobyname_mutex);
286     }
287
288   fd = socket(native_domain, native_type, native_protocol);
289
290   if (fd < 0)
291     {
292       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno));
293       return NULL;
294     }
295
296   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, "blocking", TRUE, NULL));
297 }
298
299 GSocket *
300 g_socket_new_from_fd (gint fd)
301 {
302   glong arg;
303   gboolean blocking;
304
305   if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
306     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
307
308   blocking = ((arg & O_NONBLOCK) == 0);
309
310   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, "blocking", blocking, NULL));
311 }
312
313 void
314 g_socket_set_blocking (GSocket  *socket,
315                        gboolean  blocking)
316 {
317   glong arg;
318
319   g_return_if_fail (G_IS_SOCKET (socket));
320
321   if ((arg = fcntl (socket->priv->fd, F_GETFL, NULL)) < 0)
322     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
323
324   arg = blocking ? arg & ~O_NONBLOCK : arg | O_NONBLOCK;
325
326   if (fcntl (socket->priv->fd, F_SETFL, arg) < 0)
327     g_warning ("Error setting socket status flags: %s", g_strerror (errno));
328
329   socket->priv->blocking = blocking;
330 }
331
332 gboolean
333 g_socket_get_blocking (GSocket *socket)
334 {
335   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
336
337   return socket->priv->blocking;
338 }
339
340 void
341 g_socket_set_reuse_address (GSocket  *socket,
342                             gboolean  reuse)
343 {
344   gint value = (gint) reuse;
345
346   g_return_if_fail (G_IS_SOCKET (socket));
347
348   if (setsockopt (socket->priv->fd, SOL_SOCKET, SO_REUSEADDR, (gpointer) &value, sizeof (value)) < 0)
349     g_warning ("error setting reuse address: %s", g_strerror (errno));
350
351   socket->priv->reuse_address = reuse;
352 }
353
354 gboolean
355 g_socket_get_reuse_address (GSocket *socket)
356 {
357   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
358
359   return socket->priv->reuse_address;
360 }
361
362 GSocketAddress *
363 g_socket_get_local_address (GSocket  *socket,
364                             GError  **error)
365 {
366   gchar buffer[256];
367   gsize len = 256;
368
369   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
370
371   if (socket->priv->local_address)
372     return socket->priv->local_address;
373
374   if (getsockname (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
375     {
376       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get local address: %s", g_strerror (errno));
377       return NULL;
378     }
379
380   return (socket->priv->local_address = g_object_ref_sink (g_socket_address_from_native (buffer, len)));
381 }
382
383 GSocketAddress *
384 g_socket_get_remote_address (GSocket  *socket,
385                              GError  **error)
386 {
387   gchar buffer[256];
388   gsize len = 256;
389
390   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
391
392   if (socket->priv->remote_address)
393     return socket->priv->remote_address;
394
395   if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
396     {
397       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get remote address: %s", g_strerror (errno));
398       return NULL;
399     }
400
401   return (socket->priv->remote_address = g_object_ref_sink (g_socket_address_from_native (buffer, len)));
402 }
403
404 gboolean
405 g_socket_listen (GSocket  *socket,
406                  GError  **error)
407 {
408   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
409
410   if (listen (socket->priv->fd, socket->priv->backlog) < 0)
411     {
412       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not listen: %s", g_strerror (errno));
413       return FALSE;
414     }
415
416   return TRUE;
417 }
418
419 gboolean
420 g_socket_bind (GSocket         *socket,
421                GSocketAddress  *address,
422                GError         **error)
423 {
424   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
425
426   {
427     gchar addr[256];
428
429     if (!g_socket_address_to_native (address, addr))
430       return FALSE;
431
432     if (bind (socket->priv->fd, (struct sockaddr *) addr, g_socket_address_native_size (address)) < 0)
433       {
434         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error binding to address: %s", g_strerror (errno));
435         return FALSE;
436       }
437
438     g_object_ref_sink (address);
439
440     socket->priv->local_address = address;
441
442     return TRUE;
443   }
444 }
445
446 GSocket *
447 g_socket_accept (GSocket       *socket,
448                  GError       **error)
449 {
450   gint ret;
451
452   if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
453     {
454       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection: %s", g_strerror (errno));
455       return NULL;
456     }
457
458   return g_socket_new_from_fd (ret);
459 }
460
461 gboolean
462 g_socket_connect (GSocket         *socket,
463                   GSocketAddress  *address,
464                   GError         **error)
465 {
466   gchar buffer[256];
467
468   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
469
470   g_socket_address_to_native (address, buffer);
471
472   if (connect (socket->priv->fd, (struct sockaddr *) buffer, g_socket_address_native_size (address)) < 0)
473     {
474       if (errno == EINPROGRESS)
475         g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, "connection in progress");
476       else
477         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno));
478       return FALSE;
479     }
480
481   socket->priv->remote_address = g_object_ref_sink (address);
482
483   return TRUE;
484 }
485
486 gssize
487 g_socket_receive (GSocket       *socket,
488                   gchar         *buffer,
489                   gsize          size,
490                   GError       **error)
491 {
492   gssize ret;
493
494   g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
495
496   if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0)
497     {
498       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error receiving data: %s", g_strerror (errno));
499       return -1;
500     }
501
502   return ret;
503 }
504
505 gssize
506 g_socket_send (GSocket       *socket,
507                gchar         *buffer,
508                gsize          size,
509                GError       **error)
510 {
511   gssize ret;
512
513   g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
514
515   if ((ret = send (socket->priv->fd, buffer, size, 0)) < 0)
516     {
517       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error sending data: %s", g_strerror (errno));
518       return -1;
519     }
520
521   return ret;
522 }
523
524 void
525 g_socket_close (GSocket *socket)
526 {
527   g_return_if_fail (G_IS_SOCKET (socket));
528
529 #ifdef G_OS_WIN32
530   closesocket (socket->priv->fd);
531 #else
532   close (socket->priv->fd);
533 #endif
534 }
535
536 GSource *
537 g_socket_create_source (GSocket      *socket,
538                         GIOCondition  condition,
539                         GCancellable *cancellable)
540 {
541   g_return_val_if_fail (G_IS_SOCKET (socket) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
542
543   return _g_fd_source_new (socket->priv->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, cancellable);
544 }