Consider existing addresses with a zero refcount valid to return (with an
[platform/upstream/libsoup.git] / libsoup / soup-socket.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-socket.c: Platform neutral socket networking code.
4  *
5  * Authors:
6  *      David Helder  (dhelder@umich.edu)
7  *      Alex Graveley (alex@ximian.com)
8  *
9  * Original code compliments of David Helder's GNET Networking Library, and is
10  * Copyright (C) 2000  David Helder & Andrew Lanoix.
11  *
12  * All else Copyright (C) 2000, Ximian, Inc.
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #include <config.h>
17 #endif
18
19 #include <fcntl.h>
20 #include <glib.h>
21 #include <string.h>
22
23 #include "soup-private.h"
24 #include "soup-socket.h"
25
26 #ifdef SOUP_WIN32
27 #  define socklen_t gint32
28 #  define SOUP_CLOSE_SOCKET(fd) closesocket(fd)
29 #  define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_win32_new_stream_socket(fd)
30 #  ifndef INET_ADDRSTRLEN
31 #    define INET_ADDRSTRLEN 16
32 #    define INET6_ADDRSTRLEN 46
33 #  endif
34 #else
35 #  include <unistd.h>
36 #  ifndef socklen_t
37 #    define socklen_t size_t
38 #  endif
39 #  define SOUP_CLOSE_SOCKET(fd) close(fd)
40 #  define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_unix_new(fd)
41 #endif
42
43 #define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
44
45 typedef struct {
46         SoupSocketConnectFn  func;
47         gpointer             data;
48
49         gpointer             inetaddr_id;
50         gpointer             tcp_id;
51 } SoupSocketConnectState;
52
53 static void
54 soup_address_new_sync_cb (SoupAddress *addr,
55                           SoupAddressStatus  status,
56                           gpointer           user_data)
57 {
58         SoupAddress **ret = user_data;
59         *ret = addr;
60 }
61
62 SoupAddress *
63 soup_address_new_sync (const gchar *name, const gint port)
64 {
65         SoupAddress *ret = (SoupAddress *) 0xdeadbeef;
66
67         soup_address_new (name, port, soup_address_new_sync_cb, &ret);
68
69         while (1) {
70                 g_main_iteration (TRUE);
71                 if (ret != (SoupAddress *) 0xdeadbeef) return ret;
72         }
73
74         return ret;
75 }
76
77 /**
78  * soup_address_ref
79  * @ia: SoupAddress to reference
80  *
81  * Increment the reference counter of the SoupAddress.
82  **/
83 void
84 soup_address_ref (SoupAddress* ia)
85 {
86         g_return_if_fail (ia != NULL);
87
88         ++ia->ref_count;
89 }
90
91 /**
92  * soup_address_copy
93  * @ia: SoupAddress to copy
94  *
95  * Creates a copy of the given SoupAddress
96  **/
97 SoupAddress *
98 soup_address_copy (SoupAddress* ia)
99 {
100         SoupAddress* new_ia;
101         g_return_val_if_fail (ia != NULL, NULL);
102
103         new_ia = g_new0(SoupAddress, 1);
104         new_ia->ref_count = 1;
105
106         new_ia->name = g_strdup (ia->name);
107         memcpy (&new_ia->sa, &ia->sa, sizeof(struct sockaddr));
108
109         return new_ia;
110 }
111
112 static void
113 soup_address_get_name_sync_cb (SoupAddress       *addr,
114                                SoupAddressStatus  status,
115                                const char        *name,
116                                gpointer           user_data)
117 {
118         const char **ret = user_data;
119         *ret = name;
120 }
121
122 const gchar *
123 soup_address_get_name_sync (SoupAddress *addr)
124 {
125         const char *ret = (const char *) 0xdeadbeef;
126
127         soup_address_get_name (addr, 
128                                soup_address_get_name_sync_cb, 
129                                (gpointer) &ret);
130
131         while (1) {
132                 g_main_iteration (TRUE);
133                 if (ret != (const char *) 0xdeadbeef) return ret;
134         }
135
136         return ret;
137 }
138
139 /**
140  * soup_address_get_canonical_name:
141  * @ia: Address to get the canonical name of.
142  *
143  * Get the "canonical" name of an address (eg, for IP4 the dotted
144  * decimal name 141.213.8.59).
145  *
146  * Returns: NULL if there was an error.  The caller is responsible
147  * for deleting the returned string.
148  **/
149 gchar*
150 soup_address_get_canonical_name (SoupAddress* ia)
151 {
152         gchar buffer [INET_ADDRSTRLEN]; /* defined in netinet/in.h */
153         guchar* p = (guchar*) &(SOUP_SOCKADDR_IN(ia->sa).sin_addr);
154
155         g_return_val_if_fail (ia != NULL, NULL);
156
157         g_snprintf(buffer,
158                    sizeof (buffer),
159                    "%d.%d.%d.%d",
160                    p [0],
161                    p [1],
162                    p [2],
163                    p [3]);
164
165         return g_strdup (buffer);
166 }
167
168 /**
169  * soup_address_get_port:
170  * @ia: Address to get the port number of.
171  *
172  * Get the port number.
173  * Returns: the port number.
174  */
175 gint
176 soup_address_get_port (const SoupAddress* ia)
177 {
178         g_return_val_if_fail(ia != NULL, -1);
179
180         return (gint) g_ntohs (((struct sockaddr_in*) &ia->sa)->sin_port);
181 }
182
183 /**
184  * soup_address_set_port:
185  * @ia: Address to set the port number of.
186  * @port: New port number
187  *
188  * Set the port number.
189  **/
190 void
191 soup_address_set_port (const SoupAddress* ia, guint port)
192 {
193         g_return_if_fail (ia != NULL);
194
195         ((struct sockaddr_in*) &ia->sa)->sin_port = g_htons (port);
196 }
197
198 /**
199  * soup_address_hash:
200  * @p: Pointer to an #SoupAddress.
201  *
202  * Hash the address.  This is useful for glib containers.
203  *
204  * Returns: hash value.
205  **/
206 guint
207 soup_address_hash (const gpointer p)
208 {
209         const SoupAddress* ia;
210         guint32 port;
211         guint32 addr;
212
213         g_assert(p != NULL);
214
215         ia = (const SoupAddress*) p;
216         /* We do pay attention to network byte order just in case the hash
217            result is saved or sent to a different host.  */
218         port = (guint32) g_ntohs (((struct sockaddr_in*) &ia->sa)->sin_port);
219         addr = g_ntohl (((struct sockaddr_in*) &ia->sa)->sin_addr.s_addr);
220
221         return (port ^ addr);
222 }
223
224 /**
225  * soup_address_equal:
226  * @p1: Pointer to first #SoupAddress.
227  * @p2: Pointer to second #SoupAddress.
228  *
229  * Compare two #SoupAddress's.
230  *
231  * Returns: 1 if they are the same; 0 otherwise.
232  **/
233 gint
234 soup_address_equal (const gpointer p1, const gpointer p2)
235 {
236         const SoupAddress* ia1 = (const SoupAddress*) p1;
237         const SoupAddress* ia2 = (const SoupAddress*) p2;
238
239         g_assert(p1 != NULL && p2 != NULL);
240
241         /* Note network byte order doesn't matter */
242         return ((SOUP_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==
243                  SOUP_SOCKADDR_IN(ia2->sa).sin_addr.s_addr) &&
244                 (SOUP_SOCKADDR_IN(ia1->sa).sin_port ==
245                  SOUP_SOCKADDR_IN(ia2->sa).sin_port));
246 }
247
248 /**
249  * soup_address_noport_equal:
250  * @p1: Pointer to first SoupAddress.
251  * @p2: Pointer to second SoupAddress.
252  *
253  * Compare two #SoupAddress's, but does not compare the port numbers.
254  *
255  * Returns: 1 if they are the same; 0 otherwise.
256  **/
257 gint
258 soup_address_noport_equal (const gpointer p1, const gpointer p2)
259 {
260         const SoupAddress* ia1 = (const SoupAddress*) p1;
261         const SoupAddress* ia2 = (const SoupAddress*) p2;
262
263         g_assert (p1 != NULL && p2 != NULL);
264
265         /* Note network byte order doesn't matter */
266         return (SOUP_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==
267                 SOUP_SOCKADDR_IN(ia2->sa).sin_addr.s_addr);
268 }
269
270 /**
271  * soup_address_gethostaddr:
272  *
273  * Get the primary host's #SoupAddress.
274  *
275  * Returns: the #SoupAddress of the host; NULL if there was an error.
276  * The caller is responsible for deleting the returned #SoupAddress.
277  **/
278 SoupAddress *
279 soup_address_gethostaddr (void)
280 {
281         gchar* name;
282         struct sockaddr_in* sa_in, sa;
283         SoupAddress* ia = NULL;
284
285         name = soup_address_gethostname ();
286
287         if (name && soup_gethostbyname (name, &sa, NULL)) {
288                 ia = g_new0 (SoupAddress, 1);
289                 ia->name = g_strdup (name);
290                 ia->ref_count = 1;
291
292                 sa_in = (struct sockaddr_in*) &ia->sa;
293                 sa_in->sin_family = AF_INET;
294                 sa_in->sin_port = 0;
295                 memcpy (&sa_in->sin_addr, &sa.sin_addr, 4);
296         }
297
298         return ia;
299 }
300
301
302 static void
303 soup_socket_connect_tcp_cb (SoupSocket* socket,
304                             SoupSocketConnectStatus status,
305                             gpointer data)
306 {
307         SoupSocketConnectState* state = (SoupSocketConnectState*) data;
308
309         if (status == SOUP_SOCKET_NEW_STATUS_OK)
310                 (*state->func) (socket,
311                                 SOUP_SOCKET_CONNECT_ERROR_NONE,
312                                 state->data);
313         else
314                 (*state->func) (NULL,
315                                 SOUP_SOCKET_CONNECT_ERROR_NETWORK,
316                                 state->data);
317
318         g_free (state);
319 }
320
321 static void
322 soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
323                                  SoupAddressStatus status,
324                                  gpointer data)
325 {
326         SoupSocketConnectState* state = (SoupSocketConnectState*) data;
327
328         if (status == SOUP_ADDRESS_STATUS_OK) {
329                 state->inetaddr_id = NULL;
330                 state->tcp_id = soup_socket_new (inetaddr,
331                                                  soup_socket_connect_tcp_cb,
332                                                  state);
333                 soup_address_unref (inetaddr);
334         } else {
335                 (*state->func) (NULL,
336                                 SOUP_SOCKET_CONNECT_ERROR_ADDR_RESOLVE,
337                                 state->data);
338                 g_free (state);
339         }
340 }
341
342 /**
343  * soup_socket_connect:
344  * @hostname: Name of host to connect to
345  * @port: Port to connect to
346  * @func: Callback function
347  * @data: User data passed when callback function is called.
348  *
349  * A quick and easy non-blocking #SoupSocket constructor.  This
350  * connects to the specified address and port and then calls the
351  * callback with the data.  Use this function when you're a client
352  * connecting to a server and you don't want to block or mess with
353  * #SoupAddress's.  It may call the callback before the function
354  * returns.  It will call the callback if there is a failure.
355  *
356  * Returns: ID of the connection which can be used with
357  * soup_socket_connect_cancel() to cancel it; NULL on
358  * failure.
359  **/
360 SoupSocketConnectId
361 soup_socket_connect (const gchar*        hostname,
362                      const gint          port,
363                      SoupSocketConnectFn func,
364                      gpointer            data)
365 {
366         SoupSocketConnectState* state;
367         gpointer id;
368
369         g_return_val_if_fail (hostname != NULL, NULL);
370         g_return_val_if_fail (func != NULL, NULL);
371
372         state = g_new0 (SoupSocketConnectState, 1);
373         state->func = func;
374         state->data = data;
375
376         id = soup_address_new (hostname,
377                                port,
378                                soup_socket_connect_inetaddr_cb,
379                                state);
380
381         /* Note that soup_address_new can fail immediately and call
382            our callback which will delete the state.  The users callback
383            would be called in the process. */
384
385         if (id == NULL) return NULL;
386
387         state->inetaddr_id = id;
388
389         return state;
390 }
391
392 /**
393  * soup_socket_connect_cancel:
394  * @id: Id of the connection.
395  *
396  * Cancel an asynchronous connection that was started with
397  * soup_socket_connect().
398  */
399 void
400 soup_socket_connect_cancel (SoupSocketConnectId id)
401 {
402         SoupSocketConnectState* state = (SoupSocketConnectState*) id;
403
404         g_return_if_fail (state != NULL);
405
406         if (state->inetaddr_id)
407                 soup_address_new_cancel (state->inetaddr_id);
408         else if (state->tcp_id)
409                 soup_socket_new_cancel (state->tcp_id);
410
411         g_free (state);
412 }
413
414 static void
415 soup_socket_connect_sync_cb (SoupSocket              *socket,
416                              SoupSocketConnectStatus  status,
417                              gpointer                 data)
418 {
419         SoupSocket **ret = data;
420         *ret = socket;
421 }
422
423 SoupSocket *
424 soup_socket_connect_sync (const gchar *name,
425                           const gint   port)
426 {
427         SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
428
429         soup_socket_connect (name, port, soup_socket_connect_sync_cb, &ret);
430
431         while (1) {
432                 g_main_iteration (TRUE);
433                 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
434         }
435
436         return ret;
437 }
438
439 static void
440 soup_socket_new_sync_cb (SoupSocket*         socket,
441                          SoupSocketNewStatus status,
442                          gpointer            data)
443 {
444         SoupSocket **ret = data;
445         *ret = socket;
446 }
447
448 SoupSocket *
449 soup_socket_new_sync (SoupAddress *addr)
450 {
451         SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
452
453         soup_socket_new (addr, soup_socket_new_sync_cb, &ret);
454
455         while (1) {
456                 g_main_iteration (TRUE);
457                 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
458         }
459
460         return ret;
461 }
462
463 /**
464  * soup_socket_ref
465  * @s: SoupSocket to reference
466  *
467  * Increment the reference counter of the SoupSocket.
468  **/
469 void
470 soup_socket_ref (SoupSocket* s)
471 {
472         g_return_if_fail (s != NULL);
473
474         ++s->ref_count;
475 }
476
477 /**
478  * soup_socket_unref
479  * @s: #SoupSocket to unreference
480  *
481  * Remove a reference from the #SoupSocket.  When reference count
482  * reaches 0, the socket is deleted.
483  **/
484 void
485 soup_socket_unref (SoupSocket* s)
486 {
487         g_return_if_fail(s != NULL);
488
489         --s->ref_count;
490
491         if (s->ref_count == 0) {
492                 SOUP_CLOSE_SOCKET (s->sockfd);
493                 if (s->addr) soup_address_unref (s->addr);
494                 if (s->iochannel) g_io_channel_unref (s->iochannel);
495
496                 g_free(s);
497         }
498 }
499
500 /**
501  * soup_socket_get_iochannel:
502  * @socket: SoupSocket to get GIOChannel from.
503  *
504  * Get the #GIOChannel for the #SoupSocket.
505  *
506  * For a client socket, the #GIOChannel represents the data stream.
507  * Use it like you would any other #GIOChannel.
508  *
509  * For a server socket however, the #GIOChannel represents incoming
510  * connections.  If you can read from it, there's a connection
511  * waiting.
512  *
513  * There is one channel for every socket.  This function refs the
514  * channel before returning it.  You should unref the channel when
515  * you are done with it.  However, you should not close the channel -
516  * this is done when you delete the socket.
517  *
518  * Returns: A #GIOChannel; NULL on failure.
519  *
520  **/
521 GIOChannel*
522 soup_socket_get_iochannel (SoupSocket* socket)
523 {
524         g_return_val_if_fail (socket != NULL, NULL);
525
526         if (socket->iochannel == NULL)
527                 socket->iochannel = SOUP_SOCKET_IOCHANNEL_NEW (socket->sockfd);
528
529         g_io_channel_ref (socket->iochannel);
530
531         return socket->iochannel;
532 }
533
534 /**
535  * soup_socket_get_address:
536  * @socket: #SoupSocket to get address of.
537  *
538  * Get the address of the socket.  If the socket is client socket,
539  * the address is the address of the remote host it is connected to.
540  * If the socket is a server socket, the address is the address of
541  * the local host.  (Though you should use
542  * soup_address_gethostaddr() to get the #SoupAddress of the local
543  * host.)
544  *
545  * Returns: #SoupAddress of socket; NULL on failure.
546  **/
547 SoupAddress *
548 soup_socket_get_address (const SoupSocket* socket)
549 {
550         g_return_val_if_fail (socket != NULL, NULL);
551         g_return_val_if_fail (socket->addr != NULL, NULL);
552
553         soup_address_ref (socket->addr);
554
555         return socket->addr;
556 }
557
558 /**
559  * soup_socket_get_port:
560  * @socket: SoupSocket to get the port number of.
561  *
562  * Get the port number the socket is bound to.
563  *
564  * Returns: Port number of the socket.
565  **/
566 gint
567 soup_socket_get_port(const SoupSocket* socket)
568 {
569         g_return_val_if_fail (socket != NULL, 0);
570
571         return g_ntohs (SOUP_SOCKADDR_IN (socket->addr->sa).sin_port);
572 }
573
574 /**
575  * soup_socket_server_new:
576  * @port: Port number for the socket (SOUP_SERVER_ANY_PORT if you don't care).
577  *
578  * Create and open a new #SoupSocket with the specified port number.
579  * Use this sort of socket when your are a server and you know what
580  * the port number should be (or pass 0 if you don't care what the
581  * port is).
582  *
583  * Returns: a new #SoupSocket, or NULL if there was a failure.
584  **/
585 SoupSocket *
586 soup_socket_server_new (const gint port)
587 {
588         SoupSocket* s;
589         struct sockaddr_in* sa_in;
590         socklen_t socklen;
591
592         /* Create socket */
593         s = g_new0 (SoupSocket, 1);
594         s->ref_count = 1;
595
596         if ((s->sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
597                 g_free (s);
598                 return NULL;
599         }
600
601         s->addr = g_new0 (SoupAddress, 1);
602         s->addr->ref_count = 1;
603
604         /* Set up address and port for connection */
605         sa_in = (struct sockaddr_in*) &s->addr->sa;
606         sa_in->sin_family = AF_INET;
607         sa_in->sin_addr.s_addr = g_htonl (INADDR_ANY);
608         sa_in->sin_port = g_htons (port);
609
610         /* The socket is set to non-blocking mode later in the Windows
611            version.*/
612 #ifndef SOUP_WIN32
613         {
614                 const int on = 1;
615                 gint flags;
616
617                 /* Set REUSEADDR so we can reuse the port */
618                 if (setsockopt (s->sockfd,
619                                 SOL_SOCKET,
620                                 SO_REUSEADDR,
621                                 &on,
622                                 sizeof (on)) != 0)
623                         g_warning("Can't set reuse on tcp socket\n");
624
625                 /* Get the flags (should all be 0?) */
626                 flags = fcntl (s->sockfd, F_GETFL, 0);
627                 if (flags == -1) goto SETUP_ERROR;
628
629                 /* Make the socket non-blocking */
630                 if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
631                         goto SETUP_ERROR;
632         }
633 #endif
634
635         /* Bind */
636         if (bind (s->sockfd, &s->addr->sa, sizeof (s->addr->sa)) != 0)
637                 goto SETUP_ERROR;
638
639         /* Get the socket name - don't care if it fails */
640         socklen = sizeof (s->addr->sa);
641         getsockname (s->sockfd, &s->addr->sa, &socklen);
642
643         /* Listen */
644         if (listen (s->sockfd, 10) != 0) goto SETUP_ERROR;
645
646         return s;
647
648  SETUP_ERROR:
649         SOUP_CLOSE_SOCKET (s->sockfd);
650         g_free (s->addr);
651         g_free (s);
652         return NULL;
653 }