Make this more complicated, with a SoupMessageQueueItem to keep track of
[platform/upstream/libsoup.git] / libsoup / soup-address.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-address.c: Internet address handing
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <unistd.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/types.h>
18
19 #include "soup-address.h"
20 #include "soup-dns.h"
21 #include "soup-enum-types.h"
22 #include "soup-marshal.h"
23 #include "soup-misc.h"
24
25 #ifndef INET_ADDRSTRLEN
26 #  define INET_ADDRSTRLEN 16
27 #  define INET6_ADDRSTRLEN 46
28 #endif
29
30 #ifndef INADDR_NONE
31 #define INADDR_NONE -1
32 #endif
33
34 /**
35  * SECTION:soup-address
36  * @short_description: DNS support
37  *
38  * #SoupAddress represents the address of a TCP connection endpoint:
39  * both the IP address and the port. (It is somewhat like an
40  * object-oriented version of struct sockaddr.)
41  *
42  * If libsoup was built with IPv6 support, #SoupAddress will allow
43  * both IPv4 and IPv6 addresses.
44  **/
45
46 enum {
47         PROP_0,
48
49         PROP_NAME,
50         PROP_FAMILY,
51         PROP_PORT,
52         PROP_PHYSICAL,
53         PROP_SOCKADDR,
54
55         LAST_PROP
56 };
57
58 typedef struct {
59         struct sockaddr *sockaddr;
60
61         char *name, *physical;
62         guint port;
63
64         SoupDNSLookup *lookup;
65         guint timeout_id;
66 } SoupAddressPrivate;
67 #define SOUP_ADDRESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_ADDRESS, SoupAddressPrivate))
68
69 /* sockaddr generic macros */
70 #define SOUP_SIN(priv) ((struct sockaddr_in *)priv->sockaddr)
71 #ifdef HAVE_IPV6
72 #define SOUP_SIN6(priv) ((struct sockaddr_in6 *)priv->sockaddr)
73 #endif
74
75 /* sockaddr family macros */
76 #define SOUP_ADDRESS_GET_FAMILY(priv) (priv->sockaddr->sa_family)
77 #define SOUP_ADDRESS_SET_FAMILY(priv, family) \
78         (priv->sockaddr->sa_family = family)
79 #ifdef HAVE_IPV6
80 #define SOUP_ADDRESS_FAMILY_IS_VALID(family) \
81         (family == AF_INET || family == AF_INET6)
82 #define SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE(family) \
83         (family == AF_INET ? sizeof (struct sockaddr_in) : \
84                              sizeof (struct sockaddr_in6))
85 #define SOUP_ADDRESS_FAMILY_DATA_SIZE(family) \
86         (family == AF_INET ? sizeof (struct in_addr) : \
87                              sizeof (struct in6_addr))
88 #else
89 #define SOUP_ADDRESS_FAMILY_IS_VALID(family) (family == AF_INET)
90 #define SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE(family) sizeof (struct sockaddr_in)
91 #define SOUP_ADDRESS_FAMILY_DATA_SIZE(family) sizeof (struct in_addr)
92 #endif
93
94 /* sockaddr port macros */
95 #define SOUP_ADDRESS_PORT_IS_VALID(port) (port >= 0 && port <= 65535)
96 #ifdef HAVE_IPV6
97 #define SOUP_ADDRESS_GET_PORT(priv) \
98         (priv->sockaddr->sa_family == AF_INET ? \
99                 SOUP_SIN(priv)->sin_port : \
100                 SOUP_SIN6(priv)->sin6_port)
101 #define SOUP_ADDRESS_SET_PORT(priv, port) \
102         G_STMT_START {                                  \
103         if (priv->sockaddr->sa_family == AF_INET)       \
104                 SOUP_SIN(priv)->sin_port = port;        \
105         else                                            \
106                 SOUP_SIN6(priv)->sin6_port = port;      \
107         } G_STMT_END
108 #else
109 #define SOUP_ADDRESS_GET_PORT(priv) (SOUP_SIN(priv)->sin_port)
110 #define SOUP_ADDRESS_SET_PORT(priv, port) (SOUP_SIN(priv)->sin_port = port)
111 #endif
112
113 /* sockaddr data macros */
114 #ifdef HAVE_IPV6
115 #define SOUP_ADDRESS_GET_DATA(priv) \
116         (priv->sockaddr->sa_family == AF_INET ? \
117                 (gpointer)&SOUP_SIN(priv)->sin_addr : \
118                 (gpointer)&SOUP_SIN6(priv)->sin6_addr)
119 #else
120 #define SOUP_ADDRESS_GET_DATA(priv) ((gpointer)&SOUP_SIN(priv)->sin_addr)
121 #endif
122 #define SOUP_ADDRESS_SET_DATA(priv, data, length) \
123         memcpy (SOUP_ADDRESS_GET_DATA (priv), data, length)
124
125
126 static GObject *constructor (GType                  type,
127                              guint                  n_construct_properties,
128                              GObjectConstructParam *construct_properties);
129 static void set_property (GObject *object, guint prop_id,
130                           const GValue *value, GParamSpec *pspec);
131 static void get_property (GObject *object, guint prop_id,
132                           GValue *value, GParamSpec *pspec);
133
134 G_DEFINE_TYPE (SoupAddress, soup_address, G_TYPE_OBJECT)
135
136 static void
137 soup_address_init (SoupAddress *addr)
138 {
139 }
140
141 static void
142 finalize (GObject *object)
143 {
144         SoupAddress *addr = SOUP_ADDRESS (object);
145         SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
146
147         if (priv->sockaddr)
148                 g_free (priv->sockaddr);
149         if (priv->name)
150                 g_free (priv->name);
151         if (priv->physical)
152                 g_free (priv->physical);
153
154         if (priv->lookup)
155                 soup_dns_lookup_free (priv->lookup);
156         if (priv->timeout_id)
157                 g_source_remove (priv->timeout_id);
158
159         G_OBJECT_CLASS (soup_address_parent_class)->finalize (object);
160 }
161
162 static void
163 soup_address_class_init (SoupAddressClass *address_class)
164 {
165         GObjectClass *object_class = G_OBJECT_CLASS (address_class);
166
167         soup_dns_init ();
168
169         g_type_class_add_private (address_class, sizeof (SoupAddressPrivate));
170
171         /* virtual method override */
172         object_class->constructor = constructor;
173         object_class->finalize = finalize;
174         object_class->set_property = set_property;
175         object_class->get_property = get_property;
176
177         /* properties */
178         g_object_class_install_property (
179                 object_class, PROP_NAME,
180                 g_param_spec_string (SOUP_ADDRESS_NAME,
181                                      "Name",
182                                      "Hostname for this address",
183                                      NULL,
184                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
185         g_object_class_install_property (
186                 object_class, PROP_FAMILY,
187                 g_param_spec_enum (SOUP_ADDRESS_FAMILY,
188                                    "Family",
189                                    "Address family for this address",
190                                    SOUP_TYPE_ADDRESS_FAMILY,
191                                    SOUP_ADDRESS_FAMILY_INVALID,
192                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
193         g_object_class_install_property (
194                 object_class, PROP_PORT,
195                 g_param_spec_int (SOUP_ADDRESS_PORT,
196                                   "Port",
197                                   "Port for this address",
198                                   -1, 65535, -1,
199                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
200         g_object_class_install_property (
201                 object_class, PROP_PHYSICAL,
202                 g_param_spec_string (SOUP_ADDRESS_PHYSICAL,
203                                      "Physical address",
204                                      "IP address for this address",
205                                      NULL,
206                                      G_PARAM_READABLE));
207         g_object_class_install_property (
208                 object_class, PROP_SOCKADDR,
209                 g_param_spec_pointer (SOUP_ADDRESS_SOCKADDR,
210                                       "sockaddr",
211                                       "struct sockaddr for this address",
212                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
213
214 #ifdef G_OS_WIN32
215         /* This hopefully is a good place to call WSAStartup */
216         {
217                 WSADATA wsadata;
218                 if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0)
219                         g_error ("Windows Sockets could not be initialized");
220         }
221 #endif
222 }
223
224 static GObject *
225 constructor (GType                  type,
226              guint                  n_construct_properties,
227              GObjectConstructParam *construct_properties)
228 {
229         GObject *addr;
230         SoupAddressPrivate *priv;
231
232         addr = G_OBJECT_CLASS (soup_address_parent_class)->constructor (
233                 type, n_construct_properties, construct_properties);
234         if (!addr)
235                 return NULL;
236         priv = SOUP_ADDRESS_GET_PRIVATE (addr);
237
238         if (priv->name) {
239                 if (!priv->sockaddr)
240                         priv->lookup = soup_dns_lookup_name (priv->name);
241         } else if (priv->sockaddr)
242                 priv->lookup = soup_dns_lookup_address (priv->sockaddr);
243         else {
244                 g_object_unref (addr);
245                 return NULL;
246         }
247
248         return addr;
249 }
250
251 static void
252 set_property (GObject *object, guint prop_id,
253               const GValue *value, GParamSpec *pspec)
254 {
255         SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (object);
256         SoupAddressFamily family;
257         struct sockaddr *sa;
258         int len, port;
259
260         /* This is a mess because the properties are mostly orthogonal,
261          * but g_object_constructor wants to set a default value for each
262          * of them.
263          */
264
265         switch (prop_id) {
266         case PROP_NAME:
267                 priv->name = g_value_dup_string (value);
268                 break;
269
270         case PROP_FAMILY:
271                 family = g_value_get_enum (value);
272                 if (family == SOUP_ADDRESS_FAMILY_INVALID)
273                         return;
274                 g_return_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family));
275                 g_return_if_fail (priv->sockaddr == NULL);
276
277                 priv->sockaddr = g_malloc0 (SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (family));
278                 SOUP_ADDRESS_SET_FAMILY (priv, family);
279                 SOUP_ADDRESS_SET_PORT (priv, htons (priv->port));
280                 break;
281
282         case PROP_PORT:
283                 port = g_value_get_int (value);
284                 if (port == -1)
285                         return;
286                 g_return_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port));
287
288                 priv->port = port;
289                 if (priv->sockaddr)
290                         SOUP_ADDRESS_SET_PORT (priv, htons (port));
291                 break;
292
293         case PROP_SOCKADDR:
294                 sa = g_value_get_pointer (value);
295                 if (!sa)
296                         return;
297                 g_return_if_fail (priv->sockaddr == NULL);
298
299                 len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family);
300                 priv->sockaddr = g_memdup (sa, len);
301                 priv->port = ntohs (SOUP_ADDRESS_GET_PORT (priv));
302                 break;
303         default:
304                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
305                 break;
306         }
307 }
308
309 static void
310 get_property (GObject *object, guint prop_id,
311               GValue *value, GParamSpec *pspec)
312 {
313         SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (object);
314
315         switch (prop_id) {
316         case PROP_NAME:
317                 g_value_set_string (value, priv->name);
318                 break;
319         case PROP_FAMILY:
320                 if (priv->sockaddr)
321                         g_value_set_enum (value, SOUP_ADDRESS_GET_FAMILY (priv));
322                 else
323                         g_value_set_enum (value, 0);
324                 break;
325         case PROP_PORT:
326                 g_value_set_int (value, priv->port);
327                 break;
328         case PROP_PHYSICAL:
329                 g_value_set_string (value, soup_address_get_physical (SOUP_ADDRESS (object)));
330                 break;
331         case PROP_SOCKADDR:
332                 g_value_set_pointer (value, priv->sockaddr);
333                 break;
334         default:
335                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
336                 break;
337         }
338 }
339
340 /**
341  * soup_address_new:
342  * @name: a hostname or physical address
343  * @port: a port number
344  *
345  * Creates a #SoupAddress from @name and @port. The #SoupAddress's IP
346  * address may not be available right away; the caller can call
347  * soup_address_resolve_async() or soup_address_resolve_sync() to
348  * force a DNS resolution.
349  *
350  * Return value: a #SoupAddress
351  **/
352 SoupAddress *
353 soup_address_new (const char *name, guint port)
354 {
355         g_return_val_if_fail (name != NULL, NULL);
356         g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL);
357
358         return g_object_new (SOUP_TYPE_ADDRESS,
359                              SOUP_ADDRESS_NAME, name,
360                              SOUP_ADDRESS_PORT, port,
361                              NULL);
362 }
363
364 /**
365  * soup_address_new_from_sockaddr:
366  * @sa: a pointer to a sockaddr
367  * @len: size of @sa
368  *
369  * Returns a #SoupAddress equivalent to @sa (or %NULL if @sa's
370  * address family isn't supported)
371  *
372  * Return value: the new #SoupAddress
373  **/
374 SoupAddress *
375 soup_address_new_from_sockaddr (struct sockaddr *sa, int len)
376 {
377         g_return_val_if_fail (sa != NULL, NULL);
378         g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (sa->sa_family), NULL);
379         g_return_val_if_fail (len == SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family), NULL);
380
381         return g_object_new (SOUP_TYPE_ADDRESS,
382                              SOUP_ADDRESS_SOCKADDR, sa,
383                              NULL);
384 }
385
386 /**
387  * SoupAddressFamily:
388  * @SOUP_ADDRESS_FAMILY_INVALID: an invalid %SoupAddress
389  * @SOUP_ADDRESS_FAMILY_IPV4: an IPv4 address
390  * @SOUP_ADDRESS_FAMILY_IPV6: an IPv6 address
391  *
392  * The supported address families. Note that the
393  * %SOUP_ADDRESS_FAMILY_IPV6 constant is available even if libsoup was
394  * built without IPv6 support, but attempting to create an IPv6
395  * address will fail in that case.
396  **/
397
398 /**
399  * SOUP_ADDRESS_ANY_PORT:
400  *
401  * This can be passed to any #SoupAddress method that expects a port,
402  * to indicate that you don't care what port is used.
403  **/
404
405 /**
406  * soup_address_new_any:
407  * @family: the address family
408  * @port: the port number (usually %SOUP_ADDRESS_ANY_PORT)
409  *
410  * Returns a #SoupAddress corresponding to the "any" address
411  * for @family (or %NULL if @family isn't supported), suitable for
412  * passing to soup_socket_server_new().
413  *
414  * Return value: the new #SoupAddress
415  **/
416 SoupAddress *
417 soup_address_new_any (SoupAddressFamily family, guint port)
418 {
419         g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family), NULL);
420         g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL);
421
422         return g_object_new (SOUP_TYPE_ADDRESS,
423                              SOUP_ADDRESS_FAMILY, family,
424                              SOUP_ADDRESS_PORT, port,
425                              NULL);
426 }
427
428 /**
429  * soup_address_get_name:
430  * @addr: a #SoupAddress
431  *
432  * Returns the hostname associated with @addr.
433  *
434  * Return value: the hostname, or %NULL if it is not known.
435  **/
436 const char *
437 soup_address_get_name (SoupAddress *addr)
438 {
439         g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
440
441         return SOUP_ADDRESS_GET_PRIVATE (addr)->name;
442 }
443
444 /**
445  * soup_address_get_sockaddr:
446  * @addr: a #SoupAddress
447  * @len: return location for sockaddr length
448  *
449  * Returns the sockaddr associated with @addr, with its length in
450  * *@len. If the sockaddr is not yet known, returns %NULL.
451  *
452  * Return value: the sockaddr, or %NULL
453  **/
454 struct sockaddr *
455 soup_address_get_sockaddr (SoupAddress *addr, int *len)
456 {
457         SoupAddressPrivate *priv;
458
459         g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
460         priv = SOUP_ADDRESS_GET_PRIVATE (addr);
461
462         if (priv->sockaddr && len)
463                 *len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv));
464
465         return priv->sockaddr;
466 }
467
468 /**
469  * soup_address_get_physical:
470  * @addr: a #SoupAddress
471  *
472  * Returns the physical address associated with @addr as a string.
473  * (Eg, "127.0.0.1"). If the address is not yet known, returns %NULL.
474  *
475  * Return value: the physical address, or %NULL
476  **/
477 const char *
478 soup_address_get_physical (SoupAddress *addr)
479 {
480         SoupAddressPrivate *priv;
481
482         g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
483         priv = SOUP_ADDRESS_GET_PRIVATE (addr);
484
485         if (!priv->sockaddr)
486                 return NULL;
487
488         if (!priv->physical)
489                 priv->physical = soup_dns_ntop (priv->sockaddr);
490
491         return priv->physical;
492 }
493
494 /**
495  * soup_address_get_port:
496  * @addr: a #SoupAddress
497  *
498  * Returns the port associated with @addr.
499  *
500  * Return value: the port
501  **/
502 guint
503 soup_address_get_port (SoupAddress *addr)
504 {
505         g_return_val_if_fail (SOUP_IS_ADDRESS (addr), 0);
506
507         return SOUP_ADDRESS_GET_PRIVATE (addr)->port;
508 }
509
510
511 static void
512 update_address (SoupAddress *addr, SoupDNSLookup *lookup)
513 {
514         SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
515
516         if (!priv->name)
517                 priv->name = soup_dns_lookup_get_hostname (lookup);
518
519         if (!priv->sockaddr) {
520                 priv->sockaddr = soup_dns_lookup_get_address (lookup);
521                 SOUP_ADDRESS_SET_PORT (priv, htons (priv->port));
522         }
523 }
524
525 typedef struct {
526         SoupAddress         *addr;
527         SoupAddressCallback  callback;
528         gpointer             callback_data;
529 } SoupAddressResolveAsyncData;
530
531 static void
532 lookup_resolved (SoupDNSLookup *lookup, guint status, gpointer user_data)
533 {
534         SoupAddressResolveAsyncData *res_data = user_data;
535         SoupAddress *addr;
536         SoupAddressCallback callback;
537         gpointer callback_data;
538
539         addr = res_data->addr;
540         callback = res_data->callback;
541         callback_data = res_data->callback_data;
542         g_free (res_data);
543
544         if (status == SOUP_STATUS_OK)
545                 update_address (addr, lookup);
546
547         if (callback)
548                 callback (addr, status, callback_data);
549
550         g_object_unref (addr);
551 }
552
553 /**
554  * SoupAddressCallback:
555  * @addr: the #SoupAddress that was resolved
556  * @status: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
557  * %SOUP_STATUS_CANCELLED
558  * @data: the user data that was passed to
559  * soup_address_resolve_async()
560  *
561  * The callback function passed to soup_address_resolve_async().
562  **/
563
564 /**
565  * soup_address_resolve_async:
566  * @addr: a #SoupAddress
567  * @async_context: the #GMainContext to call @callback from
568  * @cancellable: a #GCancellable object, or %NULL
569  * @callback: callback to call with the result
570  * @user_data: data for @callback
571  *
572  * Asynchronously resolves the missing half of @addr (its IP address
573  * if it was created with soup_address_new(), or its hostname if it
574  * was created with soup_address_new_from_sockaddr() or
575  * soup_address_new_any().)
576  *
577  * If @cancellable is non-%NULL, it can be used to cancel the
578  * resolution. @callback will still be invoked in this case, with a
579  * status of %SOUP_STATUS_CANCELLED.
580  **/
581 void
582 soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context,
583                             GCancellable *cancellable,
584                             SoupAddressCallback callback, gpointer user_data)
585 {
586         SoupAddressPrivate *priv;
587         SoupAddressResolveAsyncData *res_data;
588
589         g_return_if_fail (SOUP_IS_ADDRESS (addr));
590         priv = SOUP_ADDRESS_GET_PRIVATE (addr);
591
592         res_data = g_new (SoupAddressResolveAsyncData, 1);
593         res_data->addr          = addr;
594         res_data->callback      = callback;
595         res_data->callback_data = user_data;
596
597         g_object_ref (addr);
598         soup_dns_lookup_resolve_async (priv->lookup, async_context, cancellable,
599                                        lookup_resolved, res_data);
600 }
601
602 /**
603  * soup_address_resolve_sync:
604  * @addr: a #SoupAddress
605  * @cancellable: a #GCancellable object, or %NULL
606  *
607  * Synchronously resolves the missing half of @addr, as with
608  * soup_address_resolve_async().
609  *
610  * If @cancellable is non-%NULL, it can be used to cancel the
611  * resolution. soup_address_resolve_sync() will then return a status
612  * of %SOUP_STATUS_CANCELLED.
613  *
614  * Return value: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
615  * %SOUP_STATUS_CANCELLED.
616  **/
617 guint
618 soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable)
619 {
620         SoupAddressPrivate *priv;
621         guint status;
622
623         g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED);
624         priv = SOUP_ADDRESS_GET_PRIVATE (addr);
625
626         g_object_ref (addr);
627         status = soup_dns_lookup_resolve (priv->lookup, cancellable);
628         if (status == SOUP_STATUS_OK)
629                 update_address (addr, priv->lookup);
630         g_object_unref (addr);
631         return status;
632 }