fix div by zero
[oweals/gnunet.git] / src / transport / plugin_transport_http_common.c
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2002-2013 GNUnet e.V.
4
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Affero General Public License for more details.
14
15  You should have received a copy of the GNU Affero General Public License
16  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /**
20  * @file transport/plugin_transport_http_common.c
21  * @brief functionality shared between http(s)client plugins
22  * @author Matthias Wachs
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_transport_plugin.h"
27 #include "plugin_transport_http_common.h"
28 #include "gnunet_resolver_service.h"
29
30 static void
31 http_clean_splitted (struct SplittedHTTPAddress *spa)
32 {
33   if (NULL != spa)
34   {
35     GNUNET_free_non_null(spa->protocol);
36     GNUNET_free_non_null(spa->host);
37     GNUNET_free_non_null(spa->path);
38     GNUNET_free_non_null(spa);
39   }
40 }
41
42
43 struct SplittedHTTPAddress *
44 http_split_address (const char * addr)
45 {
46   struct SplittedHTTPAddress *sp;
47   char *src = GNUNET_strdup (addr);
48   char *protocol_start = NULL;
49   char *host_start = NULL;
50   char *v6_end = NULL;
51   char *port_start = NULL;
52   char *path_start = NULL;
53   protocol_start = src;
54
55   sp = GNUNET_new (struct SplittedHTTPAddress);
56   /* Address string consists of protocol://host[:port]path*/
57
58   host_start = strstr (src, "://");
59   if (NULL == host_start)
60   {
61     GNUNET_free(src);
62     GNUNET_free(sp);
63     return NULL ;
64   }
65   host_start[0] = '\0';
66   sp->protocol = GNUNET_strdup (protocol_start);
67
68   host_start += strlen ("://");
69   if (strlen (host_start) == 0)
70   {
71     GNUNET_free(src);
72     GNUNET_free(sp->protocol);
73     GNUNET_free(sp);
74     return NULL ;
75   }
76
77   /* Find path start */
78   path_start = strchr (host_start, '/');
79   if (NULL != path_start)
80   {
81     sp->path = GNUNET_strdup (path_start);
82     path_start[0] = '\0';
83   }
84   else
85     sp->path = GNUNET_strdup ("");
86
87   if (strlen (host_start) < 1)
88   {
89     GNUNET_free(src);
90     GNUNET_free(sp->protocol);
91     GNUNET_free(sp->path);
92     GNUNET_free(sp);
93     return NULL ;
94   }
95
96   if (NULL != (port_start = strrchr (host_start, ':')))
97   {
98     /* *We COULD have a port, but also an IPv6 address! */
99     if (NULL != (v6_end = strchr (host_start, ']')))
100     {
101       if (v6_end < port_start)
102       {
103         /* IPv6 address + port */
104         port_start[0] = '\0';
105         port_start++;
106         sp->port = atoi (port_start);
107         if ((0 == sp->port) || (65535 < sp->port))
108         {
109           GNUNET_free(src);
110           GNUNET_free(sp->protocol);
111           GNUNET_free(sp->path);
112           GNUNET_free(sp);
113           return NULL ;
114         }
115       }
116       else
117       {
118         /* IPv6 address + no port */
119         if (0 == strcmp (sp->protocol, "https"))
120           sp->port = HTTPS_DEFAULT_PORT;
121         else if (0 == strcmp (sp->protocol, "http"))
122           sp->port = HTTP_DEFAULT_PORT;
123       }
124     }
125     else
126     {
127       /* No IPv6 address */
128       port_start[0] = '\0';
129       port_start++;
130       sp->port = atoi (port_start);
131       if ((0 == sp->port) || (65535 < sp->port))
132       {
133         GNUNET_free(src);
134         GNUNET_free(sp->protocol);
135         GNUNET_free(sp->path);
136         GNUNET_free(sp);
137         return NULL ;
138       }
139     }
140   }
141   else
142   {
143     /* No ':' as port separator, default port for protocol */
144     if (0 == strcmp (sp->protocol, "https"))
145       sp->port = HTTPS_DEFAULT_PORT;
146     else if (0 == strcmp (sp->protocol, "http"))
147       sp->port = HTTP_DEFAULT_PORT;
148     else
149     {
150       GNUNET_break(0);
151       GNUNET_free(src);
152       GNUNET_free(sp->protocol);
153       GNUNET_free(sp->path);
154       GNUNET_free(sp);
155       return NULL ;
156     }
157   }
158   if (strlen (host_start) > 0)
159     sp->host = GNUNET_strdup (host_start);
160   else
161   {
162     GNUNET_break(0);
163     GNUNET_free(src);
164     GNUNET_free(sp->protocol);
165     GNUNET_free(sp->path);
166     GNUNET_free(sp);
167     return NULL ;
168   }
169   GNUNET_free(src);
170   return sp;
171 }
172
173 /**
174  * Closure for #append_port().
175  */
176 struct PrettyPrinterContext
177 {
178   /**
179    * DLL
180    */
181   struct PrettyPrinterContext *next;
182
183   /**
184    * DLL
185    */
186   struct PrettyPrinterContext *prev;
187
188   /**
189    * Resolver handle
190    */
191   struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
192
193   /**
194    * Function to call with the result.
195    */
196   GNUNET_TRANSPORT_AddressStringCallback asc;
197
198   /**
199    * Clsoure for @e asc.
200    */
201   void *asc_cls;
202
203   /**
204    * Timeout task
205    */
206   struct GNUNET_SCHEDULER_Task * timeout_task;
207
208   /**
209    * Splitted Address
210    */
211   struct SplittedHTTPAddress *saddr;
212
213   /**
214    * Plugin String
215    */
216   char *plugin;
217
218   /**
219    * Was conversion successful
220    */
221   int sucess;
222
223   /**
224    * Address options
225    */
226   uint32_t options;
227 };
228
229 /**
230  * Head of PPC list
231  */
232 static struct PrettyPrinterContext *dll_ppc_head;
233
234 /**
235  * Tail of PPC list
236  */
237 static struct PrettyPrinterContext *dll_ppc_tail;
238
239 /**
240  * Function called for a quick conversion of the binary address to
241  * a numeric address.  Note that the caller must not free the
242  * address and that the next call to this function is allowed
243  * to override the address again.
244  *
245  * @param plugin the name of the plugin
246  * @param saddr the splitted http address
247  * @param options address options
248  * @param dnsresult dns name to include in address
249  * @return string representing the same address or NULL on error
250  */
251 static const char *
252 http_common_plugin_dnsresult_to_address (const char *plugin,
253     const struct SplittedHTTPAddress *saddr,
254     uint32_t options,
255     const char *dnsresult)
256 {
257   static char rbuf[1024];
258   char *res;
259
260   GNUNET_asprintf (&res, "%s.%u.%s://%s:%u%s", plugin, options, saddr->protocol,
261       dnsresult, saddr->port, saddr->path);
262   if (strlen (res) + 1 < 500)
263   {
264     GNUNET_memcpy (rbuf, res, strlen (res) + 1);
265     GNUNET_free(res);
266     return rbuf;
267   }
268   GNUNET_break(0);
269   GNUNET_free(res);
270   return NULL ;
271 }
272
273
274 static void
275 http_common_dns_reverse_lookup_cb (void *cls, const char *hostname)
276 {
277   struct PrettyPrinterContext *ppc = cls;
278
279   if (NULL != hostname)
280   {
281     ppc->asc (ppc->asc_cls,
282         http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr, ppc->options,
283             hostname), GNUNET_OK);
284     ppc->sucess = GNUNET_YES;
285
286   }
287   else
288   {
289     ppc->asc (ppc->asc_cls, NULL,
290         (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
291
292     GNUNET_CONTAINER_DLL_remove(dll_ppc_head, dll_ppc_tail, ppc);
293     http_clean_splitted (ppc->saddr);
294     GNUNET_free(ppc->plugin);
295     GNUNET_free(ppc);
296   }
297 }
298
299
300 static int
301 http_common_dns_reverse_lookup (const struct sockaddr *sockaddr,
302                                 socklen_t sockaddr_len,
303                                 const char *type,
304                                 struct SplittedHTTPAddress *saddr,
305                                 uint32_t options,
306                                 struct GNUNET_TIME_Relative timeout,
307                                 GNUNET_TRANSPORT_AddressStringCallback asc,
308                                 void *asc_cls)
309 {
310   struct PrettyPrinterContext *ppc;
311
312   ppc = GNUNET_new (struct PrettyPrinterContext);
313   ppc->saddr = saddr;
314   ppc->asc = asc;
315   ppc->asc_cls = asc_cls;
316   ppc->plugin = GNUNET_strdup (type);
317   ppc->options = options;
318   ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sockaddr,
319                                                        sockaddr_len,
320                                                        GNUNET_YES,
321                                                        timeout,
322                                                        &http_common_dns_reverse_lookup_cb,
323                                                        ppc);
324   if (NULL == ppc->resolver_handle)
325   {
326     GNUNET_free(ppc->plugin);
327     GNUNET_free(ppc);
328     return GNUNET_SYSERR;
329   }
330   GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
331                                dll_ppc_tail,
332                                ppc);
333   return GNUNET_OK;
334 }
335
336
337 static void
338 http_common_dns_ip_lookup_cb (void *cls,
339                               const struct sockaddr *addr,
340                               socklen_t addrlen)
341 {
342   struct PrettyPrinterContext *ppc = cls;
343
344   if (NULL != addr)
345   {
346     ppc->asc (ppc->asc_cls,
347         http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr, ppc->options,
348             GNUNET_a2s (addr, addrlen)), GNUNET_OK);
349     ppc->sucess = GNUNET_YES;
350     ppc->asc (ppc->asc_cls, GNUNET_a2s (addr, addrlen), GNUNET_OK);
351   }
352   else
353   {
354     ppc->asc (ppc->asc_cls, NULL,
355         (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
356
357     GNUNET_CONTAINER_DLL_remove(dll_ppc_head, dll_ppc_tail, ppc);
358     GNUNET_free(ppc->plugin);
359     http_clean_splitted (ppc->saddr);
360     GNUNET_free(ppc);
361   }
362 }
363
364
365 static int
366 http_common_dns_ip_lookup (const char *name,
367                            const char *type,
368                            struct SplittedHTTPAddress *saddr,
369                            uint32_t options,
370                            struct GNUNET_TIME_Relative timeout,
371                            GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
372 {
373   struct PrettyPrinterContext *ppc;
374
375   ppc = GNUNET_new (struct PrettyPrinterContext);
376   ppc->sucess = GNUNET_NO;
377   ppc->saddr = saddr;
378   ppc->asc = asc;
379   ppc->asc_cls = asc_cls;
380   ppc->plugin = GNUNET_strdup (type);
381   ppc->options = options;
382   ppc->resolver_handle = GNUNET_RESOLVER_ip_get (name,
383                                                  AF_UNSPEC,
384                                                  timeout,
385                                                  &http_common_dns_ip_lookup_cb,
386                                                  ppc);
387   if (NULL == ppc->resolver_handle)
388   {
389     GNUNET_free(ppc->plugin);
390     GNUNET_free(ppc);
391     return GNUNET_SYSERR;
392   }
393   GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
394                                dll_ppc_tail,
395                                ppc);
396   return GNUNET_OK;
397 }
398
399
400 /**
401  * Convert the transports address to a nice, human-readable
402  * format.
403  *
404  * @param cls closure
405  * @param type name of the transport that generated the address
406  * @param addr one of the addresses of the host, NULL for the last address
407  *        the specific address format depends on the transport
408  * @param addrlen length of the @a addr
409  * @param numeric should (IP) addresses be displayed in numeric form?
410  * @param timeout after how long should we give up?
411  * @param asc function to call on each string
412  * @param asc_cls closure for @a asc
413  */
414 void
415 http_common_plugin_address_pretty_printer (void *cls, const char *type,
416                                            const void *addr,
417                                            size_t addrlen,
418                                            int numeric,
419                                            struct GNUNET_TIME_Relative timeout,
420                                            GNUNET_TRANSPORT_AddressStringCallback asc,
421                                            void *asc_cls)
422 {
423   const struct HttpAddress *address = addr;
424   struct SplittedHTTPAddress *saddr;
425   struct sockaddr *sock_addr;
426   const char *ret;
427   char *addr_str;
428   int res;
429   int have_ip;
430
431   saddr = NULL;
432   sock_addr = NULL;
433   if ( (addrlen < sizeof(struct HttpAddress)) ||
434        (addrlen != http_common_address_get_size (address)) )
435   {
436     GNUNET_break(0);
437     goto handle_error;
438   }
439
440   addr_str = (char *) &address[1];
441   if (addr_str[ntohl (address->urlen) - 1] != '\0')
442   {
443     GNUNET_break(0);
444     goto handle_error;
445   }
446
447   saddr = http_split_address (addr_str);
448   if (NULL == saddr)
449   {
450     GNUNET_break(0);
451     goto handle_error;
452   }
453
454   sock_addr = http_common_socket_from_address (addr, addrlen, &res);
455   if (GNUNET_SYSERR == res)
456   {
457     /* Malformed address */
458     GNUNET_break (0);
459     goto handle_error;
460   }
461   else if (GNUNET_NO == res)
462   {
463     /* Could not convert to IP */
464     have_ip = GNUNET_NO;
465   }
466   else if (GNUNET_YES == res)
467   {
468     /* Converted to IP */
469     have_ip = GNUNET_YES;
470   }
471   else
472   {
473     /* Must not happen */
474     GNUNET_break (0);
475     goto handle_error;
476   }
477
478   if ( (GNUNET_YES == numeric) &&
479        (GNUNET_YES == have_ip) )
480   {
481     /* No lookup required */
482     ret = http_common_plugin_address_to_string (type, address, addrlen);
483     asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
484     asc (asc_cls, NULL, GNUNET_OK);
485     http_clean_splitted (saddr);
486     GNUNET_free_non_null (sock_addr);
487     return;
488   }
489   if ( (GNUNET_YES == numeric) &&
490        (GNUNET_NO == have_ip) )
491   {
492     /* Forward lookup */
493     if (GNUNET_SYSERR ==
494         http_common_dns_ip_lookup (saddr->host, type, saddr,
495                                    address->options, timeout,
496                                    asc, asc_cls))
497     {
498       GNUNET_break(0);
499       goto handle_error;
500     }
501     /* Wait for resolver callback */
502     GNUNET_free_non_null (sock_addr);
503     return;
504   }
505   if ( (GNUNET_NO == numeric) &&
506        (GNUNET_YES == have_ip) )
507   {
508     /* Reverse lookup */
509     if (GNUNET_SYSERR ==
510         http_common_dns_reverse_lookup (sock_addr,
511                                         (AF_INET == sock_addr->sa_family)
512                                         ? sizeof(struct sockaddr_in)
513                                         : sizeof(struct sockaddr_in6),
514                                         type,
515                                         saddr,
516                                         address->options, timeout,
517                                         asc, asc_cls))
518     {
519       GNUNET_break(0);
520       goto handle_error;
521     }
522     /* Wait for resolver callback */
523     GNUNET_free_non_null (sock_addr);
524     return;
525   }
526   if ( (GNUNET_NO == numeric) &&
527        (GNUNET_NO == have_ip) )
528   {
529     /* No lookup required */
530     ret = http_common_plugin_address_to_string (type, address, addrlen);
531     asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
532     asc (asc_cls, NULL, GNUNET_OK);
533     GNUNET_free_non_null (sock_addr);
534     http_clean_splitted (saddr);
535     return;
536   }
537   /* Error (argument supplied not GNUNET_YES or GNUNET_NO) */
538   GNUNET_break (0);
539   goto handle_error;
540
541  handle_error:
542   /* Report error */
543   asc (asc_cls, NULL, GNUNET_SYSERR);
544   asc (asc_cls, NULL, GNUNET_OK);
545   GNUNET_free_non_null (sock_addr);
546   if (NULL != saddr)
547     http_clean_splitted (saddr);
548 }
549
550
551 /**
552  * FIXME.
553  */
554 const char *
555 http_common_plugin_address_to_url (void *cls,
556                                    const void *addr,
557                                    size_t addrlen)
558 {
559   static char rbuf[1024];
560   const struct HttpAddress *address = addr;
561   const char * addr_str;
562
563   if (NULL == addr)
564   {
565     GNUNET_break(0);
566     return NULL;
567   }
568   if (0 == addrlen)
569   {
570     GNUNET_break(0);
571     return NULL;
572   }
573   if (addrlen != http_common_address_get_size (address))
574   {
575     GNUNET_break(0);
576     return NULL;
577   }
578   addr_str = (char *) &address[1];
579   if (addr_str[ntohl (address->urlen) - 1] != '\0')
580     return NULL;
581
582   GNUNET_memcpy (rbuf,
583           &address[1],
584           ntohl (address->urlen));
585   return rbuf;
586 }
587
588
589 /**
590  * Function called for a quick conversion of the binary address to
591  * a numeric address.  Note that the caller must not free the
592  * address and that the next call to this function is allowed
593  * to override the address again.
594  *
595  * @param plugin the name of the plugin
596  * @param addr binary address
597  * @param addrlen length of the address
598  * @return string representing the same address
599  */
600 const char *
601 http_common_plugin_address_to_string (const char *plugin,
602                                       const void *addr,
603                                       size_t addrlen)
604 {
605   static char rbuf[1024];
606   const struct HttpAddress *address = addr;
607   const char * addr_str;
608   char *res;
609
610   GNUNET_assert(NULL != plugin);
611   if (NULL == addr)
612     return NULL;
613   if (0 == addrlen)
614     return NULL;
615   if (addrlen != http_common_address_get_size (address))
616     return NULL;
617   addr_str = (char *) &address[1];
618   if (addr_str[ntohl (address->urlen) - 1] != '\0')
619     return NULL;
620   GNUNET_asprintf (&res, "%s.%u.%s", plugin, ntohl (address->options),
621       &address[1]);
622   if (strlen (res) + 1 < 500)
623   {
624     GNUNET_memcpy (rbuf, res, strlen (res) + 1);
625     GNUNET_free(res);
626     return rbuf;
627   }
628   GNUNET_break(0);
629   GNUNET_free(res);
630   return NULL;
631 }
632
633 /**
634  * Function called to convert a string address to
635  * a binary address.
636  *
637  * @param cls closure ('struct Plugin*')
638  * @param addr string address
639  * @param addrlen length of the @a addr
640  * @param buf location to store the buffer
641  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
642  * @param added length of created address
643  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
644  */
645 int
646 http_common_plugin_string_to_address (void *cls,
647                                       const char *addr,
648                                       uint16_t addrlen,
649                                       void **buf,
650                                       size_t *added)
651 {
652   struct HttpAddress *a;
653   char *address;
654   char *plugin;
655   char *optionstr;
656   size_t urlen;
657   uint32_t options;
658
659   /* Format protocol.options.address:port */
660   address = NULL;
661   plugin = NULL;
662   optionstr = NULL;
663   if ((NULL == addr) || (addrlen == 0))
664   {
665     GNUNET_break(0);
666     return GNUNET_SYSERR;
667   }
668   if ('\0' != addr[addrlen - 1])
669   {
670     GNUNET_break(0);
671     return GNUNET_SYSERR;
672   }
673   if (strlen (addr) != addrlen - 1)
674   {
675     GNUNET_break(0);
676     return GNUNET_SYSERR;
677   }
678   plugin = GNUNET_strdup (addr);
679   optionstr = strchr (plugin, '.');
680   if (NULL == optionstr)
681   {
682     GNUNET_break(0);
683     GNUNET_free(plugin);
684     return GNUNET_SYSERR;
685   }
686   optionstr[0] = '\0';
687   optionstr++;
688   options = atol (optionstr); /* 0 on conversion error, that's ok */
689   address = strchr (optionstr, '.');
690   if (NULL == address)
691   {
692     GNUNET_break(0);
693     GNUNET_free(plugin);
694     return GNUNET_SYSERR;
695   }
696   address[0] = '\0';
697   address++;
698   urlen = strlen (address) + 1;
699
700   a = GNUNET_malloc (sizeof (struct HttpAddress) + urlen);
701   a->options = htonl (options);
702   a->urlen = htonl (urlen);
703   GNUNET_memcpy (&a[1], address, urlen);
704
705   (*buf) = a;
706   (*added) = sizeof(struct HttpAddress) + urlen;
707   GNUNET_free(plugin);
708   return GNUNET_OK;
709 }
710
711
712 /**
713  * Create a HTTP address from a socketaddr
714  *
715  * @param protocol protocol
716  * @param addr sockaddr * address
717  * @param addrlen length of the address
718  * @return the HttpAddress
719  */
720 struct HttpAddress *
721 http_common_address_from_socket (const char *protocol,
722                                  const struct sockaddr *addr,
723                                  socklen_t addrlen)
724 {
725   struct HttpAddress *address = NULL;
726   char *res;
727   size_t len;
728
729   GNUNET_asprintf (&res,
730                    "%s://%s",
731                    protocol,
732                    GNUNET_a2s (addr,
733                                addrlen));
734   len = strlen (res) + 1;
735   address = GNUNET_malloc (sizeof (struct HttpAddress) + len);
736   address->options = htonl (HTTP_OPTIONS_NONE);
737   address->urlen = htonl (len);
738   GNUNET_memcpy (&address[1], res, len);
739   GNUNET_free(res);
740   return address;
741 }
742
743
744 /**
745  * Create a socketaddr from a HTTP address
746  *
747  * @param addr a `sockaddr *` address
748  * @param addrlen length of the @a addr
749  * @param res the result:
750  *   #GNUNET_SYSERR, invalid input,
751  *   #GNUNET_YES: could convert to ip,
752  *   #GNUNET_NO: valid input but could not convert to ip (hostname?)
753  * @return the string
754  */
755 struct sockaddr *
756 http_common_socket_from_address (const void *addr,
757                                  size_t addrlen,
758                                  int *res)
759 {
760   const struct HttpAddress *ha;
761   struct SplittedHTTPAddress * spa;
762   struct sockaddr_storage *s;
763   char * to_conv;
764   size_t urlen;
765
766   (*res) = GNUNET_SYSERR;
767   ha = (const struct HttpAddress *) addr;
768   if (NULL == addr)
769   {
770     GNUNET_break (0);
771     return NULL;
772   }
773   if (0 == addrlen)
774   {
775     GNUNET_break (0);
776     return NULL;
777   }
778   if (addrlen < sizeof(struct HttpAddress))
779   {
780     GNUNET_break (0);
781     return NULL;
782   }
783   urlen = ntohl (ha->urlen);
784   if (sizeof(struct HttpAddress) + urlen != addrlen)
785   {
786     /* This is a legacy addresses */
787     return NULL;
788   }
789   if (addrlen < sizeof(struct HttpAddress) + urlen)
790   {
791     /* This is a legacy addresses */
792     return NULL;
793   }
794   if (((char *) addr)[addrlen - 1] != '\0')
795   {
796     GNUNET_break (0);
797     return NULL;
798   }
799   spa = http_split_address ((const char *) &ha[1]);
800   if (NULL == spa)
801   {
802     (*res) = GNUNET_SYSERR;
803     return NULL;
804   }
805
806   s = GNUNET_new (struct sockaddr_storage);
807   GNUNET_asprintf (&to_conv, "%s:%u", spa->host, spa->port);
808   if (GNUNET_SYSERR
809       == GNUNET_STRINGS_to_address_ip (to_conv, strlen (to_conv), s))
810   {
811     /* could be a hostname */
812     GNUNET_free(s);
813     (*res) = GNUNET_NO;
814     s = NULL;
815   }
816   else if ((AF_INET != s->ss_family) && (AF_INET6 != s->ss_family))
817   {
818     GNUNET_free (s);
819     (*res) = GNUNET_SYSERR;
820     s = NULL;
821   }
822   else
823   {
824     (*res) = GNUNET_YES;
825   }
826   http_clean_splitted (spa);
827   GNUNET_free (to_conv);
828   return (struct sockaddr *) s;
829 }
830
831
832 /**
833  * Get the length of an address
834  *
835  * @param addr address
836  * @return the size
837  */
838 size_t
839 http_common_address_get_size (const struct HttpAddress * addr)
840 {
841   return sizeof(struct HttpAddress) + ntohl (addr->urlen);
842 }
843
844
845 /**
846  * Compare addr1 to addr2
847  *
848  * @param addr1 address1
849  * @param addrlen1 address 1 length
850  * @param addr2 address2
851  * @param addrlen2 address 2 length
852  * @return #GNUNET_YES if equal, #GNUNET_NO if not, #GNUNET_SYSERR on error
853  */
854 size_t
855 http_common_cmp_addresses (const void *addr1,
856                            size_t addrlen1,
857                            const void *addr2,
858                            size_t addrlen2)
859 {
860   const char *a1 = addr1;
861   const char *a2 = addr2;
862   const struct HttpAddress *ha1;
863   const struct HttpAddress *ha2;
864   ha1 = (const struct HttpAddress *) a1;
865   ha2 = (const struct HttpAddress *) a2;
866
867   if (NULL == a1)
868     return GNUNET_SYSERR;
869   if (0 == addrlen1)
870     return GNUNET_SYSERR;
871   if (a1[addrlen1 - 1] != '\0')
872     return GNUNET_SYSERR;
873
874   if (NULL == a2)
875     return GNUNET_SYSERR;
876   if (0 == addrlen2)
877     return GNUNET_SYSERR;
878   if (a2[addrlen2 - 1] != '\0')
879     return GNUNET_SYSERR;
880
881   if (addrlen1 != addrlen2)
882     return GNUNET_NO;
883   if (ha1->urlen != ha2->urlen)
884     return GNUNET_NO;
885
886   if (0 == strcmp ((const char *) &ha1[1], (const char *) &ha2[1]))
887     return GNUNET_YES;
888   return GNUNET_NO;
889 }
890
891
892 /**
893  * Function obtain the network type for an address.
894  *
895  * @param env the environment
896  * @param address the address
897  * @return the network type
898  */
899 enum GNUNET_ATS_Network_Type
900 http_common_get_network_for_address (struct GNUNET_TRANSPORT_PluginEnvironment *env,
901                                      const struct GNUNET_HELLO_Address *address)
902 {
903
904   struct sockaddr *sa;
905   enum GNUNET_ATS_Network_Type net_type;
906   size_t salen = 0;
907   int res;
908
909   net_type = GNUNET_ATS_NET_UNSPECIFIED;
910   sa = http_common_socket_from_address (address->address,
911                                         address->address_length,
912                                         &res);
913   if (GNUNET_SYSERR == res)
914     return net_type;
915   if (GNUNET_YES == res)
916   {
917     GNUNET_assert (NULL != sa);
918     if (AF_INET == sa->sa_family)
919     {
920       salen = sizeof (struct sockaddr_in);
921     }
922     else if (AF_INET6 == sa->sa_family)
923     {
924       salen = sizeof (struct sockaddr_in6);
925     }
926     net_type = env->get_address_type (env->cls,
927                                       sa,
928                                       salen);
929     GNUNET_free (sa);
930   }
931   return net_type;
932 }
933
934
935
936 /* end of plugin_transport_http_common.c */