diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-07-01 14:17:34 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-07-01 14:17:34 +0000 |
commit | 6129a0a79b56923d483216ba78ba250c2cf0403c (patch) | |
tree | bb379ed2d3035497cf939e28a21ab70985a3dd0a | |
parent | 0e4eb80cafbc54240c5d82589dea973d6ee22df3 (diff) | |
download | gnunet-6129a0a79b56923d483216ba78ba250c2cf0403c.tar.gz gnunet-6129a0a79b56923d483216ba78ba250c2cf0403c.zip |
more hacking on nat test code
-rw-r--r-- | src/include/gnunet_nat_lib.h | 2 | ||||
-rw-r--r-- | src/nat/nat.c | 27 | ||||
-rw-r--r-- | src/nat/nat_test.c | 296 |
3 files changed, 310 insertions, 15 deletions
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h index 07f6ca5e8..1eb8b5703 100644 --- a/src/include/gnunet_nat_lib.h +++ b/src/include/gnunet_nat_lib.h | |||
@@ -162,7 +162,7 @@ typedef void (*GNUNET_NAT_TestCallback)(void *cls, | |||
162 | * | 162 | * |
163 | * @param cfg configuration for the NAT traversal | 163 | * @param cfg configuration for the NAT traversal |
164 | * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP | 164 | * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP |
165 | * @param bnd_port port to bind to | 165 | * @param bnd_port port to bind to, 0 for connection reversal |
166 | * @param adv_port externally advertised port to use | 166 | * @param adv_port externally advertised port to use |
167 | * @param report function to call with the result of the test | 167 | * @param report function to call with the result of the test |
168 | * @param report_cls closure for report | 168 | * @param report_cls closure for report |
diff --git a/src/nat/nat.c b/src/nat/nat.c index e708cdabf..4e78c5d24 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c | |||
@@ -331,10 +331,11 @@ remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h, | |||
331 | GNUNET_CONTAINER_DLL_remove (h->lal_head, | 331 | GNUNET_CONTAINER_DLL_remove (h->lal_head, |
332 | h->lal_tail, | 332 | h->lal_tail, |
333 | pos); | 333 | pos); |
334 | h->address_callback (h->callback_cls, | 334 | if (NULL != h->address_callback) |
335 | GNUNET_NO, | 335 | h->address_callback (h->callback_cls, |
336 | (const struct sockaddr* ) &pos[1], | 336 | GNUNET_NO, |
337 | pos->addrlen); | 337 | (const struct sockaddr* ) &pos[1], |
338 | pos->addrlen); | ||
338 | GNUNET_free (pos); | 339 | GNUNET_free (pos); |
339 | } | 340 | } |
340 | } | 341 | } |
@@ -369,10 +370,11 @@ add_to_address_list_as_is (struct GNUNET_NAT_Handle *h, | |||
369 | "Adding address `%s' from source %d\n", | 370 | "Adding address `%s' from source %d\n", |
370 | GNUNET_a2s (arg, arg_size), | 371 | GNUNET_a2s (arg, arg_size), |
371 | src); | 372 | src); |
372 | h->address_callback (h->callback_cls, | 373 | if (NULL != h->address_callback) |
373 | GNUNET_YES, | 374 | h->address_callback (h->callback_cls, |
374 | arg, | 375 | GNUNET_YES, |
375 | arg_size); | 376 | arg, |
377 | arg_size); | ||
376 | } | 378 | } |
377 | 379 | ||
378 | 380 | ||
@@ -1273,10 +1275,11 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) | |||
1273 | GNUNET_CONTAINER_DLL_remove (h->lal_head, | 1275 | GNUNET_CONTAINER_DLL_remove (h->lal_head, |
1274 | h->lal_tail, | 1276 | h->lal_tail, |
1275 | lal); | 1277 | lal); |
1276 | h->address_callback (h->callback_cls, | 1278 | if (NULL != h->address_callback) |
1277 | GNUNET_NO, | 1279 | h->address_callback (h->callback_cls, |
1278 | (const struct sockaddr*) &lal[1], | 1280 | GNUNET_NO, |
1279 | lal->addrlen); | 1281 | (const struct sockaddr*) &lal[1], |
1282 | lal->addrlen); | ||
1280 | GNUNET_free (lal); | 1283 | GNUNET_free (lal); |
1281 | } | 1284 | } |
1282 | for (i=0;i<h->num_local_addrs;i++) | 1285 | for (i=0;i<h->num_local_addrs;i++) |
diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c index f31c5059d..a8bf227a0 100644 --- a/src/nat/nat_test.c +++ b/src/nat/nat_test.c | |||
@@ -28,25 +28,249 @@ | |||
28 | #include "gnunet_nat_lib.h" | 28 | #include "gnunet_nat_lib.h" |
29 | #include "nat.h" | 29 | #include "nat.h" |
30 | 30 | ||
31 | /** | ||
32 | * | ||
33 | */ | ||
34 | struct NatActivity | ||
35 | { | ||
36 | /** | ||
37 | * | ||
38 | */ | ||
39 | struct NatActivity *next; | ||
40 | |||
41 | /** | ||
42 | * | ||
43 | */ | ||
44 | struct NatActivity *prev; | ||
45 | |||
46 | /** | ||
47 | * | ||
48 | */ | ||
49 | struct GNUNET_NETWORK_Handle *sock; | ||
50 | |||
51 | /** | ||
52 | * | ||
53 | */ | ||
54 | struct GNUNET_NAT_Test *h; | ||
55 | |||
56 | /** | ||
57 | * | ||
58 | */ | ||
59 | GNUNET_SCHEDULER_TaskIdentifier rtask; | ||
60 | }; | ||
31 | 61 | ||
32 | /** | 62 | /** |
33 | * Handle to a NAT test. | 63 | * Handle to a NAT test. |
34 | */ | 64 | */ |
35 | struct GNUNET_NAT_Test | 65 | struct GNUNET_NAT_Test |
36 | { | 66 | { |
67 | |||
68 | /** | ||
69 | * | ||
70 | */ | ||
71 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
72 | |||
73 | /** | ||
74 | * | ||
75 | */ | ||
37 | GNUNET_NAT_TestCallback report; | 76 | GNUNET_NAT_TestCallback report; |
38 | 77 | ||
78 | /** | ||
79 | * | ||
80 | */ | ||
39 | void *report_cls; | 81 | void *report_cls; |
82 | |||
83 | /** | ||
84 | * | ||
85 | */ | ||
86 | struct GNUNET_NAT_Handle *nat; | ||
87 | |||
88 | /** | ||
89 | * | ||
90 | */ | ||
91 | struct GNUNET_NETWORK_Handle *lsock; | ||
92 | |||
93 | /** | ||
94 | * | ||
95 | */ | ||
96 | struct NatActivity *head; | ||
97 | |||
98 | /** | ||
99 | * | ||
100 | */ | ||
101 | struct NatActivity *tail; | ||
102 | |||
103 | /** | ||
104 | * | ||
105 | */ | ||
106 | GNUNET_SCHEDULER_TaskIdentifier ltask; | ||
107 | |||
108 | /** | ||
109 | * | ||
110 | */ | ||
111 | int is_tcp; | ||
112 | |||
113 | /** | ||
114 | * | ||
115 | */ | ||
116 | uint16_t data; | ||
117 | |||
118 | /** | ||
119 | * | ||
120 | */ | ||
121 | uint16_t adv_port; | ||
122 | |||
40 | }; | 123 | }; |
41 | 124 | ||
42 | 125 | ||
43 | /** | 126 | /** |
127 | * Function called from GNUNET_NAT_register | ||
128 | * whenever someone asks us to do connection | ||
129 | * reversal. | ||
130 | * | ||
131 | * @param cls closure, our 'struct GNUNET_NAT_Handle' | ||
132 | * @param addr public IP address of the other peer | ||
133 | * @param addrlen actual lenght of the address | ||
134 | */ | ||
135 | static void | ||
136 | reversal_cb (void *cls, | ||
137 | const struct sockaddr *addr, | ||
138 | socklen_t addrlen) | ||
139 | { | ||
140 | struct GNUNET_NAT_Test *h = cls; | ||
141 | const struct sockaddr_in *sa; | ||
142 | |||
143 | if (addrlen != sizeof (struct sockaddr_in)) | ||
144 | return; | ||
145 | sa = (const struct sockaddr_in *) addr; | ||
146 | if (h->data != sa->sin_port) | ||
147 | { | ||
148 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
149 | "Received connection reversal request for wrong port\n"); | ||
150 | return; /* wrong port */ | ||
151 | } | ||
152 | /* report success */ | ||
153 | h->report (h->report_cls, GNUNET_OK); | ||
154 | } | ||
155 | |||
156 | |||
157 | /** | ||
158 | * Activity on our incoming socket. Read data from the | ||
159 | * incoming connection. | ||
160 | * | ||
161 | * @param cls the 'struct NatActivity' | ||
162 | * @param tc scheduler context | ||
163 | */ | ||
164 | static void | ||
165 | do_read (void *cls, | ||
166 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
167 | { | ||
168 | struct NatActivity *na = cls; | ||
169 | struct GNUNET_NAT_Test *tst; | ||
170 | |||
171 | na->rtask = GNUNET_SCHEDULER_NO_TASK; | ||
172 | tst = na->h; | ||
173 | GNUNET_CONTAINER_DLL_remove (tst->head, | ||
174 | tst->tail, | ||
175 | na); | ||
176 | if (1) | ||
177 | { | ||
178 | // fimxe: read from socket... | ||
179 | } | ||
180 | GNUNET_NETWORK_socket_close (na->sock); | ||
181 | GNUNET_free (na); | ||
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Activity on our listen socket. Accept the | ||
187 | * incoming connection. | ||
188 | * | ||
189 | * @param cls the 'struct GNUNET_NAT_Test' | ||
190 | * @param tc scheduler context | ||
191 | */ | ||
192 | static void | ||
193 | do_accept (void *cls, | ||
194 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
195 | { | ||
196 | struct GNUNET_NAT_Test *tst = cls; | ||
197 | struct GNUNET_NETWORK_Handle *s; | ||
198 | struct NatActivity *wl; | ||
199 | |||
200 | tst->ltask = GNUNET_SCHEDULER_NO_TASK; | ||
201 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
202 | return; | ||
203 | tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
204 | tst->lsock, | ||
205 | &do_accept, | ||
206 | tst); | ||
207 | s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL); | ||
208 | if (NULL == s) | ||
209 | return; /* odd error */ | ||
210 | wl = GNUNET_malloc (sizeof (struct NatActivity)); | ||
211 | wl->sock = s; | ||
212 | wl->h = tst; | ||
213 | wl->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
214 | wl->sock, | ||
215 | &do_read, | ||
216 | wl); | ||
217 | GNUNET_CONTAINER_DLL_insert (tst->head, | ||
218 | tst->tail, | ||
219 | wl); | ||
220 | } | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Address-callback, used to send message to gnunet-nat-server. | ||
225 | * | ||
226 | * @param cls closure | ||
227 | * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean | ||
228 | * the previous (now invalid) one | ||
229 | * @param addr either the previous or the new public IP address | ||
230 | * @param addrlen actual lenght of the address | ||
231 | */ | ||
232 | static void | ||
233 | addr_cb (void *cls, | ||
234 | int add_remove, | ||
235 | const struct sockaddr *addr, | ||
236 | socklen_t addrlen) | ||
237 | { | ||
238 | struct GNUNET_NAT_Test *h = cls; | ||
239 | struct GNUNET_CLIENT_Connection *client; | ||
240 | struct GNUNET_NAT_TestMessage msg; | ||
241 | const struct sockaddr_in *sa; | ||
242 | |||
243 | if (GNUNET_YES != add_remove) | ||
244 | return; | ||
245 | if (addrlen != sizeof (struct sockaddr_in)) | ||
246 | return; /* ignore IPv6 here */ | ||
247 | sa = (const struct sockaddr_in*) addr; | ||
248 | msg.header.size = htons (sizeof(struct GNUNET_NAT_TestMessage)); | ||
249 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST); | ||
250 | msg.dst_ipv4 = sa->sin_addr.s_addr; | ||
251 | msg.dport = sa->sin_port; | ||
252 | msg.data = h->data; | ||
253 | msg.is_tcp = htonl ((uint32_t) h->is_tcp); | ||
254 | |||
255 | client = GNUNET_CLIENT_connect ("gnunet-nat-server", | ||
256 | h->cfg); | ||
257 | GNUNET_break (GNUNET_OK == | ||
258 | GNUNET_CLIENT_transmit_and_get_response (client, | ||
259 | &msg.header, | ||
260 | GNUNET_TIME_UNIT_SECONDS, | ||
261 | GNUNET_YES, | ||
262 | NULL, NULL)); | ||
263 | GNUNET_CLIENT_disconnect (client, GNUNET_YES); | ||
264 | } | ||
265 | |||
266 | |||
267 | /** | ||
44 | * Start testing if NAT traversal works using the | 268 | * Start testing if NAT traversal works using the |
45 | * given configuration (IPv4-only). | 269 | * given configuration (IPv4-only). |
46 | * | 270 | * |
47 | * @param cfg configuration for the NAT traversal | 271 | * @param cfg configuration for the NAT traversal |
48 | * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP | 272 | * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP |
49 | * @param bnd_port port to bind to | 273 | * @param bnd_port port to bind to, 0 for connection reversal |
50 | * @param adv_port externally advertised port to use | 274 | * @param adv_port externally advertised port to use |
51 | * @param report function to call with the result of the test | 275 | * @param report function to call with the result of the test |
52 | * @param report_cls closure for report | 276 | * @param report_cls closure for report |
@@ -60,7 +284,59 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
60 | GNUNET_NAT_TestCallback report, | 284 | GNUNET_NAT_TestCallback report, |
61 | void *report_cls) | 285 | void *report_cls) |
62 | { | 286 | { |
63 | return NULL; | 287 | struct GNUNET_NAT_Test *ret; |
288 | struct sockaddr_in sa; | ||
289 | const struct sockaddr *addrs[] = { (const struct sockaddr*) &sa }; | ||
290 | const socklen_t addrlens[] = { sizeof (sa) }; | ||
291 | |||
292 | memset (&sa, 0, sizeof (sa)); | ||
293 | sa.sin_port = htons (bnd_port); | ||
294 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
295 | sa.sin_len = sizeof (sa); | ||
296 | #endif | ||
297 | |||
298 | ret = GNUNET_malloc (sizeof (struct GNUNET_NAT_Test)); | ||
299 | ret->cfg = cfg; | ||
300 | ret->is_tcp = is_tcp; | ||
301 | ret->data = bnd_port; | ||
302 | ret->adv_port = adv_port; | ||
303 | ret->report = report; | ||
304 | ret->report_cls = report_cls; | ||
305 | if (bnd_port == 0) | ||
306 | { | ||
307 | ret->nat = GNUNET_NAT_register (cfg, is_tcp, | ||
308 | 0, | ||
309 | 0, NULL, NULL, | ||
310 | &addr_cb, &reversal_cb, ret); | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | ret->lsock = GNUNET_NETWORK_socket_create (AF_INET, | ||
315 | (is_tcp==GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, 0); | ||
316 | if ( (ret->lsock == NULL) || | ||
317 | (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret->lsock, | ||
318 | (const struct sockaddr*) &sa, | ||
319 | sizeof (sa))) ) | ||
320 | { | ||
321 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
322 | _("Failed to create listen socket for NAT test\n")); | ||
323 | if (NULL != ret->lsock) | ||
324 | GNUNET_NETWORK_socket_close (ret->lsock); | ||
325 | GNUNET_free (ret); | ||
326 | return NULL; | ||
327 | } | ||
328 | GNUNET_break (GNUNET_OK == | ||
329 | GNUNET_NETWORK_socket_listen (ret->lsock, 5)); | ||
330 | ret->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
331 | ret->lsock, | ||
332 | &do_accept, | ||
333 | ret); | ||
334 | ret->nat = GNUNET_NAT_register (cfg, is_tcp, | ||
335 | adv_port, | ||
336 | 1, addrs, addrlens, | ||
337 | &addr_cb, NULL, ret); | ||
338 | } | ||
339 | return ret; | ||
64 | } | 340 | } |
65 | 341 | ||
66 | 342 | ||
@@ -72,6 +348,22 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
72 | void | 348 | void |
73 | GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) | 349 | GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) |
74 | { | 350 | { |
351 | struct NatActivity *pos; | ||
352 | |||
353 | while (NULL != (pos = tst->head)) | ||
354 | { | ||
355 | GNUNET_CONTAINER_DLL_remove (tst->head, | ||
356 | tst->tail, | ||
357 | pos); | ||
358 | GNUNET_SCHEDULER_cancel (pos->rtask); | ||
359 | GNUNET_NETWORK_socket_close (pos->sock); | ||
360 | GNUNET_free (pos); | ||
361 | } | ||
362 | if (GNUNET_SCHEDULER_NO_TASK != tst->ltask) | ||
363 | GNUNET_SCHEDULER_cancel (tst->ltask); | ||
364 | if (NULL != tst->lsock) | ||
365 | GNUNET_NETWORK_socket_close (tst->lsock); | ||
366 | GNUNET_NAT_unregister (tst->nat); | ||
75 | GNUNET_free (tst); | 367 | GNUNET_free (tst); |
76 | } | 368 | } |
77 | 369 | ||