1 /* GNet - Networking library
2 * Copyright (C) 2000 David Helder
3 * Copyright (C) 2001 Mark Ferlatte
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * 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
21 #include "gnet-private.h"
22
23 #ifndef GNET_WIN32
24
25 #include "unix.h"
26 #include <errno.h>
27 #include <string.h>
28
29 struct _GUnixSocket
30 {
31 gint sockfd;
32 guint ref_count;
33 GIOChannel *iochannel;
34 struct sockaddr_un sa;
35
36 gboolean server;
37 gboolean abstract; /* Abstract unix socket? */
38 };
39
40 #define PATH(S) (((struct sockaddr_un *) (&(S)->sa))->sun_path)
41
42 #ifndef SUN_LEN
43 #define SUN_LEN(sa_un) \
44 G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + strlen (sa_un->sun_path)
45 #endif
46
47 /* GNET_SUN_LEN: our own version of SUN_LEN that also works for abstract
48 * sockets where SUN_LEN fails because it doesn't take into account the
49 * initial zero in the path string in the case of abstract sockets */
50 #define GNET_SUN_LEN(sa_un) gnet_sun_len(sa_un)
51
52 static gboolean gnet_unix_socket_unlink (const gchar *path);
53
54 static guint
gnet_sun_len(struct sockaddr_un * sa_un)55 gnet_sun_len (struct sockaddr_un *sa_un)
56 {
57 /* normal unix socket */
58 if (sa_un->sun_path[0] != '\0')
59 return SUN_LEN (sa_un);
60
61 /* abstract socket, has a zero byte before the path */
62 return G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + 1
63 + strlen (sa_un->sun_path + 1);
64 }
65
66 static GUnixSocket*
gnet_unix_socket_new_internal(const gchar * path,gboolean abstract)67 gnet_unix_socket_new_internal (const gchar * path, gboolean abstract)
68 {
69 struct sockaddr_un *sa_un;
70 GUnixSocket *s;
71
72 g_return_val_if_fail (path != NULL, NULL);
73
74 #ifndef HAVE_ABSTRACT_SOCKETS
75 /* if abstract unix sockets are not available, create a normal unix socket */
76 abstract = FALSE;
77 #endif
78
79 /* Create socket */
80 s = g_new0 (GUnixSocket, 1);
81 sa_un = (struct sockaddr_un *) &s->sa;
82 s->ref_count = 1;
83 s->server = FALSE;
84 s->sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
85 if (!GNET_IS_SOCKET_VALID (s->sockfd)) {
86 g_warning ("socket(%s) failed: %s", path, g_strerror (errno));
87 g_free(s);
88 return NULL;
89 }
90
91 if (abstract) {
92 sa_un->sun_path[0] = '\0';
93 strncpy (sa_un->sun_path + 1, path, sizeof (sa_un->sun_path) - 2);
94 s->abstract = TRUE;
95 } else {
96 strncpy (sa_un->sun_path, path, sizeof (sa_un->sun_path) - 1);
97 }
98
99 sa_un->sun_family = AF_UNIX;
100 if (connect (s->sockfd, (struct sockaddr*) sa_un, GNET_SUN_LEN (sa_un)) != 0) {
101 g_warning ("connect(%s) failed: %s", path, g_strerror (errno));
102 GNET_CLOSE_SOCKET (s->sockfd);
103 g_free(s);
104 return NULL;
105 }
106
107 return s;
108 }
109
110 /**
111 * gnet_unix_socket_new
112 * @path: path
113 *
114 * Creates a #GUnixSocket and connects to @path. This function will
115 * block to connect. Use this constructor to create a #GUnixSocket
116 * for a client.
117 *
118 * Returns: a new #GUnixSocket; NULL on failure.
119 *
120 **/
121 GUnixSocket*
gnet_unix_socket_new(const gchar * path)122 gnet_unix_socket_new (const gchar * path)
123 {
124 return gnet_unix_socket_new_internal (path, FALSE);
125 }
126
127 /**
128 * gnet_unix_socket_new_abstract
129 * @path: path
130 *
131 * Creates a #GUnixSocket and connects to @path in the abstract
132 * unix socket domain. This function will block to connect. Use this
133 * constructor to create a #GUnixSocket for a client.
134 *
135 * If the abstract unix sockets are not available on the platform in use,
136 * this function will behave like gnet_unix_socket_new().
137 *
138 * Returns: a new #GUnixSocket, or NULL on failure.
139 *
140 * Since: 2.0.8
141 **/
142 GUnixSocket*
gnet_unix_socket_new_abstract(const gchar * path)143 gnet_unix_socket_new_abstract (const gchar * path)
144 {
145 return gnet_unix_socket_new_internal (path, TRUE);
146 }
147
148
149 /**
150 * gnet_unix_socket_delete
151 * @socket: a #GUnixSocket
152 *
153 * Deletes a #GUnixSocket.
154 *
155 **/
156 void
gnet_unix_socket_delete(GUnixSocket * socket)157 gnet_unix_socket_delete (GUnixSocket* socket)
158 {
159 if (socket != NULL)
160 gnet_unix_socket_unref (socket);
161 }
162
163
164 /**
165 * gnet_unix_socket_ref
166 * @socket: a #GUnixSocket
167 *
168 * Adds a reference to a #GUnixSocket.
169 *
170 **/
171 void
gnet_unix_socket_ref(GUnixSocket * socket)172 gnet_unix_socket_ref (GUnixSocket* socket)
173 {
174 g_return_if_fail (socket != NULL);
175
176 socket->ref_count++;
177 }
178
179
180 /**
181 * gnet_unix_socket_unref
182 * @socket: a #GUnixSocket
183 *
184 * Removes a reference from a #GUnixSocket. A #GUnixSocket is
185 * deleted when the reference count reaches 0.
186 *
187 **/
188 void
gnet_unix_socket_unref(GUnixSocket * socket)189 gnet_unix_socket_unref (GUnixSocket* socket)
190 {
191 g_return_if_fail (socket != NULL);
192
193 socket->ref_count--;
194 if (socket->ref_count == 0) {
195 GNET_CLOSE_SOCKET(socket->sockfd); /* Don't care if this fails. */
196 if (socket->iochannel)
197 g_io_channel_unref (socket->iochannel);
198 if (socket->server && !socket->abstract)
199 gnet_unix_socket_unlink (PATH (socket));
200 g_free(socket);
201 }
202 }
203
204
205 /**
206 * gnet_unix_socket_get_io_channel
207 * @socket: a #GUnixSocket
208 *
209 * Gets the #GIOChannel of a #GUnixSocket.
210 *
211 * For a client socket, the #GIOChannel represents the data stream.
212 * Use it like you would any other #GIOChannel.
213 *
214 * For a server socket, however, the #GIOChannel represents the
215 * listening socket. When it's readable, there's a connection
216 * waiting to be accepted.
217 *
218 * Every #GUnixSocket has one and only one #GIOChannel. If you ref
219 * the channel, then you must unref it eventually. Do not close the
220 * channel. The channel is closed by GNet when the socket is
221 * deleted.
222 *
223 * Returns: a #GIOChannel.
224 *
225 **/
226 GIOChannel*
gnet_unix_socket_get_io_channel(GUnixSocket * socket)227 gnet_unix_socket_get_io_channel (GUnixSocket* socket)
228 {
229 g_return_val_if_fail(socket != NULL, NULL);
230
231 if (socket->iochannel == NULL)
232 socket->iochannel = _gnet_io_channel_new (socket->sockfd);
233
234 return socket->iochannel;
235 }
236
237
238 /**
239 * gnet_unix_socket_get_path
240 * @socket: a #GUnixSocket
241 *
242 * Gets the path of a #GUnixSocket.
243 *
244 * Returns: the path.
245 *
246 **/
247 gchar*
gnet_unix_socket_get_path(const GUnixSocket * socket)248 gnet_unix_socket_get_path(const GUnixSocket* socket)
249 {
250 g_return_val_if_fail(socket != NULL, NULL);
251
252 return g_strdup (PATH(socket));
253 }
254
255 static GUnixSocket*
gnet_unix_socket_server_new_internal(const gchar * path,gboolean abstract)256 gnet_unix_socket_server_new_internal (const gchar * path, gboolean abstract)
257 {
258 struct sockaddr_un *sa_un;
259 GUnixSocket *s;
260 gint flags;
261 socklen_t n;
262
263 g_return_val_if_fail (path != NULL, NULL);
264
265 #ifndef HAVE_ABSTRACT_SOCKETS
266 /* if abstract unix sockets are not available, create a normal unix socket */
267 abstract = FALSE;
268 #endif
269
270 s = g_new0 (GUnixSocket, 1);
271 sa_un = (struct sockaddr_un *) &s->sa;
272 sa_un->sun_family = AF_UNIX;
273 s->ref_count = 1;
274 s->server = TRUE;
275
276 if (abstract) {
277 sa_un->sun_path[0] = '\0';
278 strncpy (sa_un->sun_path + 1, path, sizeof (sa_un->sun_path) - 2);
279 s->abstract = TRUE;
280 } else {
281 strncpy (sa_un->sun_path, path, sizeof (sa_un->sun_path) - 1);
282 if (!gnet_unix_socket_unlink (PATH (s)))
283 goto error;
284 }
285
286 s->sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
287 if (!GNET_IS_SOCKET_VALID(s->sockfd)) {
288 g_warning ("socket(%s) failed: %s", path, g_strerror (errno));
289 goto error;
290 }
291
292 flags = fcntl(s->sockfd, F_GETFL, 0);
293 if (flags == -1) {
294 g_warning ("fcntl(%s) failed: %s", path, g_strerror (errno));
295 goto error;
296 }
297
298 /* Make the socket non-blocking */
299 if (fcntl(s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
300 g_warning ("fcntl(%s) failed: %s", path, g_strerror (errno));
301 goto error;
302 }
303
304 if (bind (s->sockfd, (struct sockaddr*) sa_un, GNET_SUN_LEN (sa_un)) != 0)
305 goto error;
306
307 /* Get the socket name FIXME (why? -DAH) */
308 n = sizeof(s->sa);
309 if (getsockname (s->sockfd, (struct sockaddr*) &s->sa, &n) != 0)
310 goto error;
311
312 if (listen (s->sockfd, 10) != 0)
313 goto error;
314
315 return s;
316
317 error:
318 gnet_unix_socket_delete (s);
319 return NULL;
320 }
321
322 /**
323 * gnet_unix_socket_server_new
324 * @path: path
325 *
326 * Creates a #GUnixSocket bound to @path. Use this constructor to
327 * create a #GUnixSocket for a server.
328 *
329 * Returns: a new #GUnixSocket; NULL on error.
330 *
331 **/
332 GUnixSocket*
gnet_unix_socket_server_new(const gchar * path)333 gnet_unix_socket_server_new (const gchar * path)
334 {
335 return gnet_unix_socket_server_new_internal (path, FALSE);
336 }
337
338 /**
339 * gnet_unix_socket_server_new_abstract
340 * @path: path
341 *
342 * Creates a #GUnixSocket bound to @path in the abstract unix socket
343 * domain. Use this constructor to create a #GUnixSocket for a
344 * server.
345 *
346 * If the abstract unix sockets are not available on the platform in use,
347 * this function will behave the same as gnet_unix_socket_server_new().
348 *
349 * Returns: a new #GUnixSocket, or NULL on error.
350 *
351 *
352 * Since: 2.0.8
353 **/
354 GUnixSocket*
gnet_unix_socket_server_new_abstract(const gchar * path)355 gnet_unix_socket_server_new_abstract (const gchar * path)
356 {
357 return gnet_unix_socket_server_new_internal (path, TRUE);
358 }
359
360 /**
361 * gnet_unix_socket_server_accept
362 * @socket: a #GUnixSocket
363 *
364 * Accepts a connection from a #GUnixSocket. The socket must have
365 * been created using gnet_unix_socket_server_new(). This function
366 * will block. Even if the socket's #GIOChannel is readable, the
367 * function may still block.
368 *
369 * Returns: a new #GUnixSocket representing a new connection; NULL on
370 * error.
371 *
372 **/
373 GUnixSocket*
gnet_unix_socket_server_accept(const GUnixSocket * socket)374 gnet_unix_socket_server_accept (const GUnixSocket *socket)
375 {
376 gint sockfd;
377 struct sockaddr sa;
378 fd_set fdset;
379 socklen_t n;
380 GUnixSocket *s;
381
382 g_return_val_if_fail(socket != NULL, NULL);
383
384 try_again:
385 FD_ZERO(&fdset);
386 FD_SET(socket->sockfd, &fdset);
387
388 if (select(socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
389 if (errno == EINTR)
390 goto try_again;
391 return NULL;
392 }
393 n = sizeof(s->sa);
394 if ((sockfd = accept(socket->sockfd, &sa, &n)) == -1) {
395 if (errno == EWOULDBLOCK ||
396 errno == ECONNABORTED ||
397 #ifdef EPROTO /* OpenBSD does not have EPROTO */
398 errno == EPROTO ||
399 #endif /* EPROTO */
400 errno == EINTR)
401 goto try_again;
402 return NULL;
403 }
404 s = g_new0(GUnixSocket, 1);
405 s->ref_count = 1;
406 s->sockfd = sockfd;
407 memcpy(&s->sa, &sa, sizeof(s->sa));
408 return s;
409 }
410
411
412 /**
413 * gnet_unix_socket_server_accept_nonblock
414 * @socket: a #GUnixSocket
415 *
416 * Accepts a connection from a #GUnixSocket without blocking. The
417 * socket must have been created using gnet_unix_socket_server_new().
418 *
419 * Note that if the socket's #GIOChannel is readable, then there is
420 * PROBABLY a new connection. It is possible for the connection
421 * to close by the time this function is called, so it may return
422 * NULL.
423 *
424 * Returns: a new #GUnixSocket representing a new connection; NULL
425 * otherwise.
426 *
427 **/
428 GUnixSocket*
gnet_unix_socket_server_accept_nonblock(const GUnixSocket * socket)429 gnet_unix_socket_server_accept_nonblock (const GUnixSocket *socket)
430 {
431 gint sockfd;
432 struct sockaddr sa;
433 fd_set fdset;
434 socklen_t n;
435 GUnixSocket *s;
436 struct timeval tv = {0, 0};
437
438 g_return_val_if_fail (socket != NULL, NULL);
439
440 try_again:
441 FD_ZERO(&fdset);
442 FD_SET(socket->sockfd, &fdset);
443
444 if(select(socket->sockfd + 1, &fdset, NULL, NULL, &tv) == -1) {
445 if (errno == EINTR)
446 goto try_again;
447 return NULL;
448 }
449
450 n = sizeof(sa);
451
452 if ((sockfd = accept(socket->sockfd, &sa, &n)) == -1) {
453 /* If we get an error, return. We don't want to try again
454 as we do in gnet_unix_socket_server_accept() - it might
455 cause a block. */
456 return NULL;
457 }
458
459 s = g_new0(GUnixSocket, 1);
460 s->ref_count = 1;
461 s->sockfd = sockfd;
462 memcpy(&s->sa, &sa, sizeof(s->sa));
463
464 return s;
465 }
466
467 static gboolean
gnet_unix_socket_unlink(const gchar * path)468 gnet_unix_socket_unlink(const gchar * path)
469 {
470 struct stat stbuf;
471
472 g_return_val_if_fail (path != NULL, FALSE);
473
474 if (stat (path, &stbuf) == 0) {
475 if (S_ISSOCK(stbuf.st_mode)) {
476 if (unlink(path) == 0) {
477 return TRUE;
478 } else {
479 /* Can't unlink */
480 return FALSE;
481 }
482 } else {
483 /* path is not a socket */
484 return FALSE;
485 }
486 } else if (errno == ENOENT) {
487 /* File doesn't exist, so we're okay */
488 return TRUE;
489 }
490 return FALSE;
491 }
492
493 #endif /* !GNET_WIN32 */
494