aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-11-30 08:17:33 +0100
committerChristian Grothoff <christian@grothoff.org>2016-11-30 08:17:33 +0100
commite43df97dfdb10903dd53571ab07863d95740592c (patch)
tree5a4bfaffe744b311d3097eac17117a978a8c259c /src
parent1b4333f3a6a4f76aa76fc3abc21e8476ea0a92e3 (diff)
downloadgnunet-e43df97dfdb10903dd53571ab07863d95740592c.tar.gz
gnunet-e43df97dfdb10903dd53571ab07863d95740592c.zip
moving basic logic for launching nat-server helper to new NAT service
Diffstat (limited to 'src')
-rw-r--r--src/nat/Makefile.am3
-rw-r--r--src/nat/gnunet-service-nat.c1
-rw-r--r--src/nat/gnunet-service-nat_helper.c345
-rw-r--r--src/nat/gnunet-service-nat_helper.h74
4 files changed, 422 insertions, 1 deletions
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index 6e96c41ff..0ca6dc1d2 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -96,7 +96,8 @@ libgnunetnatnew_la_LDFLAGS = \
96 96
97gnunet_service_nat_SOURCES = \ 97gnunet_service_nat_SOURCES = \
98 gnunet-service-nat.c \ 98 gnunet-service-nat.c \
99 gnunet-service-nat_stun.c gnunet-service-nat_stun.h 99 gnunet-service-nat_stun.c gnunet-service-nat_stun.h \
100 gnunet-service-nat_helper.c gnunet-service-nat_helper.h
100gnunet_service_nat_LDADD = \ 101gnunet_service_nat_LDADD = \
101 $(top_builddir)/src/util/libgnunetutil.la \ 102 $(top_builddir)/src/util/libgnunetutil.la \
102 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 103 $(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 8499a9724..ffee6374e 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -35,6 +35,7 @@
35#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
36#include "gnunet_nat_service.h" 36#include "gnunet_nat_service.h"
37#include "gnunet-service-nat_stun.h" 37#include "gnunet-service-nat_stun.h"
38#include "gnunet-service-nat_helper.h"
38#include "nat.h" 39#include "nat.h"
39#include <gcrypt.h> 40#include <gcrypt.h>
40 41
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c
new file mode 100644
index 000000000..4867f5675
--- /dev/null
+++ b/src/nat/gnunet-service-nat_helper.c
@@ -0,0 +1,345 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
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 3, 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file nat/gnunet-service-nat_helper.c
23 * @brief runs the gnunet-helper-nat-server
24 * @author Milan Bouchet-Valat
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet-service-nat_helper.h"
30
31#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
32
33/**
34 * Information we keep per NAT helper process.
35 */
36struct HelperContext
37{
38
39 /**
40 * IP address we pass to the NAT helper.
41 */
42 const char *internal_address;
43
44 /**
45 * Function to call if we receive a reversal request.
46 */
47 GN_ReversalCallback cb;
48
49 /**
50 * Closure for @e cb.
51 */
52 void *cb_cls;
53
54 /**
55 * How long do we wait for restarting a crashed gnunet-helper-nat-server?
56 */
57 struct GNUNET_TIME_Relative server_retry_delay;
58
59 /**
60 * ID of select gnunet-helper-nat-server stdout read task
61 */
62 struct GNUNET_SCHEDULER_Task *server_read_task;
63
64 /**
65 * The process id of the server process (if behind NAT)
66 */
67 struct GNUNET_OS_Process *server_proc;
68
69 /**
70 * stdout pipe handle for the gnunet-helper-nat-server process
71 */
72 struct GNUNET_DISK_PipeHandle *server_stdout;
73
74 /**
75 * stdout file handle (for reading) for the gnunet-helper-nat-server process
76 */
77 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
78};
79
80
81/**
82 * Task that restarts the gnunet-helper-nat-server process after a crash
83 * after a certain delay.
84 *
85 * @param cls a `struct HelperContext`
86 */
87static void
88restart_nat_server (void *cls);
89
90
91/**
92 * Try again starting the helper later
93 *
94 * @param h context of the helper
95 */
96static void
97try_again (struct HelperContext *h)
98{
99 GNUNET_assert (NULL == h->server_read_task);
100 h->server_retry_delay
101 = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay);
102 h->server_read_task
103 = GNUNET_SCHEDULER_add_delayed (h->server_retry_delay,
104 &restart_nat_server,
105 h);
106}
107
108
109/**
110 * We have been notified that gnunet-helper-nat-server has written
111 * something to stdout. Handle the output, then reschedule this
112 * function to be called again once more is available.
113 *
114 * @param cls the `struct HelperContext`
115 */
116static void
117nat_server_read (void *cls)
118{
119 struct HelperContext *h = cls;
120 char mybuf[40];
121 ssize_t bytes;
122 int port;
123 const char *port_start;
124 struct sockaddr_in sin_addr;
125
126 h->server_read_task = NULL;
127 memset (mybuf,
128 0,
129 sizeof (mybuf));
130 bytes
131 = GNUNET_DISK_file_read (h->server_stdout_handle,
132 mybuf,
133 sizeof (mybuf));
134 if (bytes < 1)
135 {
136 LOG (GNUNET_ERROR_TYPE_DEBUG,
137 "Finished reading from server stdout with code: %d\n",
138 bytes);
139 if (0 != GNUNET_OS_process_kill (h->server_proc,
140- GNUNET_TERM_SIG))
141 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
142 "nat",
143 "kill");
144 GNUNET_OS_process_wait (h->server_proc);
145 GNUNET_OS_process_destroy (h->server_proc);
146 h->server_proc = NULL;
147 GNUNET_DISK_pipe_close (h->server_stdout);
148 h->server_stdout = NULL;
149 h->server_stdout_handle = NULL;
150 try_again (h);
151 return;
152 }
153
154 port_start = NULL;
155 for (size_t i = 0; i < sizeof (mybuf); i++)
156 {
157 if (mybuf[i] == '\n')
158 {
159 mybuf[i] = '\0';
160 break;
161 }
162 if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf)))
163 {
164 mybuf[i] = '\0';
165 port_start = &mybuf[i + 1];
166 }
167 }
168
169 /* construct socket address of sender */
170 memset (&sin_addr,
171 0,
172 sizeof (sin_addr));
173 sin_addr.sin_family = AF_INET;
174#if HAVE_SOCKADDR_IN_SIN_LEN
175 sin_addr.sin_len = sizeof (sin_addr);
176#endif
177 if ( (NULL == port_start) ||
178 (1 != SSCANF (port_start,
179 "%d",
180 &port)) ||
181 (-1 == inet_pton (AF_INET,
182 mybuf,
183 &sin_addr.sin_addr)))
184 {
185 /* should we restart gnunet-helper-nat-server? */
186 LOG (GNUNET_ERROR_TYPE_WARNING,
187 "nat",
188 _("gnunet-helper-nat-server generated malformed address `%s'\n"),
189 mybuf);
190 h->server_read_task
191 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
192 h->server_stdout_handle,
193 &nat_server_read,
194 h);
195 return;
196 }
197 sin_addr.sin_port = htons ((uint16_t) port);
198 LOG (GNUNET_ERROR_TYPE_DEBUG,
199 "gnunet-helper-nat-server read: %s:%d\n",
200 mybuf,
201 port);
202 h->cb (h->cb_cls,
203 &sin_addr);
204 h->server_read_task
205 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
206 h->server_stdout_handle,
207 &nat_server_read,
208 h);
209}
210
211
212/**
213 * Task that restarts the gnunet-helper-nat-server process after a crash
214 * after a certain delay.
215 *
216 * @param cls a `struct HelperContext`
217 */
218static void
219restart_nat_server (void *cls)
220{
221 struct HelperContext *h = cls;
222 char *binary;
223
224 h->server_read_task = NULL;
225 h->server_stdout
226 = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES,
227 GNUNET_NO, GNUNET_YES);
228 if (NULL == h->server_stdout)
229 {
230 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
231 "pipe");
232 try_again (h);
233 return;
234 }
235 LOG (GNUNET_ERROR_TYPE_DEBUG,
236 "Starting `%s' at `%s'\n",
237 "gnunet-helper-nat-server",
238 h->internal_address);
239 /* Start the server process */
240 binary
241 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
242 h->server_proc
243 = GNUNET_OS_start_process (GNUNET_NO,
244 0,
245 NULL,
246 h->server_stdout,
247 NULL,
248 binary,
249 "gnunet-helper-nat-server",
250 h->internal_address,
251 NULL);
252 GNUNET_free (binary);
253 if (NULL == h->server_proc)
254 {
255 LOG (GNUNET_ERROR_TYPE_WARNING,
256 "nat",
257 _("Failed to start %s\n"),
258 "gnunet-helper-nat-server");
259 GNUNET_DISK_pipe_close (h->server_stdout);
260 h->server_stdout = NULL;
261 try_again (h);
262 return;
263 }
264 /* Close the write end of the read pipe */
265 GNUNET_DISK_pipe_close_end (h->server_stdout,
266 GNUNET_DISK_PIPE_END_WRITE);
267 h->server_stdout_handle
268 = GNUNET_DISK_pipe_handle (h->server_stdout,
269 GNUNET_DISK_PIPE_END_READ);
270 h->server_read_task
271 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
272 h->server_stdout_handle,
273 &nat_server_read,
274 h);
275}
276
277
278/**
279 * Start the gnunet-helper-nat-server and process incoming
280 * requests.
281 *
282 * @param internal_address
283 * @param cb function to call if we receive a request
284 * @param cb_cls closure for @a cb
285 * @return NULL on error
286 */
287struct HelperContext *
288GN_start_gnunet_nat_server_ (const char *internal_address,
289 GN_ReversalCallback cb,
290 void *cb_cls)
291{
292 struct HelperContext *h;
293
294 h = GNUNET_new (struct HelperContext);
295 h->cb = cb;
296 h->cb_cls = cb_cls;
297 h->internal_address
298 = internal_address;
299 if (NULL == h->server_stdout)
300 {
301 GN_stop_gnunet_nat_server_ (h);
302 return NULL;
303 }
304 return h;
305}
306
307
308/**
309 * Start the gnunet-helper-nat-server and process incoming
310 * requests.
311 *
312 * @param h helper context to stop
313 */
314void
315GN_stop_gnunet_nat_server_ (struct HelperContext *h)
316{
317 if (NULL != h->server_read_task)
318 {
319 GNUNET_SCHEDULER_cancel (h->server_read_task);
320 h->server_read_task = NULL;
321 }
322 if (NULL != h->server_proc)
323 {
324 if (0 != GNUNET_OS_process_kill (h->server_proc,
325 GNUNET_TERM_SIG))
326 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
327 "nat",
328 "kill");
329 GNUNET_OS_process_wait (h->server_proc);
330 GNUNET_OS_process_destroy (h->server_proc);
331 h->server_proc = NULL;
332 GNUNET_DISK_pipe_close (h->server_stdout);
333 h->server_stdout = NULL;
334 h->server_stdout_handle = NULL;
335 }
336 if (NULL != h->server_stdout)
337 {
338 GNUNET_DISK_pipe_close (h->server_stdout);
339 h->server_stdout = NULL;
340 h->server_stdout_handle = NULL;
341 }
342 GNUNET_free (h);
343}
344
345/* end of gnunet-service-nat_helper.c */
diff --git a/src/nat/gnunet-service-nat_helper.h b/src/nat/gnunet-service-nat_helper.h
new file mode 100644
index 000000000..c3074d9ad
--- /dev/null
+++ b/src/nat/gnunet-service-nat_helper.h
@@ -0,0 +1,74 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
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 3, 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file nat/gnunet-service-nat_helper.h
23 * @brief runs the gnunet-helper-nat-server
24 * @author Milan Bouchet-Valat
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30
31/**
32 * Information we keep per NAT helper process.
33 */
34struct HelperContext;
35
36
37/**
38 * Function called whenever we get a connection reversal
39 * request from another peer.
40 *
41 * @param cls closure
42 * @param ra IP address of the peer who wants us to connect to it
43 */
44typedef void
45(*GN_ReversalCallback) (void *cls,
46 const struct sockaddr_in *ra);
47
48
49/**
50 * Start the gnunet-helper-nat-server and process incoming
51 * requests.
52 *
53 * @param internal_address
54 * @param cb function to call if we receive a request
55 * @param cb_cls closure for @a cb
56 * @return NULL on error
57 */
58struct HelperContext *
59GN_start_gnunet_nat_server_ (const char *internal_address,
60 GN_ReversalCallback cb,
61 void *cb_cls);
62
63
64/**
65 * Start the gnunet-helper-nat-server and process incoming
66 * requests.
67 *
68 * @param h helper context to stop
69 */
70void
71GN_stop_gnunet_nat_server_ (struct HelperContext *h);
72
73
74/* end of gnunet-service-nat_helper.h */