2 This file is part of GNUnet
3 (C) 2006 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 upnp/upnp_init.c
23 * @brief API for UPnP access
24 * @author Christian Grothoff
28 #include "gnunet_util.h"
30 #include "gnunet_upnp_service.h"
31 #include "gnunet_core.h"
33 static struct GNUNET_GE_Context *ectx;
35 static struct GNUNET_GC_Configuration *cfg;
37 static struct GNUNET_CronManager *cron;
39 static struct GNUNET_Mutex *lock;
49 static unsigned int maps_size;
51 static struct GNUNET_ThreadHandle *discovery;
53 static struct GNUNET_NETWORK_Handle *discovery_socket;
56 * Obtain the public/external IP address.
58 * @return GNUNET_SYSERR on error, GNUNET_OK on success
61 gnunet_upnp_get_public_ip (struct in_addr *address)
66 struct sockaddr_in s4;
69 ip = gaim_upnp_get_public_ip ();
72 socklen = sizeof (struct sockaddr_in);
73 sa = (struct sockaddr *) &s4;
74 ret = GNUNET_get_ip_from_hostname (NULL, ip, AF_INET, &sa, &socklen);
76 *address = s4.sin_addr;
85 if (discovery != NULL)
87 GNUNET_IO_shutdown (discovery_socket, SHUT_RDWR);
88 GNUNET_IO_close (&discovery_socket);
89 GNUNET_thread_join (discovery, &unused);
97 gaim_upnp_discover (ectx, cfg, discovery_socket);
102 * Periodically try to (re)discover UPnP access points.
105 discover (void *unused)
108 discovery_socket = GNUNET_IO_socket (PF_INET, SOCK_DGRAM, 0);
109 if (NULL == discovery_socket)
111 discovery = GNUNET_thread_create (&discover_thread, NULL, 1024 * 128);
115 * Periodically repeat our requests for port mappings.
118 portmap (void *unused)
122 GNUNET_mutex_lock (lock);
123 for (i = 0; i < maps_size; i++)
124 gaim_upnp_change_port_mapping (ectx,
125 cfg, GNUNET_NO, maps[i].port,
127 GNUNET_mutex_unlock (lock);
132 * Get the external IP address for the local machine.
134 * @return GNUNET_SYSERR on error, GNUNET_OK on success
137 gnunet_upnp_get_ip (unsigned short port,
138 const char *protocol, struct in_addr *address)
142 GNUNET_mutex_lock (lock);
143 for (i = 0; i < maps_size; i++)
144 if ((0 == strcmp (maps[i].proto, protocol)) && (maps[i].port == port))
149 GNUNET_array_grow (maps, maps_size, maps_size + 1);
150 maps[i].proto = protocol;
152 gaim_upnp_change_port_mapping (ectx, cfg, GNUNET_YES, port, protocol);
154 GNUNET_mutex_unlock (lock);
155 return gnunet_upnp_get_public_ip (address);
160 * Get the external IP address for the local machine.
162 GNUNET_UPnP_ServiceAPI *
163 provide_module_upnp (GNUNET_CoreAPIForPlugins * capi)
165 static GNUNET_UPnP_ServiceAPI api;
169 cron = GNUNET_cron_create (ectx);
170 lock = GNUNET_mutex_create (GNUNET_NO);
171 GNUNET_cron_start (cron);
172 GNUNET_cron_add_job (cron, &discover, 0, 5 * GNUNET_CRON_MINUTES, NULL);
173 GNUNET_cron_add_job (cron, &portmap, 150 * GNUNET_CRON_SECONDS,
174 5 * GNUNET_CRON_MINUTES, NULL);
175 api.get_ip = gnunet_upnp_get_ip;
183 release_module_upnp ()
188 return GNUNET_SYSERR; /* not loaded! */
189 for (i = 0; i < maps_size; i++)
190 gaim_upnp_change_port_mapping (ectx,
191 cfg, GNUNET_NO, maps[i].port,
193 GNUNET_cron_stop (cron);
194 GNUNET_cron_del_job (cron, &discover, 5 * GNUNET_CRON_MINUTES, NULL);
195 GNUNET_cron_del_job (cron, &portmap, 5 * GNUNET_CRON_MINUTES, NULL);
196 GNUNET_cron_destroy (cron);
199 GNUNET_mutex_destroy (lock);
201 GNUNET_array_grow (maps, maps_size, 0);