Make things inherit from GInitiallyUnowned, some more socket changes
[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
28 #include <string.h>
29 #ifndef G_OS_WIN32
30 # include <netinet/in.h>
31 # include <arpa/inet.h>
32 # include <netdb.h>
33 # include <fcntl.h>
34 #else
35
36 #endif
37 #include <errno.h>
38
39 #include "ginetaddress.h"
40 #include "ginet4address.h"
41 #include "ginet6address.h"
42 #include "gsocket.h"
43 #include "gnioerror.h"
44 #include "ginetsocketaddress.h"
45
46 G_DEFINE_TYPE (GSocket, g_socket, G_TYPE_OBJECT);
47
48 enum
49 {
50   PROP_0,
51   PROP_FD
52 };
53
54 struct _GSocketPrivate
55 {
56   gint fd;
57   gboolean blocking;
58 };
59
60 static void
61 g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
62 {
63   GSocket *socket = G_SOCKET (object);
64
65   switch (prop_id)
66     {
67       case PROP_FD:
68         g_value_set_int (value, socket->priv->fd);
69         break;
70
71       default:
72         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
73     }
74 }
75
76 static void
77 g_socket_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
78 {
79   GSocket *socket = G_SOCKET (object);
80
81   switch (prop_id)
82     {
83       case PROP_FD:
84         socket->priv->fd = g_value_get_int (value);
85         break;
86
87       default:
88         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
89     }
90 }
91
92 static void
93 g_socket_finalize (GObject *object)
94 {
95   GSocket *socket G_GNUC_UNUSED = G_SOCKET (object);
96
97   if (G_OBJECT_CLASS (g_socket_parent_class)->finalize)
98     (*G_OBJECT_CLASS (g_socket_parent_class)->finalize) (object);
99 }
100
101 static void
102 g_socket_dispose (GObject *object)
103 {
104   GSocket *socket G_GNUC_UNUSED = G_SOCKET (object);;
105
106   if (G_OBJECT_CLASS (g_socket_parent_class)->dispose)
107     (*G_OBJECT_CLASS (g_socket_parent_class)->dispose) (object);
108 }
109
110 static void
111 g_socket_class_init (GSocketClass *klass)
112 {
113   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
114
115   g_type_class_add_private (klass, sizeof (GSocketPrivate));
116
117   gobject_class->finalize = g_socket_finalize;
118   gobject_class->dispose = g_socket_dispose;
119   gobject_class->set_property = g_socket_set_property;
120   gobject_class->get_property = g_socket_get_property;
121 }
122
123 static void
124 g_socket_init (GSocket *socket)
125 {
126   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, G_TYPE_SOCKET, GSocketPrivate);
127
128   socket->priv->fd = -1;
129   socket->priv->blocking = TRUE;
130 }
131
132 GSocket *
133 g_socket_new (gint domain, gint type, gint protocol)
134 {
135   gint sock;
136
137   sock = socket(domain, type, protocol);
138
139   if (sock < 0)
140     return NULL;
141
142   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", sock, NULL));
143 }
144
145 GSocket *
146 g_socket_new_from_fd (gint fd)
147 {
148   return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL));
149 }
150
151 void
152 g_socket_set_blocking (GSocket  *socket,
153                        gboolean  blocking)
154 {
155   glong arg;
156
157   g_return_if_fail (G_IS_SOCKET (socket));
158
159   if ((arg = fcntl (socket->priv->fd, F_GETFL, NULL)) < 0)
160     g_warning ("Error getting socket status flags: %s", g_strerror (errno));
161
162   arg = blocking ? arg | O_NONBLOCK : arg & ~O_NONBLOCK;
163
164   if (fcntl (socket->priv->fd, F_SETFL, arg) < 0)
165     g_warning ("Error setting socket status flags: %s", g_strerror (errno));
166 }
167
168 void
169 g_socket_listen (GSocket *socket,
170                  gint     backlog)
171 {
172   g_return_if_fail (G_IS_SOCKET (socket));
173
174   listen (socket->priv->fd, backlog);
175 }
176
177 gboolean
178 g_socket_bind (GSocket         *socket,
179                GSocketAddress  *address,
180                GError         **error)
181 {
182   g_return_val_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address), FALSE);
183
184   {
185     gchar addr[g_socket_address_native_size (address)];
186
187     if (!g_socket_address_to_native (address, addr))
188       return FALSE;
189
190     if (bind (socket->priv->fd, (struct sockaddr *) addr, g_socket_address_native_size (address)) < 0)
191       {
192         // TODO: set error
193         return FALSE;
194       }
195
196     g_object_unref (address);
197
198     return TRUE;
199   }
200 }
201
202 gboolean
203 g_socket_connect (GSocket         *socket,
204                   GSocketAddress  *address,
205                   GCancellable    *cancellable,
206                   GError         **error)
207 {
208   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
209 /*
210   if (connect () < 0)
211     {
212       if (errno == EINPROGRESS)
213         g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, "connection in progress");
214       else
215         g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno));
216       return FALSE;
217     }
218 */
219   return TRUE;
220 }
221
222 void
223 g_socket_connect_async (GSocket             *socket,
224                         GSocketAddress      *address,
225                         GCancellable        *cancellable,
226                         GAsyncReadyCallback *callback,
227                         gpointer             user_data)
228 {
229
230 }
231
232 gboolean
233 g_socket_connect_finish (GSocket       *socket,
234                          GAsyncResult  *result,
235                          GError       **error)
236 {
237   return FALSE;
238 }