aboutsummaryrefslogtreecommitdiff
path: root/src/upnp/upnp_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/upnp/upnp_init.c')
-rw-r--r--src/upnp/upnp_init.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/upnp/upnp_init.c b/src/upnp/upnp_init.c
new file mode 100644
index 000000000..3dc0d2b7c
--- /dev/null
+++ b/src/upnp/upnp_init.c
@@ -0,0 +1,208 @@
1/*
2 This file is part of GNUnet
3 (C) 2006 Christian Grothoff (and other contributing authors)
4
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 2, or (at your
8 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 General Public License for more details.
14
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.
19*/
20
21/**
22 * @file src/transports/upnp/init.c
23 * @brief API for UPnP access
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "upnp.h"
30#include "gnunet_upnp_service.h"
31#include "gnunet_core.h"
32
33static struct GNUNET_GE_Context *ectx;
34
35static struct GNUNET_GC_Configuration *cfg;
36
37static struct GNUNET_CronManager *cron;
38
39static struct GNUNET_Mutex *lock;
40
41typedef struct
42{
43 unsigned short port;
44 const char *proto;
45} PMap;
46
47static PMap *maps;
48
49static unsigned int maps_size;
50
51static struct GNUNET_ThreadHandle *discovery;
52
53static int discovery_socket;
54
55/**
56 * Obtain the public/external IP address.
57 *
58 * @return GNUNET_SYSERR on error, GNUNET_OK on success
59 */
60static int
61gnunet_upnp_get_public_ip (struct in_addr *address)
62{
63 const char *ip;
64 socklen_t socklen;
65 struct sockaddr *sa;
66 struct sockaddr_in s4;
67 int ret;
68
69 ip = gaim_upnp_get_public_ip ();
70 if (ip == NULL)
71 return GNUNET_SYSERR;
72 socklen = sizeof (struct sockaddr_in);
73 sa = (struct sockaddr *) &s4;
74 ret = GNUNET_get_ip_from_hostname (NULL, ip, AF_INET, &sa, &socklen);
75 if (ret == GNUNET_OK)
76 *address = s4.sin_addr;
77 return ret;
78}
79
80static void
81kill_discovery ()
82{
83 void *unused;
84
85 if (discovery != NULL)
86 {
87 SHUTDOWN (discovery_socket, SHUT_RDWR);
88 CLOSE (discovery_socket);
89 GNUNET_thread_join (discovery, &unused);
90 discovery = NULL;
91 }
92}
93
94static void *
95discover_thread ()
96{
97 gaim_upnp_discover (ectx, cfg, discovery_socket);
98 return NULL;
99}
100
101/**
102 * Periodically try to (re)discover UPnP access points.
103 */
104static void
105discover (void *unused)
106{
107 kill_discovery ();
108 discovery_socket = SOCKET (PF_INET, SOCK_DGRAM, 0);
109 if (discovery_socket == -1)
110 return;
111 discovery = GNUNET_thread_create (&discover_thread, NULL, 1024 * 128);
112}
113
114/**
115 * Periodically repeat our requests for port mappings.
116 */
117static void
118portmap (void *unused)
119{
120 unsigned int i;
121
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,
126 maps[i].proto);
127 GNUNET_mutex_unlock (lock);
128}
129
130
131/**
132 * Get the external IP address for the local machine.
133 *
134 * @return GNUNET_SYSERR on error, GNUNET_OK on success
135 */
136static int
137gnunet_upnp_get_ip (unsigned short port,
138 const char *protocol, struct in_addr *address)
139{
140 unsigned int i;
141
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))
145 break;
146 if (i == maps_size)
147 {
148 /* new entry! */
149 GNUNET_array_grow (maps, maps_size, maps_size + 1);
150 maps[i].proto = protocol;
151 maps[i].port = port;
152 gaim_upnp_change_port_mapping (ectx, cfg, GNUNET_YES, port, protocol);
153 }
154 GNUNET_mutex_unlock (lock);
155 return gnunet_upnp_get_public_ip (address);
156}
157
158
159/**
160 * Get the external IP address for the local machine.
161 */
162GNUNET_UPnP_ServiceAPI *
163provide_module_upnp (GNUNET_CoreAPIForPlugins * capi)
164{
165 static GNUNET_UPnP_ServiceAPI api;
166
167 ectx = capi->ectx;
168 cfg = capi->cfg;
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;
176 return &api;
177}
178
179/**
180 * Shutdown UPNP.
181 */
182int
183release_module_upnp ()
184{
185 unsigned int i;
186
187 if (cron == NULL)
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,
192 maps[i].proto);
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);
197 kill_discovery ();
198 cron = NULL;
199 GNUNET_mutex_destroy (lock);
200 lock = NULL;
201 GNUNET_array_grow (maps, maps_size, 0);
202 ectx = NULL;
203 cfg = NULL;
204 return GNUNET_OK;
205}
206
207
208/* end of init.c */