69a1b5cecb783fafa1f3ebdc3d78ce3520a6078d
[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_REUSE_ADDRESS,
202                                    g_param_spec_boolean ("reuse-address",
203                                                          "reuse address",
204                                                          "allow reuse of local addresses when binding",
205                                                          FALSE,
206                                                          G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
207
208   g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
209                                    g_param_spec_object ("local-address",
210                                                         "local address",
211                                                         "the local address the socket is bound to",
212                                                         G_TYPE_SOCKET_ADDRESS,
213                                                         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
214
215   g_object_class_install_property (gobject_class, PROP_REMOTE_ADDRESS,
216                                    g_param_spec_object ("remote-address",
217                                                         "remote address",
218                                                         "the remote address the socket is connected to",
219                                                         G_TYPE_SOCKET_ADDRESS,
220                                                         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
221 }
222
223 static void
224 g_socket_init (GSocket *socket)
225 {
226   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, G_TYPE_SOCKET, GSocketPrivate);
227
228   socket->priv->fd = -1;
229   socket->priv->blocking = TRUE;
230   socket->priv->backlog = 10;
231   socket->priv->remote_address = NULL;
232   socket->priv->local_address = NULL;
233 }
234
235 GSocket *
236 g_socket_new (GSocketDomain domain, GSocketType type, const gchar *protocol, GError **error)
237 {
238   static GStaticMutex getprotobyname_mutex = G_STATIC_MUTEX_INIT;
239   gint fd, native_domain, native_type, native_protocol;
240
241   switch (domain)
242     {
243       case G_SOCKET_DOMAIN_INET:
244         native_domain = PF_INET;
245         break;
246
247       case G_SOCKET_DOMAIN_INET6:
248         native_domain = PF_INET6;
249         break;
250
251       case G_SOCKET_DOMAIN_UNIX:
252         native_domain = PF_UNIX;
253         break;
254
255       default:
256         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket domain");
257         return NULL;
258     }
259
260   switch (type)
261     {
262       case G_SOCKET_TYPE_STREAM:
263         native_type = SOCK_STREAM;
264         break;
265
266       case G_SOCKET_TYPE_DATAGRAM:
267         native_type = SOCK_DGRAM;
268         break;
269
270       case G_SOCKET_TYPE_SEQPACKET:
271         native_type = SOCK_SEQPACKET;
272         break;
273
274       default:
275         g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket type");
276         return NULL;
277     }
278
279   if (protocol == NULL)
280     native_protocol = 0;
281   else
282     {
283       struct protoent *ent;
284       g_static_mutex_lock (&getprotobyname_mutex);
285       if (!(ent = getprotobyname (protocol)))
286         {
287           g_static_mutex_unlock (&getprotobyname_mutex);
288           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported socket protocol");
289           return NULL;
290         }
291       native_protocol = ent->p_proto;
292       g_static_mutex_unlock (&getprotobyname_mutex);
293     }
294
295   fd = socket(native_domain, native_type, native_protocol);
296
297   if (fd < 0)
298     {
299       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "unable to create socket: %s", g_strerror (errno));
300       return NULL;
301     }
302
303   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, "blocking", TRUE, NULL));
304 }
305
306 GSocket *
307 g_socket_new_from_fd (gint fd)
308 {
309   glong arg;
310   gboolean blocking;
311
312   if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
313     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
314
315   blocking = ((arg & O_NONBLOCK) == 0);
316
317   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, "blocking", blocking, NULL));
318 }
319
320 void
321 g_socket_set_blocking (GSocket  *socket,
322                        gboolean  blocking)
323 {
324   glong arg;
325
326   g_return_if_fail (G_IS_SOCKET (socket));
327
328   if ((arg = fcntl (socket->priv->fd, F_GETFL, NULL)) < 0)
329     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
330
331   arg = blocking ? arg & ~O_NONBLOCK : arg | O_NONBLOCK;
332
333   if (fcntl (socket->priv->fd, F_SETFL, arg) < 0)
334     g_warning ("Error setting socket status flags: %s", g_strerror (errno));
335
336   socket->priv->blocking = blocking;
337 }
338
339 gboolean
340 g_socket_get_blocking (GSocket *socket)
341 {
342   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
343
344   return socket->priv->blocking;
345 }
346
347 void
348 g_socket_set_reuse_address (GSocket  *socket,
349                             gboolean  reuse)
350 {
351   gint value = (gint) reuse;
352
353   g_return_if_fail (G_IS_SOCKET (socket));
354
355   if (setsockopt (socket->priv->fd, SOL_SOCKET, SO_REUSEADDR, (gpointer) &value, sizeof (value)) < 0)
356     g_warning ("error setting reuse address: %s", g_strerror (errno));
357
358   socket->priv->reuse_address = reuse;
359 }
360
361 gboolean
362 g_socket_get_reuse_address (GSocket *socket)
363 {
364   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
365
366   return socket->priv->reuse_address;
367 }
368
369 GSocketAddress *
370 g_socket_get_local_address (GSocket  *socket,
371                             GError  **error)
372 {
373   gchar buffer[256];
374   gsize len = 256;
375
376   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
377
378   if (socket->priv->local_address)
379     return socket->priv->local_address;
380
381   if (getsockname (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
382     {
383       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get local address: %s", g_strerror (errno));
384       return NULL;
385     }
386
387   return (socket->priv->local_address = g_object_ref_sink (g_socket_address_from_native (buffer, len)));
388 }
389
390 GSocketAddress *
391 g_socket_get_remote_address (GSocket  *socket,
392                              GError  **error)
393 {
394   gchar buffer[256];
395   gsize len = 256;
396
397   g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
398
399   if (socket->priv->remote_address)
400     return socket->priv->remote_address;
401
402   if (getpeername (socket->priv->fd, (struct sockaddr *) buffer, &len) < 0)
403     {
404       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get remote address: %s", g_strerror (errno));
405       return NULL;
406     }
407
408   return (socket->priv->remote_address = g_object_ref_sink (g_socket_address_from_native (buffer, len)));
409 }
410
411 gboolean
412 g_socket_listen (GSocket  *socket,
413                  GError  **error)
414 {
415   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
416
417   if (listen (socket->priv->fd, socket->priv->backlog) < 0)
418     {
419       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not listen: %s", g_strerror (errno));
420       return FALSE;
421     }
422
423   return TRUE;
424 }
425
426 gboolean
427 g_socket_bind (GSocket         *socket,
428                GSocketAddress  *address,
429                GError         **error)
430 {
431   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
432
433   {
434     gchar addr[256];
435
436     if (!g_socket_address_to_native (address, addr))
437       return FALSE;
438
439     if (bind (socket->priv->fd, (struct sockaddr *) addr, g_socket_address_native_size (address)) < 0)
440       {
441         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error binding to address: %s", g_strerror (errno));
442         return FALSE;
443       }
444
445     g_object_ref_sink (address);
446
447     socket->priv->local_address = address;
448
449     return TRUE;
450   }
451 }
452
453 GSocket *
454 g_socket_accept (GSocket       *socket,
455                  GError       **error)
456 {
457   gint ret;
458
459   if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
460     {
461       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error accepting connection: %s", g_strerror (errno));
462       return NULL;
463     }
464
465   return g_socket_new_from_fd (ret);
466 }
467
468 gboolean
469 g_socket_connect (GSocket         *socket,
470                   GSocketAddress  *address,
471                   GError         **error)
472 {
473   gchar buffer[256];
474
475   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
476
477   g_socket_address_to_native (address, buffer);
478
479   if (connect (socket->priv->fd, (struct sockaddr *) buffer, g_socket_address_native_size (address)) < 0)
480     {
481       if (errno == EINPROGRESS)
482         g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, "connection in progress");
483       else
484         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno));
485       return FALSE;
486     }
487
488   socket->priv->remote_address = g_object_ref_sink (address);
489
490   return TRUE;
491 }
492
493 gssize
494 g_socket_receive (GSocket       *socket,
495                   gchar         *buffer,
496                   gsize          size,
497                   GError       **error)
498 {
499   gssize ret;
500
501   g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
502
503   if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0)
504     {
505       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error receiving data: %s", g_strerror (errno));
506       return -1;
507     }
508
509   return ret;
510 }
511
512 gssize
513 g_socket_send (GSocket       *socket,
514                gchar         *buffer,
515                gsize          size,
516                GError       **error)
517 {
518   gssize ret;
519
520   g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
521
522   if ((ret = send (socket->priv->fd, buffer, size, 0)) < 0)
523     {
524       g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error sending data: %s", g_strerror (errno));
525       return -1;
526     }
527
528   return ret;
529 }
530
531 void
532 g_socket_close (GSocket *socket)
533 {
534   g_return_if_fail (G_IS_SOCKET (socket));
535
536 #ifdef G_OS_WIN32
537   closesocket (socket->priv->fd);
538 #else
539   close (socket->priv->fd);
540 #endif
541 }
542
543 GSource *
544 g_socket_create_source (GSocket      *socket,
545                         GIOCondition  condition,
546                         GCancellable *cancellable)
547 {
548   g_return_val_if_fail (G_IS_SOCKET (socket) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
549
550   return _g_fd_source_new (socket->priv->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, cancellable);
551 }