2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/plugin_transport_http.c
23 * @brief http transport service plugin
24 * @author Matthias Wachs
27 #include "plugin_transport_http.h"
30 * After how long do we expire an address that we
31 * learned from another peer if it is not reconfirmed
34 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
38 * Wrapper to manage addresses
40 struct HttpAddressWrapper
45 struct HttpAddressWrapper *next;
48 * Linked list previous
50 struct HttpAddressWrapper *prev;
52 struct HttpAddress *addr;
56 * Wrapper to manage IPv4 addresses
58 struct IPv4HttpAddressWrapper
63 struct IPv4HttpAddressWrapper *next;
66 * Linked list previous
68 struct IPv4HttpAddressWrapper *prev;
70 struct IPv4HttpAddress addr;
74 * Wrapper for IPv4 addresses.
76 struct IPv6HttpAddressWrapper
81 struct IPv6HttpAddressWrapper *next;
84 * Linked list previous
86 struct IPv6HttpAddressWrapper *prev;
88 struct IPv6HttpAddress addr6;
93 * Context for address to string conversion.
95 struct PrettyPrinterContext
98 * Function to call with the result.
100 GNUNET_TRANSPORT_AddressStringCallback asc;
105 struct Plugin *plugin;
113 * Port to add after the IP address.
124 * Encapsulation of all of the state of the plugin.
129 * Start session timeout
132 start_session_timeout (struct Session *s);
135 * Increment session timeout due to activity
138 reschedule_session_timeout (struct Session *s);
144 stop_session_timeout (struct Session *s);
147 * Append our port and forward the result.
149 * @param cls the 'struct PrettyPrinterContext*'
150 * @param hostname hostname part of the address
153 append_port (void *cls, const char *hostname)
155 struct PrettyPrinterContext *ppc = cls;
156 static char rbuf[INET6_ADDRSTRLEN + 13];
158 if (hostname == NULL)
160 ppc->asc (ppc->asc_cls, NULL);
166 const char *protocol = "http";
168 const char *protocol = "https";
170 GNUNET_assert ((strlen (hostname) + 7) < (INET6_ADDRSTRLEN + 13));
171 if (ppc->addrlen == sizeof (struct IPv6HttpAddress))
173 if (ppc->numeric == GNUNET_YES)
174 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://[%s]:%u/", protocol, hostname, ppc->port);
177 if (strchr(hostname, ':') != NULL)
178 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://[%s]:%u/", protocol, hostname, ppc->port);
180 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://%s:%u/", protocol, hostname, ppc->port);
183 else if (ppc->addrlen == sizeof (struct IPv4HttpAddress))
184 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://%s:%u/", protocol, hostname, ppc->port);
185 ppc->asc (ppc->asc_cls, rbuf);
193 * Convert the transports address to a nice, human-readable
197 * @param type name of the transport that generated the address
198 * @param addr one of the addresses of the host, NULL for the last address
199 * the specific address format depends on the transport
200 * @param addrlen length of the address
201 * @param numeric should (IP) addresses be displayed in numeric form?
202 * @param timeout after how long should we give up?
203 * @param asc function to call on each string
204 * @param asc_cls closure for asc
207 http_plugin_address_pretty_printer (void *cls, const char *type,
208 const void *addr, size_t addrlen,
210 struct GNUNET_TIME_Relative timeout,
211 GNUNET_TRANSPORT_AddressStringCallback asc,
214 GNUNET_assert (cls != NULL);
215 struct PrettyPrinterContext *ppc;
217 struct sockaddr_in s4;
218 struct sockaddr_in6 s6;
222 if ((addrlen == sizeof (struct IPv6HttpAddress)) && (addr != NULL))
224 struct IPv6HttpAddress *a6 = (struct IPv6HttpAddress *) addr;
225 s6.sin6_family = AF_INET6;
226 s6.sin6_addr = a6->ipv6_addr;
227 s6.sin6_port = a6->u6_port;
228 #if HAVE_SOCKADDR_IN_SIN_LEN
229 s6.sin6_len = sizeof (struct sockaddr_in6);
232 sbs = sizeof (struct sockaddr_in6);
233 port = ntohs (a6->u6_port);
236 else if ((addrlen == sizeof (struct IPv4HttpAddress)) && (addr != NULL))
238 struct IPv4HttpAddress *a4 = (struct IPv4HttpAddress *) addr;
240 s4.sin_family = AF_INET;
241 s4.sin_addr.s_addr = a4->ipv4_addr;
242 s4.sin_port = a4->u4_port;
243 #if HAVE_SOCKADDR_IN_SIN_LEN
244 s4.sin_len = sizeof (struct sockaddr_in);
247 sbs = sizeof (struct sockaddr_in);
248 port = ntohs (a4->u4_port);
250 else if (0 == addrlen)
252 asc (asc_cls, "<inbound connection>");
258 /* invalid address */
263 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
265 ppc->asc_cls = asc_cls;
268 ppc->addrlen = addrlen;
269 ppc->numeric = numeric;
270 GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
276 * Another peer has suggested an address for this
277 * peer and transport plugin. Check that this could be a valid
278 * address. If so, consider adding it to the list
282 * @param addr pointer to the address
283 * @param addrlen length of addr
284 * @return GNUNET_OK if this is a plausible address for this peer
288 http_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
290 struct Plugin *plugin = cls;
291 struct IPv4HttpAddressWrapper *w_tv4 = plugin->ipv4_addr_head;
292 struct IPv6HttpAddressWrapper *w_tv6 = plugin->ipv6_addr_head;
294 GNUNET_assert (cls != NULL);
295 if ((addrlen != sizeof (struct sockaddr_in)) ||
296 (addrlen != sizeof (struct sockaddr_in6)))
297 return GNUNET_SYSERR;
299 if (addrlen == sizeof (struct IPv4HttpAddress))
301 struct IPv4HttpAddress *a4 = (struct IPv4HttpAddress *) addr;
303 while (w_tv4 != NULL)
306 memcmp (&w_tv4->addr.ipv4_addr, &a4->ipv4_addr,
307 sizeof (struct in_addr))) &&
308 (w_tv4->addr.u4_port == a4->u4_port))
315 return GNUNET_SYSERR;
317 if (addrlen == sizeof (struct sockaddr_in6))
319 struct IPv6HttpAddress *a6 = (struct IPv6HttpAddress *) addr;
321 while (w_tv6 != NULL)
324 memcmp (&w_tv6->addr6.ipv6_addr, &a6->ipv6_addr,
325 sizeof (struct in6_addr))) &&
326 (w_tv6->addr6.u6_port == a6->u6_port))
333 return GNUNET_SYSERR;
338 struct GNUNET_TIME_Relative
339 http_plugin_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
340 const struct GNUNET_MessageHeader *message,
341 struct Session *session, const char *sender_address,
342 uint16_t sender_address_len)
344 struct Session *s = cls;
345 struct Plugin *plugin = s->plugin;
346 struct GNUNET_TIME_Relative delay;
347 struct GNUNET_ATS_Information atsi[2];
349 atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
350 atsi[0].value = htonl (1);
351 atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
352 atsi[1].value = session->ats_address_network_type;
353 GNUNET_break (session->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED));
355 reschedule_session_timeout (session);
358 plugin->env->receive (plugin->env->cls, &s->target, message,
359 (const struct GNUNET_ATS_Information *) &atsi,
360 2, s, s->addr, s->addrlen);
366 * Function called to convert a string address to
369 * @param cls closure ('struct Plugin*')
370 * @param addr string address
371 * @param addrlen length of the address
372 * @param buf location to store the buffer
373 * If the function returns GNUNET_SYSERR, its contents are undefined.
374 * @param added length of created address
375 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
378 http_string_to_address (void *cls,
385 char *protocol = "http";
387 char *protocol = "https";
389 char *addr_str = NULL;
390 struct sockaddr_in addr_4;
391 struct sockaddr_in6 addr_6;
392 struct IPv4HttpAddress * http_4addr;
393 struct IPv6HttpAddress * http_6addr;
395 if ((NULL == addr) || (addrlen == 0))
398 return GNUNET_SYSERR;
401 if ('\0' != addr[addrlen - 1])
404 return GNUNET_SYSERR;
407 if (strlen (addr) != addrlen - 1)
410 return GNUNET_SYSERR;
413 /* protocoll + "://" + ":" */
414 if (addrlen <= (strlen (protocol) + 4))
416 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
417 "Invalid address string `%s' to convert to address\n",
420 return GNUNET_SYSERR;
423 if (NULL == (addr_str = strstr(addr, "://")))
425 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
426 "Invalid address string `%s' to convert to address\n",
429 return GNUNET_SYSERR;
431 addr_str = &addr_str[3];
433 if (addr_str[strlen(addr_str)-1] == '/')
434 addr_str[strlen(addr_str)-1] = '\0';
436 if (GNUNET_OK == GNUNET_STRINGS_to_address_ipv4(addr_str, strlen(addr_str), &addr_4))
438 http_4addr = GNUNET_malloc (sizeof (struct IPv4HttpAddress));
439 http_4addr->u4_port = addr_4.sin_port;
440 http_4addr->ipv4_addr = (uint32_t) addr_4.sin_addr.s_addr;
442 (*added) = sizeof (struct IPv4HttpAddress);
445 if (GNUNET_OK == GNUNET_STRINGS_to_address_ipv6(addr_str, strlen(addr_str), &addr_6))
447 http_6addr = GNUNET_malloc (sizeof (struct IPv6HttpAddress));
448 http_6addr->u6_port = addr_6.sin6_port;
449 http_6addr->ipv6_addr = addr_6.sin6_addr;
451 (*added) = sizeof (struct IPv6HttpAddress);
454 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
455 "Invalid address string `%s' to convert to address\n",
458 return GNUNET_SYSERR;
463 * Function called for a quick conversion of the binary address to
464 * a numeric address. Note that the caller must not free the
465 * address and that the next call to this function is allowed
466 * to override the address again.
469 * @param addr binary address
470 * @param addrlen length of the address
471 * @return string representing the same address
474 http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
477 struct IPv4HttpAddress *a4;
478 struct IPv6HttpAddress *a6;
480 static char rbuf[INET6_ADDRSTRLEN + 13];
484 if (addrlen == sizeof (struct IPv6HttpAddress))
486 a6 = (struct IPv6HttpAddress *) addr;
487 address = GNUNET_malloc (INET6_ADDRSTRLEN);
488 GNUNET_assert (NULL !=
489 inet_ntop (AF_INET6, &a6->ipv6_addr, address,
491 port = ntohs (a6->u6_port);
493 else if (addrlen == sizeof (struct IPv4HttpAddress))
495 a4 = (struct IPv4HttpAddress *) addr;
496 address = GNUNET_malloc (INET_ADDRSTRLEN);
497 GNUNET_assert (NULL !=
498 inet_ntop (AF_INET, &(a4->ipv4_addr), address,
500 port = ntohs (a4->u4_port);
504 /* invalid address */
509 char *protocol = "http";
511 char *protocol = "https";
514 GNUNET_assert (strlen (address) + 7 < (INET6_ADDRSTRLEN + 13));
515 if (addrlen == sizeof (struct IPv6HttpAddress))
517 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://[%s]:%u/", protocol,
519 else if (addrlen == sizeof (struct IPv4HttpAddress))
521 GNUNET_snprintf (rbuf, sizeof (rbuf), "%s://%s:%u/", protocol, address,
524 GNUNET_free (address);
525 GNUNET_assert (res != 0);
531 lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
532 struct Session *session, const void *addr, size_t addrlen,
539 for (t = plugin->head; NULL != t; t = t->next)
542 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
543 "Comparing peer `%s' address `%s' len %i session %p to \n",
544 GNUNET_i2s (target), GNUNET_a2s (addr, addrlen), addrlen,
546 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
547 "peer `%s' address `%s' len %i session %p \n\n",
548 GNUNET_i2s (&t->target), GNUNET_a2s (t->addr, t->addrlen),
550 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "memcmp %i \n",
551 memcmp (addr, t->addr, addrlen));
555 if (0 == memcmp (target, &t->target, sizeof (struct GNUNET_PeerIdentity)))
558 if ( (addrlen == t->addrlen) &&
559 (0 == memcmp (addr, t->addr, addrlen)) )
561 if ( (t == session) &&
562 (t->addrlen == session->addrlen) &&
563 (0 == memcmp (session->addr, t->addr, t->addrlen)) )
567 if ( ((e_peer == GNUNET_YES) && (force_address == GNUNET_NO)) ||
568 ((e_peer == GNUNET_YES) && (force_address == GNUNET_YES) && (e_addr == GNUNET_YES)) ||
569 ((e_peer == GNUNET_YES) && (force_address == GNUNET_SYSERR)) )
577 lookup_session (struct Plugin *plugin,
578 const struct GNUNET_HELLO_Address *address)
582 for (pos = plugin->head; NULL != pos; pos = pos->next)
583 if ( (0 == memcmp (&address->peer, &pos->target, sizeof (struct GNUNET_PeerIdentity))) &&
584 (address->address_length == pos->addrlen) &&
585 (0 == memcmp (address->address, pos->addr, pos->addrlen)) )
592 exist_session (struct Plugin *plugin, struct Session *s)
594 struct Session * head;
596 GNUNET_assert (NULL != plugin);
597 GNUNET_assert (NULL != s);
599 for (head = plugin->head; head != NULL; head = head->next)
608 * Deleting the session
609 * Must not be used afterwards
613 delete_session (struct Session *s)
615 struct Plugin *plugin = s->plugin;
616 stop_session_timeout(s);
618 GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s);
619 struct HTTP_Message *msg = s->msg_head;
620 struct HTTP_Message *tmp = NULL;
626 GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
627 if (msg->transmit_cont != NULL)
629 msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
635 if (s->msg_tk != NULL)
637 GNUNET_SERVER_mst_destroy (s->msg_tk);
640 GNUNET_free (s->addr);
641 GNUNET_free_non_null (s->server_recv);
642 GNUNET_free_non_null (s->server_send);
648 create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
649 const void *addr, size_t addrlen)
651 struct Session *s = NULL;
652 struct GNUNET_ATS_Information ats;
654 GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) ||
655 (addrlen == sizeof (struct IPv4HttpAddress)));
660 if (addrlen == sizeof (struct IPv4HttpAddress))
662 struct IPv4HttpAddress *a4 = (struct IPv4HttpAddress *) addr;
663 struct sockaddr_in s4;
665 if (0 == ntohs(a4->u4_port))
668 s4.sin_family = AF_INET;
669 s4.sin_addr.s_addr = a4->ipv4_addr;
670 s4.sin_port = a4->u4_port;
671 #if HAVE_SOCKADDR_IN_SIN_LEN
672 s4.sin_len = sizeof (struct sockaddr_in);
674 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in));
676 if (addrlen == sizeof (struct IPv6HttpAddress))
678 struct IPv6HttpAddress *a6 = (struct IPv6HttpAddress *) addr;
679 struct sockaddr_in6 s6;
681 if (0 == ntohs(a6->u6_port))
684 s6.sin6_family = AF_INET6;
685 s6.sin6_addr = a6->ipv6_addr;
686 s6.sin6_port = a6->u6_port;
687 #if HAVE_SOCKADDR_IN_SIN_LEN
688 s6.sin6_len = sizeof (struct sockaddr_in6);
690 ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s6, sizeof (struct sockaddr_in6));
693 s = GNUNET_malloc (sizeof (struct Session));
694 memcpy (&s->target, target, sizeof (struct GNUNET_PeerIdentity));
696 s->addr = GNUNET_malloc (addrlen);
697 memcpy (s->addr, addr, addrlen);
698 s->addrlen = addrlen;
699 s->ats_address_network_type = ats.value;
702 start_session_timeout(s);
708 notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
711 struct Plugin *plugin = cls;
713 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
714 "Notifying transport about ending session %p (`%s')\n",
716 http_plugin_address_to_string(NULL, s->addr,s->addrlen));
718 plugin->env->session_end (plugin->env->cls, peer, s);
724 * Creates a new outbound session the transport service will use to send data to the
727 * @param cls the plugin
728 * @param address the address
729 * @return the session or NULL of max connections exceeded
731 static struct Session *
732 http_get_session (void *cls,
733 const struct GNUNET_HELLO_Address *address)
735 struct Plugin *plugin = cls;
736 struct Session * s = NULL;
739 GNUNET_assert (plugin != NULL);
740 GNUNET_assert (address != NULL);
741 GNUNET_assert (address->address != NULL);
743 /* find existing session */
744 s = lookup_session (plugin, address);
748 if (plugin->max_connections <= plugin->cur_connections)
750 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
751 "Maximum number of connections reached, "
752 "cannot connect to peer `%s'\n", GNUNET_i2s (&address->peer));
756 /* create new session */
757 addrlen = address->address_length;
759 GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) ||
760 (addrlen == sizeof (struct IPv4HttpAddress)));
762 s = create_session (plugin, &address->peer, address->address, address->address_length);
764 /* add new session */
765 GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s);
766 /* initiate new connection */
767 if (GNUNET_SYSERR == client_connect (s))
769 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
770 "Cannot connect to peer `%s' address `%s''\n",
771 http_plugin_address_to_string(NULL, s->addr, s->addrlen),
772 GNUNET_i2s (&s->target));
773 GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s);
783 * Function that can be used by the transport service to transmit
784 * a message using the plugin. Note that in the case of a
785 * peer disconnecting, the continuation MUST be called
786 * prior to the disconnect notification itself. This function
787 * will be called with this peer's HELLO message to initiate
788 * a fresh connection to another peer.
791 * @param session which session must be used
792 * @param msgbuf the message to transmit
793 * @param msgbuf_size number of bytes in 'msgbuf'
794 * @param priority how important is the message (most plugins will
795 * ignore message priority and just FIFO)
796 * @param to how long to wait at most for the transmission (does not
797 * require plugins to discard the message after the timeout,
798 * just advisory for the desired delay; most plugins will ignore
800 * @param cont continuation to call once the message has
801 * been transmitted (or if the transport is ready
802 * for the next transmission call; or if the
803 * peer disconnected...); can be NULL
804 * @param cont_cls closure for cont
805 * @return number of bytes used (on the physical network, with overheads);
806 * -1 on hard errors (i.e. address invalid); 0 is a legal value
807 * and does NOT mean that the message was not transmitted (DV)
810 http_plugin_send (void *cls,
811 struct Session *session,
812 const char *msgbuf, size_t msgbuf_size,
813 unsigned int priority,
814 struct GNUNET_TIME_Relative to,
815 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
817 struct Plugin *plugin = cls;
818 struct HTTP_Message *msg;
822 GNUNET_assert (plugin != NULL);
823 GNUNET_assert (session != NULL);
825 /* lookup if session is really existing */
829 if ((tmp == session) &&
830 (0 == memcmp (&session->target, &tmp->target, sizeof (struct GNUNET_PeerIdentity))) &&
831 (session->addrlen == tmp->addrlen) &&
832 (0 == memcmp (session->addr, tmp->addr, tmp->addrlen)))
842 /* create new message and schedule */
843 msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size);
845 msg->size = msgbuf_size;
847 msg->buf = (char *) &msg[1];
848 msg->transmit_cont = cont;
849 msg->transmit_cont_cls = cont_cls;
850 memcpy (msg->buf, msgbuf, msgbuf_size);
852 reschedule_session_timeout (session);
854 if (session->inbound == GNUNET_NO)
856 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
857 "Using outbound client session %p to send to `%s'\n", session,
858 GNUNET_i2s (&session->target));
859 client_send (session, msg);
862 if (session->inbound == GNUNET_YES)
864 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
865 "Using inbound server %p session to send to `%s'\n", session,
866 GNUNET_i2s (&session->target));
867 server_send (session, msg);
876 * Function that can be used to force the plugin to disconnect
877 * from the given peer and cancel all previous transmissions
878 * (and their continuationc).
881 * @param target peer from which to disconnect
884 http_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
886 struct Plugin *plugin = cls;
887 struct Session *next = NULL;
888 struct Session *s = plugin->head;
890 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
891 "Transport tells me to disconnect `%s'\n",
892 GNUNET_i2s (target));
896 if (0 == memcmp (target, &s->target, sizeof (struct GNUNET_PeerIdentity)))
898 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
899 "Disconnecting %s session %p to `%s'\n",
900 (s->inbound == GNUNET_NO) ? "outbound" : "inbound",
901 s, GNUNET_i2s (target));
903 if (s->inbound == GNUNET_NO)
904 GNUNET_assert (GNUNET_OK == client_disconnect (s));
906 GNUNET_assert (GNUNET_OK == server_disconnect (s));
914 find_address (struct Plugin *plugin, const struct sockaddr *addr, socklen_t addrlen)
917 struct IPv4HttpAddressWrapper *w_t4 = NULL;
918 struct IPv6HttpAddressWrapper *w_t6 = NULL;
920 af = addr->sa_family;
924 w_t4 = plugin->ipv4_addr_head;
925 struct sockaddr_in *a4 = (struct sockaddr_in *) addr;
929 int res = memcmp (&w_t4->addr.ipv4_addr,
931 sizeof (struct in_addr));
935 if (a4->sin_port != w_t4->addr.u4_port)
946 w_t6 = plugin->ipv6_addr_head;
947 struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) addr;
951 int res = memcmp (&w_t6->addr6.ipv6_addr, &a6->sin6_addr,
952 sizeof (struct in6_addr));
956 if (a6->sin6_port != w_t6->addr6.u6_port)
973 nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
976 struct Plugin *plugin = cls;
977 struct IPv4HttpAddressWrapper *w_t4 = NULL;
978 struct IPv6HttpAddressWrapper *w_t6 = NULL;
981 af = addr->sa_family;
985 w_t4 = find_address (plugin, addr, addrlen);
988 struct sockaddr_in *a4 = (struct sockaddr_in *) addr;
989 w_t4 = GNUNET_malloc (sizeof (struct IPv4HttpAddressWrapper));
990 memcpy (&w_t4->addr.ipv4_addr, &a4->sin_addr, sizeof (struct in_addr));
991 w_t4->addr.u4_port = a4->sin_port;
993 GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head,
994 plugin->ipv4_addr_tail, w_t4);
996 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
997 "Notifying transport to add IPv4 address `%s'\n",
998 http_plugin_address_to_string (NULL, &w_t4->addr,
1001 plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr,
1002 sizeof (struct IPv4HttpAddress));
1006 w_t6 = find_address (plugin, addr, addrlen);
1009 w_t6 = GNUNET_malloc (sizeof (struct IPv6HttpAddressWrapper));
1010 struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) addr;
1011 memcpy (&w_t6->addr6.ipv6_addr, &a6->sin6_addr, sizeof (struct in6_addr));
1012 w_t6->addr6.u6_port = a6->sin6_port;
1014 GNUNET_CONTAINER_DLL_insert (plugin->ipv6_addr_head,
1015 plugin->ipv6_addr_tail, w_t6);
1017 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1018 "Notifying transport to add IPv6 address `%s'\n",
1019 http_plugin_address_to_string (NULL, &w_t6->addr6,
1022 plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6,
1023 sizeof (struct IPv6HttpAddress));
1034 nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
1037 struct Plugin *plugin = cls;
1038 struct IPv4HttpAddressWrapper *w_t4 = NULL;
1039 struct IPv6HttpAddressWrapper *w_t6 = NULL;
1042 af = addr->sa_family;
1046 w_t4 = find_address (plugin, addr, addrlen);
1051 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1052 "Notifying transport to remove IPv4 address `%s'\n",
1053 http_plugin_address_to_string (NULL, &w_t4->addr,
1056 plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr,
1057 sizeof (struct IPv4HttpAddress));
1059 GNUNET_CONTAINER_DLL_remove (plugin->ipv4_addr_head, plugin->ipv4_addr_tail,
1064 w_t6 = find_address (plugin, addr, addrlen);
1068 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1069 "Notifying transport to remove IPv6 address `%s'\n",
1070 http_plugin_address_to_string (NULL, &w_t6->addr6,
1074 plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6,
1075 sizeof (struct IPv6HttpAddress));
1077 GNUNET_CONTAINER_DLL_remove (plugin->ipv6_addr_head, plugin->ipv6_addr_tail,
1088 * Our external IP address/port mapping has changed.
1090 * @param cls closure, the 'struct LocalAddrList'
1091 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1092 * the previous (now invalid) one
1093 * @param addr either the previous or the new public IP address
1094 * @param addrlen actual lenght of the address
1097 nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
1100 GNUNET_assert (cls != NULL);
1101 struct Plugin *plugin = cls;
1103 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1104 "NPMC called %s to address `%s'\n",
1105 (add_remove == GNUNET_NO) ? "remove" : "add",
1106 GNUNET_a2s (addr, addrlen));
1111 nat_add_address (cls, add_remove, addr, addrlen);
1114 nat_remove_address (cls, add_remove, addr, addrlen);
1121 http_check_ipv6 (struct Plugin *plugin)
1123 struct GNUNET_NETWORK_Handle *desc = NULL;
1125 if (plugin->ipv6 == GNUNET_YES)
1127 /* probe IPv6 support */
1128 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1131 if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
1134 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1136 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
1138 ("Disabling IPv6 since it is not supported on this system!\n"));
1139 plugin->ipv6 = GNUNET_NO;
1143 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1147 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1148 "Testing IPv6 on this system: %s\n",
1149 (plugin->ipv6 == GNUNET_YES) ? "successful" : "failed");
1155 http_get_addresses (struct Plugin *plugin, const char *serviceName,
1156 const struct GNUNET_CONFIGURATION_Handle *cfg,
1157 struct sockaddr ***addrs, socklen_t ** addr_lens)
1160 unsigned long long port;
1161 struct addrinfo hints;
1162 struct addrinfo *res;
1163 struct addrinfo *pos;
1164 struct addrinfo *next;
1168 struct sockaddr **saddrs;
1169 socklen_t *saddrlens;
1175 disablev6 = !plugin->ipv6;
1178 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT"))
1180 GNUNET_break (GNUNET_OK ==
1181 GNUNET_CONFIGURATION_get_value_number (cfg, serviceName,
1185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1187 ("Require valid port number for service in configuration!\n"));
1188 return GNUNET_SYSERR;
1193 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
1194 "Starting in listen only mode\n");
1195 return -1; /* listen only */
1199 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO"))
1201 GNUNET_break (GNUNET_OK ==
1202 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName,
1203 "BINDTO", &hostname));
1208 if (hostname != NULL)
1210 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1211 "Resolving `%s' since that is where `%s' will bind to.\n",
1212 hostname, serviceName);
1213 memset (&hints, 0, sizeof (struct addrinfo));
1215 hints.ai_family = AF_INET;
1216 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1219 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"),
1220 hostname, gai_strerror (ret));
1221 GNUNET_free (hostname);
1222 return GNUNET_SYSERR;
1226 while (NULL != (pos = next))
1228 next = pos->ai_next;
1229 if ((disablev6) && (pos->ai_family == AF_INET6))
1235 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1236 _("Failed to find %saddress for `%s'.\n"),
1237 disablev6 ? "IPv4 " : "", hostname);
1239 GNUNET_free (hostname);
1240 return GNUNET_SYSERR;
1243 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1244 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1247 while (NULL != (pos = next))
1249 next = pos->ai_next;
1250 if ((disablev6) && (pos->ai_family == AF_INET6))
1252 if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0))
1253 continue; /* not TCP */
1254 if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0))
1255 continue; /* huh? */
1256 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1257 "Service will bind to `%s'\n", GNUNET_a2s (pos->ai_addr,
1259 if (pos->ai_family == AF_INET)
1261 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
1262 saddrlens[i] = pos->ai_addrlen;
1263 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1264 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1265 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1269 GNUNET_assert (pos->ai_family == AF_INET6);
1270 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
1271 saddrlens[i] = pos->ai_addrlen;
1272 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1273 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1274 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1278 GNUNET_free (hostname);
1284 /* will bind against everything, just set port */
1290 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1291 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1293 saddrlens[i] = sizeof (struct sockaddr_in);
1294 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1295 #if HAVE_SOCKADDR_IN_SIN_LEN
1296 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1298 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1299 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1305 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1306 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1308 saddrlens[i] = sizeof (struct sockaddr_in6);
1309 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1310 #if HAVE_SOCKADDR_IN_SIN_LEN
1311 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1313 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1314 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1316 saddrlens[i] = sizeof (struct sockaddr_in);
1317 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1318 #if HAVE_SOCKADDR_IN_SIN_LEN
1319 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1321 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1322 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1326 *addr_lens = saddrlens;
1331 start_report_addresses (struct Plugin *plugin)
1333 int res = GNUNET_OK;
1334 struct sockaddr **addrs;
1335 socklen_t *addrlens;
1338 http_get_addresses (plugin, plugin->name, plugin->env->cfg, &addrs,
1340 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1341 _("Found %u addresses to report to NAT service\n"), res);
1343 if (GNUNET_SYSERR == res)
1350 GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port,
1352 (const struct sockaddr **) addrs, addrlens,
1353 &nat_port_map_callback, NULL, plugin);
1357 GNUNET_assert (addrs[res] != NULL);
1358 GNUNET_free (addrs[res]);
1360 GNUNET_free_non_null (addrs);
1361 GNUNET_free_non_null (addrlens);
1366 stop_report_addresses (struct Plugin *plugin)
1369 /* Stop NAT handle */
1370 if (NULL != plugin->nat)
1371 GNUNET_NAT_unregister (plugin->nat);
1373 /* Clean up addresses */
1374 struct IPv4HttpAddressWrapper *w_t4;
1375 struct IPv6HttpAddressWrapper *w_t6;
1377 while (plugin->ipv4_addr_head != NULL)
1379 w_t4 = plugin->ipv4_addr_head;
1380 GNUNET_CONTAINER_DLL_remove (plugin->ipv4_addr_head, plugin->ipv4_addr_tail,
1385 while (plugin->ipv6_addr_head != NULL)
1387 w_t6 = plugin->ipv6_addr_head;
1388 GNUNET_CONTAINER_DLL_remove (plugin->ipv6_addr_head, plugin->ipv6_addr_tail,
1395 * Function called when the service shuts down. Unloads our plugins
1396 * and cancels pending validations.
1398 * @param cls closure, unused
1399 * @param tc task context (unused)
1402 notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1404 struct Plugin *plugin = cls;
1405 struct HttpAddress *eaddr;
1409 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
1411 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1414 uri_len = strlen (plugin->external_hostname) + 1;
1415 eaddr_len = sizeof (struct HttpAddress) + uri_len;
1416 eaddr = GNUNET_malloc (eaddr_len);
1417 eaddr->addr_len = htonl (strlen (plugin->external_hostname) + 1);
1418 eaddr->addr = (void *) &eaddr[1];
1419 memcpy (&eaddr->addr, plugin->external_hostname, uri_len);
1420 plugin->env->notify_address (plugin->env->cls, GNUNET_YES, eaddr, eaddr_len);
1421 plugin->ext_addr = eaddr;
1422 plugin->ext_addr_len = eaddr_len;
1427 configure_plugin (struct Plugin *plugin)
1429 int res = GNUNET_OK;
1432 if (GNUNET_CONFIGURATION_have_value
1433 (plugin->env->cfg, plugin->name, "USE_IPv4"))
1436 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
1440 plugin->ipv4 = GNUNET_YES;
1443 if (GNUNET_CONFIGURATION_have_value
1444 (plugin->env->cfg, plugin->name, "USE_IPv6"))
1447 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
1451 plugin->ipv6 = GNUNET_YES;
1453 if ((plugin->ipv4 == GNUNET_NO) && (plugin->ipv6 == GNUNET_NO))
1455 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1457 ("Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"),
1459 res = GNUNET_SYSERR;
1462 /* Reading port number from config file */
1463 unsigned long long port;
1466 GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
1467 "PORT", &port)) || (port > 65535))
1469 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1470 _("Port is required! Fix in configuration\n"),
1472 res = GNUNET_SYSERR;
1475 plugin->port = port;
1477 plugin->client_only = GNUNET_NO;
1478 if (plugin->port == 0)
1480 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1481 _("Port 0, client only mode\n"));
1482 plugin->client_only = GNUNET_YES;
1485 char *bind4_address = NULL;
1487 if ((plugin->ipv4 == GNUNET_YES) &&
1489 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
1490 "BINDTO", &bind4_address)))
1492 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1493 "Binding %s plugin to specific IPv4 address: `%s'\n",
1494 plugin->protocol, bind4_address);
1495 plugin->server_addr_v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
1497 inet_pton (AF_INET, bind4_address, &plugin->server_addr_v4->sin_addr))
1499 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1501 ("Specific IPv4 address `%s' for plugin %s in configuration file is invalid! Binding to all addresses!\n"),
1502 bind4_address, plugin->protocol);
1503 GNUNET_free (plugin->server_addr_v4);
1504 plugin->server_addr_v4 = NULL;
1508 plugin->server_addr_v4->sin_family = AF_INET;
1509 plugin->server_addr_v4->sin_port = htons (plugin->port);
1511 GNUNET_free (bind4_address);
1514 char *bind6_address = NULL;
1516 if ((plugin->ipv6 == GNUNET_YES) &&
1518 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
1519 "BINDTO6", &bind6_address)))
1521 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1522 "Binding %s plugin to specific IPv6 address: `%s'\n",
1523 plugin->protocol, bind6_address);
1524 plugin->server_addr_v6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
1526 inet_pton (AF_INET6, bind6_address, &plugin->server_addr_v6->sin6_addr))
1528 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
1530 ("Specific IPv6 address `%s' for plugin %s in configuration file is invalid! Binding to all addresses!\n"),
1531 bind6_address, plugin->protocol);
1532 GNUNET_free (plugin->server_addr_v6);
1533 plugin->server_addr_v6 = NULL;
1537 plugin->server_addr_v6->sin6_family = AF_INET6;
1538 plugin->server_addr_v6->sin6_port = htons (plugin->port);
1540 GNUNET_free (bind6_address);
1543 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
1544 "EXTERNAL_HOSTNAME", &plugin->external_hostname))
1546 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1547 _("Using external hostname `%s'\n"), plugin->external_hostname);
1548 plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (¬ify_external_hostname, plugin);
1551 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1552 _("No external hostname configured\n"));
1555 /* Optional parameters */
1556 unsigned long long maxneigh;
1559 GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
1560 "MAX_CONNECTIONS", &maxneigh))
1562 plugin->max_connections = maxneigh;
1568 #define TESTING GNUNET_NO
1571 #define TIMEOUT_LOG GNUNET_ERROR_TYPE_ERROR
1572 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
1574 #define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG
1575 #define TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
1580 * Session was idle, so disconnect it
1583 session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1585 GNUNET_assert (NULL != cls);
1586 struct Session *s = cls;
1588 s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1589 GNUNET_log (TIMEOUT_LOG,
1590 "Session %p was idle for %llu ms, disconnecting\n",
1591 s, (unsigned long long) TIMEOUT.rel_value);
1593 /* call session destroy function */
1594 if (s->inbound == GNUNET_NO)
1595 GNUNET_assert (GNUNET_OK == client_disconnect (s));
1597 GNUNET_assert (GNUNET_OK == server_disconnect (s));
1602 * Start session timeout
1605 start_session_timeout (struct Session *s)
1607 GNUNET_assert (NULL != s);
1608 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
1609 s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
1612 GNUNET_log (TIMEOUT_LOG,
1613 "Timeout for session %p set to %llu ms\n",
1614 s, (unsigned long long) TIMEOUT.rel_value);
1619 * Increment session timeout due to activity
1622 reschedule_session_timeout (struct Session *s)
1624 GNUNET_assert (NULL != s);
1625 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task);
1627 GNUNET_SCHEDULER_cancel (s->timeout_task);
1628 s->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
1631 GNUNET_log (TIMEOUT_LOG,
1632 "Timeout rescheduled for session %p set to %llu ms\n",
1633 s, (unsigned long long) TIMEOUT.rel_value);
1641 stop_session_timeout (struct Session *s)
1643 GNUNET_assert (NULL != s);
1645 if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
1647 GNUNET_SCHEDULER_cancel (s->timeout_task);
1648 s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1649 GNUNET_log (TIMEOUT_LOG,
1650 "Timeout stopped for session %p\n",
1656 * Entry point for the plugin.
1659 LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
1661 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1662 struct GNUNET_TRANSPORT_PluginFunctions *api;
1663 struct Plugin *plugin;
1666 if (NULL == env->receive)
1668 /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1669 initialze the plugin or the API */
1670 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1672 api->address_pretty_printer = &http_plugin_address_pretty_printer;
1673 api->address_to_string = &http_plugin_address_to_string;
1674 api->string_to_address = &http_string_to_address;
1678 plugin = GNUNET_malloc (sizeof (struct Plugin));
1680 plugin->outbound_sessions = 0;
1681 plugin->inbound_sessions = 0;
1682 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1684 api->disconnect = &http_plugin_disconnect;
1685 api->address_pretty_printer = &http_plugin_address_pretty_printer;
1686 api->check_address = &http_plugin_address_suggested;
1687 api->address_to_string = &http_plugin_address_to_string;
1688 api->string_to_address = &http_string_to_address;
1689 api->get_session = &http_get_session;
1690 api->send = &http_plugin_send;
1693 plugin->name = "transport-https";
1694 plugin->protocol = "https";
1696 plugin->name = "transport-http";
1697 plugin->protocol = "http";
1699 /* Configure plugin from configuration */
1700 res = configure_plugin (plugin);
1701 if (res == GNUNET_SYSERR)
1703 GNUNET_free_non_null (plugin->server_addr_v4);
1704 GNUNET_free_non_null (plugin->server_addr_v6);
1705 GNUNET_free (plugin);
1710 /* checking IPv6 support */
1711 http_check_ipv6 (plugin);
1714 res = client_start (plugin);
1715 if (res == GNUNET_SYSERR)
1717 GNUNET_free_non_null (plugin->server_addr_v4);
1718 GNUNET_free_non_null (plugin->server_addr_v6);
1719 GNUNET_free (plugin);
1725 if (plugin->client_only == GNUNET_NO)
1727 res = server_start (plugin);
1728 if (res == GNUNET_SYSERR)
1730 server_stop (plugin);
1731 client_stop (plugin);
1733 GNUNET_free_non_null (plugin->server_addr_v4);
1734 GNUNET_free_non_null (plugin->server_addr_v6);
1735 GNUNET_free (plugin);
1740 /* Report addresses to transport service */
1741 start_report_addresses (plugin);
1743 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1744 "Plugin `%s' loaded\n", plugin->name);
1750 * Exit point from the plugin.
1753 LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
1755 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1756 struct Plugin *plugin = api->cls;
1758 struct Session *next;
1766 if (GNUNET_SCHEDULER_NO_TASK != plugin->notify_ext_task)
1768 GNUNET_SCHEDULER_cancel (plugin->notify_ext_task);
1769 plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
1772 if (NULL != plugin->ext_addr)
1774 plugin->env->notify_address (plugin->env->cls, GNUNET_NO, plugin->ext_addr, plugin->ext_addr_len);
1775 GNUNET_free (plugin->ext_addr);
1778 /* Stop reporting addresses to transport service */
1779 stop_report_addresses (plugin);
1781 /* cleaning up sessions */
1786 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1787 "Disconnecting `%s' \n", GNUNET_i2s (&s->target));
1788 if (s->inbound == GNUNET_NO)
1789 GNUNET_assert (GNUNET_OK == client_disconnect (s));
1791 GNUNET_assert (GNUNET_OK == server_disconnect (s));
1795 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Stopping server\n");
1797 server_stop (plugin);
1799 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Stopping client\n");
1801 client_stop (plugin);
1803 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
1804 "Plugin `%s' unloaded\n", plugin->name);
1805 GNUNET_free_non_null (plugin->server_addr_v4);
1806 GNUNET_free_non_null (plugin->server_addr_v6);
1807 GNUNET_free_non_null (plugin->external_hostname);
1808 GNUNET_free (plugin);
1813 /* end of plugin_transport_http.c */