diff options
Diffstat (limited to 'src/testbed/gnunet-service-testbed_oc.c')
-rw-r--r-- | src/testbed/gnunet-service-testbed_oc.c | 1978 |
1 files changed, 0 insertions, 1978 deletions
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c deleted file mode 100644 index 4fe7c20b3..000000000 --- a/src/testbed/gnunet-service-testbed_oc.c +++ /dev/null | |||
@@ -1,1978 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2008--2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testbed/gnunet-service-testbed_oc.c | ||
23 | * @brief code for handling overlay connect operations | ||
24 | * @author Sree Harsha Totakura | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-testbed.h" | ||
28 | #include "gnunet-service-testbed_connectionpool.h" | ||
29 | #include "gnunet_transport_hello_service.h" | ||
30 | |||
31 | /** | ||
32 | * Redefine LOG with a changed log component string | ||
33 | */ | ||
34 | #ifdef LOG | ||
35 | #undef LOG | ||
36 | #endif | ||
37 | #define LOG(kind, ...) \ | ||
38 | GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__) | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Context information for requesting ATS to connect to a peer | ||
43 | */ | ||
44 | struct ConnectivitySuggestContext | ||
45 | { | ||
46 | /** | ||
47 | * The transport handle obtained from cache. Do NOT close/disconnect. | ||
48 | */ | ||
49 | struct GNUNET_TRANSPORT_CoreHandle *th_; | ||
50 | |||
51 | /** | ||
52 | * Configuration of the peer from cache. Do not free! | ||
53 | */ | ||
54 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
55 | |||
56 | /** | ||
57 | * The GetCacheHandle for the peer2's transport handle | ||
58 | * (used to offer the HELLO to the peer). | ||
59 | */ | ||
60 | struct GST_ConnectionPool_GetHandle *cgh_p2_th; | ||
61 | |||
62 | /** | ||
63 | * The GetCacheHandle for the peer2's ATS handle. | ||
64 | */ | ||
65 | struct GST_ConnectionPool_GetHandle *cgh_p2_ats; | ||
66 | |||
67 | /** | ||
68 | * The ATS handle for the connectivity suggestion. | ||
69 | */ | ||
70 | struct GNUNET_ATS_ConnectivitySuggestHandle *csh; | ||
71 | }; | ||
72 | |||
73 | |||
74 | /** | ||
75 | * Types for context information we create for overlay connect requests | ||
76 | */ | ||
77 | enum OverlayConnectContextType | ||
78 | { | ||
79 | /** | ||
80 | * This type is used if the overlay connection is local i.e. the connection | ||
81 | * has to be made between local peers | ||
82 | */ | ||
83 | OCC_TYPE_LOCAL, | ||
84 | |||
85 | /** | ||
86 | * Type to be used when the first peer is local and the other peer is on a slave | ||
87 | * controller started by us | ||
88 | */ | ||
89 | OCC_TYPE_REMOTE_SLAVE, | ||
90 | |||
91 | /** | ||
92 | * Type to be used when the first peer is local and the other peer is on a | ||
93 | * controller which is not started by us. | ||
94 | */ | ||
95 | OCC_TYPE_REMOTE_LATERAL | ||
96 | }; | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Context data for operations on second peer in local overlay connection | ||
101 | * contexts | ||
102 | */ | ||
103 | struct LocalPeer2Context | ||
104 | { | ||
105 | /** | ||
106 | * The handle for offering the HELLO of the first peer to the second | ||
107 | * peer. | ||
108 | */ | ||
109 | struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; | ||
110 | |||
111 | /** | ||
112 | * The transport ConnectivitySuggestContext | ||
113 | */ | ||
114 | struct ConnectivitySuggestContext tcc; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Context data for operations on second peer in remote overlay connection | ||
120 | * contexts | ||
121 | */ | ||
122 | struct RemotePeer2Context | ||
123 | { | ||
124 | /** | ||
125 | * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay | ||
126 | * connection then this can be NULL until the connection to the controller is | ||
127 | * established | ||
128 | */ | ||
129 | struct GNUNET_TESTBED_Controller *p2c; | ||
130 | |||
131 | /** | ||
132 | * Operation context for the suboperation we start to get the identity of the | ||
133 | * second peer | ||
134 | */ | ||
135 | struct OperationContext *opc; | ||
136 | |||
137 | /** | ||
138 | * Notification handle acquire to connect to a remote controller. Only used | ||
139 | * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL. | ||
140 | */ | ||
141 | struct NeighbourConnectNotification *ncn; | ||
142 | |||
143 | /** | ||
144 | * The neighbour handle. Only used if the type of overlay connection is | ||
145 | * #OCC_TYPE_REMOTE_LATERAL. | ||
146 | */ | ||
147 | struct Neighbour *p2n; | ||
148 | }; | ||
149 | |||
150 | /** | ||
151 | * Context information for connecting 2 peers in overlay. | ||
152 | */ | ||
153 | struct OverlayConnectContext | ||
154 | { | ||
155 | /** | ||
156 | * The next pointer for maintaining a DLL of all OverlayConnectContexts | ||
157 | */ | ||
158 | struct OverlayConnectContext *next; | ||
159 | |||
160 | /** | ||
161 | * The prev pointer for maintaining a DLL of all OverlayConnectContexts | ||
162 | */ | ||
163 | struct OverlayConnectContext *prev; | ||
164 | |||
165 | /** | ||
166 | * The client which has requested for overlay connection. This is used to send | ||
167 | * either a success of failure message | ||
168 | */ | ||
169 | struct GNUNET_SERVICE_Client *client; | ||
170 | |||
171 | /** | ||
172 | * the first peer which is to expect an overlay connection from the second peer. | ||
173 | */ | ||
174 | struct Peer *peer; | ||
175 | |||
176 | /** | ||
177 | * Transport handle of the first peer obtained from cache to get its HELLO. Do | ||
178 | * NOT close/disconnect. | ||
179 | */ | ||
180 | struct GNUNET_TRANSPORT_CoreHandle *p1th_; | ||
181 | |||
182 | /** | ||
183 | * The #GST_ConnectionPool_GetHandle for the peer1's transport handle | ||
184 | */ | ||
185 | struct GST_ConnectionPool_GetHandle *cgh_p1th; | ||
186 | |||
187 | /** | ||
188 | * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE | ||
189 | * level peer connects and to get our identity. | ||
190 | */ | ||
191 | struct GST_ConnectionPool_GetHandle *cgh_ch; | ||
192 | |||
193 | /** | ||
194 | * HELLO of the first peer. This should be sent to the second peer. | ||
195 | */ | ||
196 | struct GNUNET_MessageHeader *hello; | ||
197 | |||
198 | /** | ||
199 | * Get GetHelloHandle to acquire a HELLO of the first peer | ||
200 | */ | ||
201 | struct GNUNET_TRANSPORT_HelloGetHandle *ghh; | ||
202 | |||
203 | /** | ||
204 | * The error message we send if this overlay connect operation has timed out | ||
205 | */ | ||
206 | char *emsg; | ||
207 | |||
208 | /** | ||
209 | * Context information for operations on the second peer | ||
210 | */ | ||
211 | union | ||
212 | { | ||
213 | /** | ||
214 | * Context information to be used if the second peer is local | ||
215 | */ | ||
216 | struct LocalPeer2Context local; | ||
217 | |||
218 | /** | ||
219 | * Context information to be used if the second peer is remote | ||
220 | */ | ||
221 | struct RemotePeer2Context remote; | ||
222 | } p2ctx; | ||
223 | |||
224 | /** | ||
225 | * The peer identity of the first peer | ||
226 | */ | ||
227 | struct GNUNET_PeerIdentity peer_identity; | ||
228 | |||
229 | /** | ||
230 | * The peer identity of the other peer | ||
231 | */ | ||
232 | struct GNUNET_PeerIdentity other_peer_identity; | ||
233 | |||
234 | /** | ||
235 | * The id of the operation responsible for creating this context | ||
236 | */ | ||
237 | uint64_t op_id; | ||
238 | |||
239 | /** | ||
240 | * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to | ||
241 | * connect to peer 2 | ||
242 | */ | ||
243 | struct GNUNET_SCHEDULER_Task *send_hello_task; | ||
244 | |||
245 | /** | ||
246 | * The id of the overlay connect timeout task | ||
247 | */ | ||
248 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
249 | |||
250 | /** | ||
251 | * The id of the cleanup task | ||
252 | */ | ||
253 | struct GNUNET_SCHEDULER_Task *cleanup_task; | ||
254 | |||
255 | /** | ||
256 | * The type of this context information | ||
257 | */ | ||
258 | enum OverlayConnectContextType type; | ||
259 | |||
260 | /** | ||
261 | * The id of the second peer which has to connect to the first peer | ||
262 | */ | ||
263 | uint32_t other_peer_id; | ||
264 | }; | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Context information for remote overlay connect operations. Remote overlay | ||
269 | * connections are used when peers A and B reside on different hosts. In these | ||
270 | * operations the host controller for peer B is asked by the host controller of | ||
271 | * peer A to make peer B connect to peer A by sending the controller of peer B | ||
272 | * the HELLO of peer A. | ||
273 | */ | ||
274 | struct RemoteOverlayConnectCtx | ||
275 | { | ||
276 | /** | ||
277 | * the next pointer for DLL | ||
278 | */ | ||
279 | struct RemoteOverlayConnectCtx *next; | ||
280 | |||
281 | /** | ||
282 | * the prev pointer for DLL | ||
283 | */ | ||
284 | struct RemoteOverlayConnectCtx *prev; | ||
285 | |||
286 | /** | ||
287 | * The peer handle of peer B | ||
288 | */ | ||
289 | struct Peer *peer; | ||
290 | |||
291 | /** | ||
292 | * Peer A's HELLO | ||
293 | */ | ||
294 | struct GNUNET_MessageHeader *hello; | ||
295 | |||
296 | /** | ||
297 | * The handle for offering HELLO | ||
298 | */ | ||
299 | struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; | ||
300 | |||
301 | /** | ||
302 | * The transport try connect context | ||
303 | */ | ||
304 | struct ConnectivitySuggestContext tcc; | ||
305 | |||
306 | /** | ||
307 | * The peer identity of peer A | ||
308 | */ | ||
309 | struct GNUNET_PeerIdentity a_id; | ||
310 | |||
311 | /** | ||
312 | * Task for offering HELLO of A to B and doing try_connect | ||
313 | */ | ||
314 | struct GNUNET_SCHEDULER_Task *attempt_connect_task_id; | ||
315 | |||
316 | /** | ||
317 | * Task to timeout RequestOverlayConnect | ||
318 | */ | ||
319 | struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id; | ||
320 | |||
321 | /** | ||
322 | * The id of the operation responsible for creating this context | ||
323 | */ | ||
324 | uint64_t op_id; | ||
325 | }; | ||
326 | |||
327 | |||
328 | /** | ||
329 | * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown | ||
330 | */ | ||
331 | static struct OverlayConnectContext *occq_head; | ||
332 | |||
333 | /** | ||
334 | * DLL tail for OverlayConnectContext DLL | ||
335 | */ | ||
336 | static struct OverlayConnectContext *occq_tail; | ||
337 | |||
338 | /** | ||
339 | * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during | ||
340 | * shutdown | ||
341 | */ | ||
342 | static struct RemoteOverlayConnectCtx *roccq_head; | ||
343 | |||
344 | /** | ||
345 | * DLL tail for RequectOverlayConnectContext DLL | ||
346 | */ | ||
347 | static struct RemoteOverlayConnectCtx *roccq_tail; | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Cleans up ForwardedOverlayConnectContext | ||
352 | * | ||
353 | * @param focc the ForwardedOverlayConnectContext to cleanup | ||
354 | */ | ||
355 | void | ||
356 | GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc) | ||
357 | { | ||
358 | struct RegisteredHostContext *rhc = focc->rhc; | ||
359 | |||
360 | GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, | ||
361 | rhc->focc_dll_tail, | ||
362 | focc); | ||
363 | GNUNET_free (focc->orig_msg); | ||
364 | GNUNET_free (focc); | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Timeout task for cancelling a forwarded overlay connect connect | ||
370 | * | ||
371 | * @param cls the `struct ForwardedOperationContext` | ||
372 | */ | ||
373 | static void | ||
374 | forwarded_overlay_connect_timeout (void *cls) | ||
375 | { | ||
376 | struct ForwardedOperationContext *fopc = cls; | ||
377 | struct RegisteredHostContext *rhc; | ||
378 | struct ForwardedOverlayConnectContext *focc; | ||
379 | |||
380 | fopc->timeout_task = NULL; | ||
381 | rhc = fopc->cls; | ||
382 | focc = rhc->focc_dll_head; | ||
383 | LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", | ||
384 | focc->peer1, | ||
385 | focc->peer2); | ||
386 | GST_cleanup_focc (focc); | ||
387 | GST_forwarded_operation_timeout (fopc); | ||
388 | if (NULL != rhc->focc_dll_head) | ||
389 | GST_process_next_focc (rhc); | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Callback to be called when forwarded overlay connection operation has a reply | ||
395 | * from the sub-controller successful. We have to relay the reply msg back to | ||
396 | * the client | ||
397 | * | ||
398 | * @param cls ForwardedOperationContext | ||
399 | * @param msg the peer create success message | ||
400 | */ | ||
401 | static void | ||
402 | forwarded_overlay_connect_listener (void *cls, | ||
403 | const struct GNUNET_MessageHeader *msg) | ||
404 | { | ||
405 | struct ForwardedOperationContext *fopc = cls; | ||
406 | struct RegisteredHostContext *rhc; | ||
407 | struct ForwardedOverlayConnectContext *focc; | ||
408 | |||
409 | rhc = fopc->cls; | ||
410 | GST_forwarded_operation_reply_relay (cls, msg); | ||
411 | focc = rhc->focc_dll_head; | ||
412 | GST_cleanup_focc (focc); | ||
413 | if (NULL != rhc->focc_dll_head) | ||
414 | GST_process_next_focc (rhc); | ||
415 | } | ||
416 | |||
417 | |||
418 | /** | ||
419 | * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext | ||
420 | * | ||
421 | * @param rhc the RegisteredHostContext | ||
422 | */ | ||
423 | void | ||
424 | GST_process_next_focc (struct RegisteredHostContext *rhc) | ||
425 | { | ||
426 | struct ForwardedOperationContext *fopc; | ||
427 | struct ForwardedOverlayConnectContext *focc; | ||
428 | struct Peer *peer; | ||
429 | struct Slave *slave; | ||
430 | |||
431 | focc = rhc->focc_dll_head; | ||
432 | GNUNET_assert (NULL != focc); | ||
433 | GNUNET_assert (RHC_DONE == rhc->state); | ||
434 | GNUNET_assert (VALID_PEER_ID (focc->peer1)); | ||
435 | peer = GST_peer_list[focc->peer1]; | ||
436 | GNUNET_assert (GNUNET_YES == peer->is_remote); | ||
437 | GNUNET_assert (NULL != (slave = peer->details.remote.slave)); | ||
438 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
439 | fopc->client = focc->client; | ||
440 | fopc->operation_id = focc->operation_id; | ||
441 | fopc->cls = rhc; | ||
442 | fopc->type = OP_OVERLAY_CONNECT; | ||
443 | fopc->opc = | ||
444 | GNUNET_TESTBED_forward_operation_msg_ (slave->controller, | ||
445 | focc->operation_id, | ||
446 | focc->orig_msg, | ||
447 | &forwarded_overlay_connect_listener, | ||
448 | fopc); | ||
449 | GNUNET_free (focc->orig_msg); | ||
450 | focc->orig_msg = NULL; | ||
451 | fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
452 | & | ||
453 | forwarded_overlay_connect_timeout, | ||
454 | fopc); | ||
455 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
456 | fopcq_tail, | ||
457 | fopc); | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Cleans up any used handles in local peer2 context | ||
463 | * | ||
464 | * @param lp2c the local peer2 context information | ||
465 | */ | ||
466 | static void | ||
467 | cleanup_occ_lp2c (struct LocalPeer2Context *lp2c) | ||
468 | { | ||
469 | if (NULL != lp2c->ohh) | ||
470 | { | ||
471 | GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh); | ||
472 | lp2c->ohh = NULL; | ||
473 | } | ||
474 | if (NULL != lp2c->tcc.cgh_p2_th) | ||
475 | { | ||
476 | GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th); | ||
477 | lp2c->tcc.cgh_p2_th = NULL; | ||
478 | } | ||
479 | if (NULL != lp2c->tcc.cgh_p2_ats) | ||
480 | { | ||
481 | GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats); | ||
482 | lp2c->tcc.cgh_p2_ats = NULL; | ||
483 | } | ||
484 | if (NULL != lp2c->tcc.csh) | ||
485 | { | ||
486 | GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh); | ||
487 | lp2c->tcc.csh = NULL; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | |||
492 | /** | ||
493 | * Cleans up any used handles in remote peer2 context. Relinquishes the | ||
494 | * remote controller connection if it has been established on-demand. | ||
495 | * | ||
496 | * @param rp2c the remote peer2 context information | ||
497 | */ | ||
498 | static void | ||
499 | cleanup_occ_rp2c (struct RemotePeer2Context *rp2c) | ||
500 | { | ||
501 | if (NULL != rp2c->opc) | ||
502 | { | ||
503 | GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc); | ||
504 | rp2c->opc = NULL; | ||
505 | } | ||
506 | if (NULL != rp2c->ncn) | ||
507 | { | ||
508 | GST_neighbour_get_connection_cancel (rp2c->ncn); | ||
509 | rp2c->ncn = NULL; | ||
510 | } | ||
511 | if ((NULL != rp2c->p2c) && (NULL != rp2c->p2n)) | ||
512 | { | ||
513 | GST_neighbour_release_connection (rp2c->p2n); | ||
514 | rp2c->p2n = NULL; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * Condition for checking if given peer is ready to be destroyed | ||
521 | * | ||
522 | * @param peer the peer to check | ||
523 | */ | ||
524 | #define PEER_EXPIRED(peer) \ | ||
525 | ((GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt)) | ||
526 | |||
527 | /** | ||
528 | * Cleanup overlay connect context structure | ||
529 | * | ||
530 | * @param occ the overlay connect context | ||
531 | */ | ||
532 | static void | ||
533 | cleanup_occ (struct OverlayConnectContext *occ) | ||
534 | { | ||
535 | struct Peer *peer2; | ||
536 | |||
537 | LOG_DEBUG ("0x%llx: Cleaning up occ\n", | ||
538 | (unsigned long long) occ->op_id); | ||
539 | GNUNET_free (occ->emsg); | ||
540 | GNUNET_free (occ->hello); | ||
541 | if (NULL != occ->send_hello_task) | ||
542 | GNUNET_SCHEDULER_cancel (occ->send_hello_task); | ||
543 | if (NULL != occ->cleanup_task) | ||
544 | GNUNET_SCHEDULER_cancel (occ->cleanup_task); | ||
545 | if (NULL != occ->timeout_task) | ||
546 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
547 | if (NULL != occ->cgh_ch) | ||
548 | GST_connection_pool_get_handle_done (occ->cgh_ch); | ||
549 | if (NULL != occ->ghh) | ||
550 | GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); | ||
551 | GST_connection_pool_get_handle_done (occ->cgh_p1th); | ||
552 | GNUNET_assert (NULL != GST_peer_list); | ||
553 | GNUNET_assert (occ->peer->reference_cnt > 0); | ||
554 | occ->peer->reference_cnt--; | ||
555 | if (PEER_EXPIRED (occ->peer)) | ||
556 | GST_destroy_peer (occ->peer); | ||
557 | switch (occ->type) | ||
558 | { | ||
559 | case OCC_TYPE_LOCAL: | ||
560 | peer2 = GST_peer_list[occ->other_peer_id]; | ||
561 | GNUNET_assert (peer2->reference_cnt > 0); | ||
562 | peer2->reference_cnt--; | ||
563 | if (PEER_EXPIRED (peer2)) | ||
564 | GST_destroy_peer (peer2); | ||
565 | cleanup_occ_lp2c (&occ->p2ctx.local); | ||
566 | break; | ||
567 | |||
568 | case OCC_TYPE_REMOTE_SLAVE: | ||
569 | case OCC_TYPE_REMOTE_LATERAL: | ||
570 | cleanup_occ_rp2c (&occ->p2ctx.remote); | ||
571 | break; | ||
572 | } | ||
573 | GNUNET_CONTAINER_DLL_remove (occq_head, | ||
574 | occq_tail, | ||
575 | occ); | ||
576 | GNUNET_free (occ); | ||
577 | } | ||
578 | |||
579 | |||
580 | /** | ||
581 | * Task for cleaning up overlay connect context structure | ||
582 | * | ||
583 | * @param cls the overlay connect context | ||
584 | */ | ||
585 | static void | ||
586 | do_cleanup_occ (void *cls) | ||
587 | { | ||
588 | struct OverlayConnectContext *occ = cls; | ||
589 | |||
590 | occ->cleanup_task = NULL; | ||
591 | cleanup_occ (occ); | ||
592 | } | ||
593 | |||
594 | |||
595 | /** | ||
596 | * Task which will be run when overlay connect request has been timed out | ||
597 | * | ||
598 | * @param cls the OverlayConnectContext | ||
599 | */ | ||
600 | static void | ||
601 | timeout_overlay_connect (void *cls) | ||
602 | { | ||
603 | struct OverlayConnectContext *occ = cls; | ||
604 | |||
605 | GNUNET_assert (NULL != occ->timeout_task); | ||
606 | occ->timeout_task = NULL; | ||
607 | /* LOG (GNUNET_ERROR_TYPE_WARNING, */ | ||
608 | /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */ | ||
609 | /* occ->peer->id, occ->other_peer_id, occ->emsg); */ | ||
610 | GST_send_operation_fail_msg (occ->client, | ||
611 | occ->op_id, | ||
612 | occ->emsg); | ||
613 | cleanup_occ (occ); | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Notify OC subsystem that @a client disconnected. | ||
619 | * | ||
620 | * @param client the client that disconnected | ||
621 | */ | ||
622 | void | ||
623 | GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client) | ||
624 | { | ||
625 | struct ForwardedOperationContext *fopc; | ||
626 | struct ForwardedOperationContext *fopcn; | ||
627 | struct OverlayConnectContext *occ; | ||
628 | struct OverlayConnectContext *occn; | ||
629 | |||
630 | for (fopc = fopcq_head; NULL != fopc; fopc = fopcn) | ||
631 | { | ||
632 | fopcn = fopc->next; | ||
633 | if (fopc->client == client) | ||
634 | { | ||
635 | GNUNET_SCHEDULER_cancel (fopc->timeout_task); | ||
636 | GST_forwarded_operation_timeout (fopc); | ||
637 | } | ||
638 | } | ||
639 | for (occ = occq_head; NULL != occ; occ = occn) | ||
640 | { | ||
641 | occn = occ->next; | ||
642 | if (occ->client == client) | ||
643 | cleanup_occ (occ); | ||
644 | } | ||
645 | // FIXME: implement clean up for client_keep replacements! | ||
646 | } | ||
647 | |||
648 | |||
649 | /** | ||
650 | * FIXME. | ||
651 | */ | ||
652 | static void | ||
653 | send_overlay_connect_success_msg (struct OverlayConnectContext *occ) | ||
654 | { | ||
655 | struct GNUNET_MQ_Envelope *env; | ||
656 | struct GNUNET_TESTBED_ConnectionEventMessage *msg; | ||
657 | |||
658 | LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n", | ||
659 | (unsigned long long) occ->op_id); | ||
660 | env = GNUNET_MQ_msg (msg, | ||
661 | GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); | ||
662 | msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT); | ||
663 | msg->peer1 = htonl (occ->peer->id); | ||
664 | msg->peer2 = htonl (occ->other_peer_id); | ||
665 | msg->operation_id = GNUNET_htonll (occ->op_id); | ||
666 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client), | ||
667 | env); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * Function called to notify transport users that another | ||
673 | * peer connected to us. | ||
674 | * | ||
675 | * @param cls closure | ||
676 | * @param new_peer the peer that connected | ||
677 | */ | ||
678 | static void | ||
679 | overlay_connect_notify (void *cls, | ||
680 | const struct GNUNET_PeerIdentity *new_peer) | ||
681 | { | ||
682 | struct OverlayConnectContext *occ = cls; | ||
683 | char *new_peer_str; | ||
684 | char *other_peer_str; | ||
685 | |||
686 | LOG_DEBUG ("Overlay connect notify\n"); | ||
687 | if (0 == | ||
688 | memcmp (new_peer, &occ->peer_identity, | ||
689 | sizeof(struct GNUNET_PeerIdentity))) | ||
690 | return; | ||
691 | new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer)); | ||
692 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
693 | if (0 != | ||
694 | memcmp (new_peer, | ||
695 | &occ->other_peer_identity, | ||
696 | sizeof(struct GNUNET_PeerIdentity))) | ||
697 | { | ||
698 | LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n", | ||
699 | new_peer_str, | ||
700 | other_peer_str); | ||
701 | GNUNET_free (new_peer_str); | ||
702 | GNUNET_free (other_peer_str); | ||
703 | return; | ||
704 | } | ||
705 | GNUNET_free (new_peer_str); | ||
706 | LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n", | ||
707 | (unsigned long long) occ->op_id, | ||
708 | other_peer_str, | ||
709 | GNUNET_i2s (&occ->peer_identity)); | ||
710 | GNUNET_free (other_peer_str); | ||
711 | if (NULL != occ->send_hello_task) | ||
712 | { | ||
713 | GNUNET_SCHEDULER_cancel (occ->send_hello_task); | ||
714 | occ->send_hello_task = NULL; | ||
715 | } | ||
716 | GNUNET_assert (NULL != occ->timeout_task); | ||
717 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
718 | occ->timeout_task = NULL; | ||
719 | switch (occ->type) | ||
720 | { | ||
721 | case OCC_TYPE_LOCAL: | ||
722 | cleanup_occ_lp2c (&occ->p2ctx.local); | ||
723 | break; | ||
724 | |||
725 | case OCC_TYPE_REMOTE_SLAVE: | ||
726 | case OCC_TYPE_REMOTE_LATERAL: | ||
727 | cleanup_occ_rp2c (&occ->p2ctx.remote); | ||
728 | break; | ||
729 | } | ||
730 | GNUNET_free (occ->emsg); | ||
731 | occ->emsg = NULL; | ||
732 | send_overlay_connect_success_msg (occ); | ||
733 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, | ||
734 | occ); | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * Callback from cache with needed ATS handle set | ||
740 | * | ||
741 | * @param cls a `struct OverlayConnectCtx *` | ||
742 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
743 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
744 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
745 | * @param my_identity the identity of our peer | ||
746 | * @param cfg configuration of the peer | ||
747 | */ | ||
748 | static void | ||
749 | occ_cache_get_handle_ats_occ_cb (void *cls, | ||
750 | struct GNUNET_CORE_Handle *ch, | ||
751 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
752 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
753 | const struct GNUNET_PeerIdentity *my_identity, | ||
754 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
755 | { | ||
756 | struct OverlayConnectContext *occ = cls; | ||
757 | struct LocalPeer2Context *lp2c; | ||
758 | |||
759 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
760 | GNUNET_assert (NULL != occ->timeout_task); | ||
761 | GNUNET_free (occ->emsg); | ||
762 | if (NULL == ac) | ||
763 | { | ||
764 | GNUNET_asprintf (&occ->emsg, | ||
765 | "0x%llx: Failed to connect to ATS of peer with id: %u", | ||
766 | (unsigned long long) occ->op_id, | ||
767 | occ->peer->id); | ||
768 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
769 | occ->timeout_task = | ||
770 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, | ||
771 | occ); | ||
772 | return; | ||
773 | } | ||
774 | occ->emsg = NULL; | ||
775 | |||
776 | GNUNET_asprintf (&occ->emsg, | ||
777 | "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s", | ||
778 | (unsigned long long) occ->op_id, | ||
779 | GNUNET_i2s (&occ->other_peer_identity)); | ||
780 | |||
781 | lp2c = &occ->p2ctx.local; | ||
782 | lp2c->tcc.csh = | ||
783 | GNUNET_ATS_connectivity_suggest (ac, | ||
784 | &occ->peer_identity, | ||
785 | 1); | ||
786 | } | ||
787 | |||
788 | |||
789 | /** | ||
790 | * Callback from cache with needed ATS handle set | ||
791 | * | ||
792 | * @param cls a `struct RemoteOverlayConnectCtx *` | ||
793 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
794 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
795 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
796 | * @param my_identity the identity of our peer | ||
797 | */ | ||
798 | static void | ||
799 | occ_cache_get_handle_ats_rocc_cb (void *cls, | ||
800 | struct GNUNET_CORE_Handle *ch, | ||
801 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
802 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
803 | const struct GNUNET_PeerIdentity *my_identity, | ||
804 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
805 | { | ||
806 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
807 | |||
808 | rocc->tcc.csh = | ||
809 | GNUNET_ATS_connectivity_suggest (ac, | ||
810 | &rocc->a_id, | ||
811 | 1); | ||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
816 | * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to | ||
817 | * peer 1. | ||
818 | * | ||
819 | * @param cls the OverlayConnectContext | ||
820 | */ | ||
821 | static void | ||
822 | send_hello (void *cls); | ||
823 | |||
824 | |||
825 | /** | ||
826 | * Task that is run when hello has been sent If tc->reason = | ||
827 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
828 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
829 | * | ||
830 | * @param cls the overlay connect context | ||
831 | */ | ||
832 | static void | ||
833 | occ_hello_sent_cb (void *cls) | ||
834 | { | ||
835 | struct OverlayConnectContext *occ = cls; | ||
836 | struct LocalPeer2Context *lp2c; | ||
837 | struct Peer *peer2; | ||
838 | |||
839 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
840 | GNUNET_assert (NULL != occ->timeout_task); | ||
841 | lp2c = &occ->p2ctx.local; | ||
842 | lp2c->ohh = NULL; | ||
843 | |||
844 | GNUNET_assert (NULL == occ->send_hello_task); | ||
845 | GNUNET_free (occ->emsg); | ||
846 | |||
847 | GNUNET_asprintf (&occ->emsg, | ||
848 | "0x%llx: Timeout while acquiring ATS of %s from cache", | ||
849 | (unsigned long long) occ->op_id, | ||
850 | GNUNET_i2s (&occ->other_peer_identity)); | ||
851 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
852 | lp2c->tcc.cgh_p2_ats = | ||
853 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
854 | peer2->details.local.cfg, | ||
855 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
856 | &occ_cache_get_handle_ats_occ_cb, | ||
857 | occ, NULL, NULL, NULL); | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
862 | * Sends the HELLO of peer1 to peer2's controller through remote overlay connect | ||
863 | * request. | ||
864 | * | ||
865 | * @param occ the overlay connect context. Its type must be either | ||
866 | * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL | ||
867 | */ | ||
868 | static void | ||
869 | send_hello_thru_rocc (struct OverlayConnectContext *occ) | ||
870 | { | ||
871 | struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; | ||
872 | char *other_peer_str; | ||
873 | uint16_t msize; | ||
874 | uint16_t hello_size; | ||
875 | |||
876 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
877 | GNUNET_assert (NULL != occ->hello); | ||
878 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
879 | LOG_DEBUG ( | ||
880 | "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n", | ||
881 | (unsigned long long) occ->op_id, | ||
882 | GNUNET_i2s (&occ->peer_identity), | ||
883 | ntohs (occ->hello->size), | ||
884 | other_peer_str); | ||
885 | GNUNET_free (other_peer_str); | ||
886 | hello_size = ntohs (occ->hello->size); | ||
887 | msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) | ||
888 | + hello_size; | ||
889 | msg = GNUNET_malloc (msize); | ||
890 | msg->header.type = | ||
891 | htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT); | ||
892 | msg->header.size = htons (msize); | ||
893 | msg->peer = htonl (occ->other_peer_id); | ||
894 | msg->operation_id = GNUNET_htonll (occ->op_id); | ||
895 | msg->peer_identity = occ->peer_identity; | ||
896 | GNUNET_memcpy (msg->hello, | ||
897 | occ->hello, | ||
898 | hello_size); | ||
899 | GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, | ||
900 | &msg->header); | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered | ||
906 | * using its TRANSPORT connection; if remote the HELLO is sent remotely by using | ||
907 | * send_hello_thru_rocc() | ||
908 | * | ||
909 | * @param cls the OverlayConnectContext | ||
910 | */ | ||
911 | static void | ||
912 | send_hello (void *cls) | ||
913 | { | ||
914 | struct OverlayConnectContext *occ = cls; | ||
915 | struct LocalPeer2Context *lp2c; | ||
916 | char *other_peer_str; | ||
917 | |||
918 | occ->send_hello_task = NULL; | ||
919 | GNUNET_assert (NULL != occ->timeout_task); | ||
920 | GNUNET_assert (NULL != occ->hello); | ||
921 | if (OCC_TYPE_LOCAL != occ->type) | ||
922 | { | ||
923 | send_hello_thru_rocc (occ); | ||
924 | return; | ||
925 | } | ||
926 | lp2c = &occ->p2ctx.local; | ||
927 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
928 | LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", | ||
929 | (unsigned long long) occ->op_id, | ||
930 | GNUNET_i2s (&occ->peer_identity), | ||
931 | other_peer_str); | ||
932 | GNUNET_free (other_peer_str); | ||
933 | lp2c->ohh = | ||
934 | GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg, | ||
935 | occ->hello, | ||
936 | &occ_hello_sent_cb, | ||
937 | occ); | ||
938 | if (NULL == lp2c->ohh) | ||
939 | { | ||
940 | GNUNET_break (0); | ||
941 | occ->send_hello_task = | ||
942 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
943 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
944 | 100 | ||
945 | + GNUNET_CRYPTO_random_u32 | ||
946 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
947 | &send_hello, occ); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | |||
952 | /** | ||
953 | * Callback from cache with needed handles set | ||
954 | * | ||
955 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
956 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
957 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
958 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
959 | * @param ignore_ peer identity which is ignored in this callback | ||
960 | * @param cfg configuration of the peer | ||
961 | */ | ||
962 | static void | ||
963 | p2_transport_connect_cache_callback (void *cls, | ||
964 | struct GNUNET_CORE_Handle *ch, | ||
965 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
966 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
967 | const struct GNUNET_PeerIdentity *ignore_, | ||
968 | const struct | ||
969 | GNUNET_CONFIGURATION_Handle *cfg) | ||
970 | { | ||
971 | struct OverlayConnectContext *occ = cls; | ||
972 | |||
973 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
974 | if (NULL == th) | ||
975 | { | ||
976 | GNUNET_asprintf (&occ->emsg, | ||
977 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
978 | (unsigned long long) occ->op_id, | ||
979 | GNUNET_i2s (&occ->other_peer_identity)); | ||
980 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
981 | occ->timeout_task = | ||
982 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
983 | return; | ||
984 | } | ||
985 | occ->p2ctx.local.tcc.th_ = th; | ||
986 | occ->p2ctx.local.tcc.cfg = cfg; | ||
987 | GNUNET_asprintf (&occ->emsg, | ||
988 | "0x%llx: Timeout while offering HELLO to %s", | ||
989 | (unsigned long long) occ->op_id, | ||
990 | GNUNET_i2s (&occ->other_peer_identity)); | ||
991 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
992 | } | ||
993 | |||
994 | |||
995 | /** | ||
996 | * Connects to the transport of the other peer if it is a local peer and | ||
997 | * schedules the send hello task | ||
998 | * | ||
999 | * @param occ the overlay connect context | ||
1000 | */ | ||
1001 | static void | ||
1002 | p2_transport_connect (struct OverlayConnectContext *occ) | ||
1003 | { | ||
1004 | struct Peer *peer2; | ||
1005 | |||
1006 | /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the | ||
1007 | HELLO! */ | ||
1008 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1009 | "Connecting to transport of peer %s to obtain HELLO\n", | ||
1010 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1011 | GNUNET_assert (NULL == occ->emsg); | ||
1012 | GNUNET_assert (NULL != occ->hello); | ||
1013 | GNUNET_assert (NULL == occ->ghh); | ||
1014 | GNUNET_assert (NULL == occ->p1th_); | ||
1015 | GNUNET_assert (NULL == occ->cgh_p1th); | ||
1016 | if (OCC_TYPE_LOCAL == occ->type) | ||
1017 | { | ||
1018 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
1019 | occ->p2ctx.local.tcc.cgh_p2_th = | ||
1020 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
1021 | peer2->details.local.cfg, | ||
1022 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1023 | &p2_transport_connect_cache_callback, | ||
1024 | occ, NULL, NULL, NULL); | ||
1025 | return; | ||
1026 | } | ||
1027 | GNUNET_asprintf (&occ->emsg, | ||
1028 | "0x%llx: Timeout while offering HELLO to %s", | ||
1029 | (unsigned long long) occ->op_id, | ||
1030 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1031 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /** | ||
1036 | * Test for checking whether HELLO message is empty | ||
1037 | * | ||
1038 | * @param cls empty flag to set | ||
1039 | * @param address the HELLO | ||
1040 | * @param expiration expiration of the HELLO | ||
1041 | * @return #GNUNET_OK | ||
1042 | */ | ||
1043 | static int | ||
1044 | test_address (void *cls, | ||
1045 | const struct GNUNET_HELLO_Address *address, | ||
1046 | struct GNUNET_TIME_Absolute expiration) | ||
1047 | { | ||
1048 | int *empty = cls; | ||
1049 | |||
1050 | *empty = GNUNET_NO; | ||
1051 | return GNUNET_OK; | ||
1052 | } | ||
1053 | |||
1054 | |||
1055 | /** | ||
1056 | * Function called whenever there is an update to the HELLO of peers in the | ||
1057 | * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's | ||
1058 | * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1 | ||
1059 | * | ||
1060 | * @param cls closure | ||
1061 | * @param hello our updated HELLO | ||
1062 | */ | ||
1063 | static void | ||
1064 | hello_update_cb (void *cls, | ||
1065 | const struct GNUNET_MessageHeader *hello) | ||
1066 | { | ||
1067 | struct OverlayConnectContext *occ = cls; | ||
1068 | int empty; | ||
1069 | uint16_t msize; | ||
1070 | |||
1071 | msize = ntohs (hello->size); | ||
1072 | empty = GNUNET_YES; | ||
1073 | (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) | ||
1074 | hello, GNUNET_NO, | ||
1075 | &test_address, | ||
1076 | &empty); | ||
1077 | if (GNUNET_YES == empty) | ||
1078 | { | ||
1079 | LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", | ||
1080 | (unsigned long long) occ->op_id, | ||
1081 | GNUNET_i2s (&occ->peer_identity)); | ||
1082 | return; | ||
1083 | } | ||
1084 | LOG_DEBUG ("0x%llx: Received HELLO of %s\n", | ||
1085 | (unsigned long long) occ->op_id, | ||
1086 | GNUNET_i2s (&occ->peer_identity)); | ||
1087 | occ->hello = GNUNET_malloc (msize); | ||
1088 | GST_cache_add_hello (occ->peer->id, hello); | ||
1089 | GNUNET_memcpy (occ->hello, hello, msize); | ||
1090 | GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); | ||
1091 | occ->ghh = NULL; | ||
1092 | GST_connection_pool_get_handle_done (occ->cgh_p1th); | ||
1093 | occ->cgh_p1th = NULL; | ||
1094 | occ->p1th_ = NULL; | ||
1095 | GNUNET_free (occ->emsg); | ||
1096 | occ->emsg = NULL; | ||
1097 | p2_transport_connect (occ); | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /** | ||
1102 | * Callback from cache with needed handles set | ||
1103 | * | ||
1104 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1105 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1106 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1107 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1108 | * @param ignore_ peer identity which is ignored in this callback | ||
1109 | */ | ||
1110 | static void | ||
1111 | p1_transport_connect_cache_callback (void *cls, | ||
1112 | struct GNUNET_CORE_Handle *ch, | ||
1113 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1114 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1115 | const struct GNUNET_PeerIdentity *ignore_, | ||
1116 | const struct | ||
1117 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1118 | { | ||
1119 | struct OverlayConnectContext *occ = cls; | ||
1120 | |||
1121 | GNUNET_free (occ->emsg); | ||
1122 | occ->emsg = NULL; | ||
1123 | if (NULL == th) | ||
1124 | { | ||
1125 | GNUNET_asprintf (&occ->emsg, | ||
1126 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
1127 | (unsigned long long) occ->op_id, | ||
1128 | GNUNET_i2s (&occ->peer_identity)); | ||
1129 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1130 | occ->timeout_task = | ||
1131 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1132 | return; | ||
1133 | } | ||
1134 | GNUNET_assert (NULL == occ->p1th_); | ||
1135 | GNUNET_assert (NULL != occ->cgh_p1th); | ||
1136 | occ->p1th_ = th; | ||
1137 | GNUNET_asprintf (&occ->emsg, | ||
1138 | "0x%llx: Timeout while acquiring HELLO of peer %s", | ||
1139 | (unsigned long long) occ->op_id, | ||
1140 | GNUNET_i2s (&occ->peer_identity)); | ||
1141 | occ->ghh = GNUNET_TRANSPORT_hello_get (cfg, | ||
1142 | GNUNET_TRANSPORT_AC_ANY, | ||
1143 | &hello_update_cb, | ||
1144 | occ); | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | /** | ||
1149 | * Callback from cache with needed CORE handle set | ||
1150 | * | ||
1151 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1152 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1153 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1154 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1155 | * @param my_identity the identity of our peer | ||
1156 | */ | ||
1157 | static void | ||
1158 | occ_cache_get_handle_core_cb (void *cls, | ||
1159 | struct GNUNET_CORE_Handle *ch, | ||
1160 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1161 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1162 | const struct GNUNET_PeerIdentity *my_identity, | ||
1163 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1164 | { | ||
1165 | struct OverlayConnectContext *occ = cls; | ||
1166 | const struct GNUNET_MessageHeader *hello; | ||
1167 | |||
1168 | GNUNET_assert (NULL != occ->timeout_task); | ||
1169 | GNUNET_free (occ->emsg); | ||
1170 | if ((NULL == ch) || (NULL == my_identity)) | ||
1171 | { | ||
1172 | GNUNET_asprintf (&occ->emsg, | ||
1173 | "0x%llx: Failed to connect to CORE of peer with " | ||
1174 | "id: %u", | ||
1175 | (unsigned long long) occ->op_id, | ||
1176 | occ->peer->id); | ||
1177 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1178 | occ->timeout_task = | ||
1179 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1180 | return; | ||
1181 | } | ||
1182 | occ->emsg = NULL; | ||
1183 | if (NULL != | ||
1184 | GNUNET_CORE_get_mq (ch, | ||
1185 | &occ->other_peer_identity)) | ||
1186 | { | ||
1187 | LOG_DEBUG ("0x%llx: Target peer already connected\n", | ||
1188 | (unsigned long long) occ->op_id); | ||
1189 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1190 | occ->timeout_task = NULL; | ||
1191 | send_overlay_connect_success_msg (occ); | ||
1192 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); | ||
1193 | return; | ||
1194 | } | ||
1195 | occ->peer_identity = *my_identity; | ||
1196 | LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", | ||
1197 | (unsigned long long) occ->op_id, | ||
1198 | GNUNET_i2s (&occ->peer_identity)); | ||
1199 | /* Lookup for HELLO in hello cache */ | ||
1200 | if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id))) | ||
1201 | { | ||
1202 | LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", | ||
1203 | (unsigned long long) occ->op_id, | ||
1204 | GNUNET_i2s (&occ->peer_identity)); | ||
1205 | occ->hello = GNUNET_copy_message (hello); | ||
1206 | p2_transport_connect (occ); | ||
1207 | return; | ||
1208 | } | ||
1209 | GNUNET_asprintf (&occ->emsg, | ||
1210 | "0x%llx: Timeout while acquiring TRANSPORT of %s from cache", | ||
1211 | (unsigned long long) occ->op_id, | ||
1212 | GNUNET_i2s (&occ->peer_identity)); | ||
1213 | occ->cgh_p1th = | ||
1214 | GST_connection_pool_get_handle (occ->peer->id, | ||
1215 | occ->peer->details.local.cfg, | ||
1216 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1217 | p1_transport_connect_cache_callback, | ||
1218 | occ, | ||
1219 | NULL, NULL, NULL); | ||
1220 | } | ||
1221 | |||
1222 | |||
1223 | /** | ||
1224 | * Callback to be called when forwarded get peer config operation as part of | ||
1225 | * overlay connect is successful. Connection to Peer 1's core is made and is | ||
1226 | * checked for new connection from peer 2 | ||
1227 | * | ||
1228 | * @param cls ForwardedOperationContext | ||
1229 | * @param msg the peer create success message | ||
1230 | */ | ||
1231 | static void | ||
1232 | overlay_connect_get_config (void *cls, | ||
1233 | const struct GNUNET_MessageHeader *msg) | ||
1234 | { | ||
1235 | struct OverlayConnectContext *occ = cls; | ||
1236 | struct RemotePeer2Context *rp2c; | ||
1237 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg; | ||
1238 | |||
1239 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1240 | rp2c = &occ->p2ctx.remote; | ||
1241 | rp2c->opc = NULL; | ||
1242 | GNUNET_assert (NULL != occ->timeout_task); | ||
1243 | if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type)) | ||
1244 | { | ||
1245 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1246 | occ->timeout_task = | ||
1247 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1248 | } | ||
1249 | cmsg = | ||
1250 | (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; | ||
1251 | occ->other_peer_identity = cmsg->peer_identity; | ||
1252 | GNUNET_free (occ->emsg); | ||
1253 | GNUNET_asprintf (&occ->emsg, | ||
1254 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1255 | "id: %u", | ||
1256 | (unsigned long long) occ->op_id, | ||
1257 | occ->peer->id); | ||
1258 | occ->cgh_ch = | ||
1259 | GST_connection_pool_get_handle (occ->peer->id, | ||
1260 | occ->peer->details.local.cfg, | ||
1261 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1262 | occ_cache_get_handle_core_cb, | ||
1263 | occ, | ||
1264 | &occ->other_peer_identity, | ||
1265 | &overlay_connect_notify, | ||
1266 | occ); | ||
1267 | return; | ||
1268 | } | ||
1269 | |||
1270 | |||
1271 | /** | ||
1272 | * Callback which will be called after a host registration succeeded or failed | ||
1273 | * | ||
1274 | * @param cls the RegisteredHostContext | ||
1275 | * @param emsg the error message; NULL if host registration is successful | ||
1276 | */ | ||
1277 | static void | ||
1278 | host_registration_comp (void *cls, const char *emsg) | ||
1279 | { | ||
1280 | struct RegisteredHostContext *rhc = cls; | ||
1281 | |||
1282 | rhc->state = RHC_DONE; | ||
1283 | GST_process_next_focc (rhc); | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * Iterator to match a registered host context | ||
1289 | * | ||
1290 | * @param cls pointer 2 pointer of RegisteredHostContext | ||
1291 | * @param key current key code | ||
1292 | * @param value value in the hash map | ||
1293 | * @return #GNUNET_YES if we should continue to | ||
1294 | * iterate, | ||
1295 | * #GNUNET_NO if not. | ||
1296 | */ | ||
1297 | static int | ||
1298 | reghost_match_iterator (void *cls, | ||
1299 | const struct GNUNET_HashCode *key, | ||
1300 | void *value) | ||
1301 | { | ||
1302 | struct RegisteredHostContext **rh = cls; | ||
1303 | struct RegisteredHostContext *rh_val = value; | ||
1304 | |||
1305 | if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host)) | ||
1306 | { | ||
1307 | GNUNET_free (*rh); | ||
1308 | *rh = rh_val; | ||
1309 | return GNUNET_NO; | ||
1310 | } | ||
1311 | return GNUNET_YES; | ||
1312 | } | ||
1313 | |||
1314 | |||
1315 | /** | ||
1316 | * Function to generate the hashcode corresponding to a RegisteredHostContext | ||
1317 | * | ||
1318 | * @param reg_host the host which is being registered in RegisteredHostContext | ||
1319 | * @param host the host of the controller which has to connect to the above rhost | ||
1320 | * @return the hashcode | ||
1321 | */ | ||
1322 | static struct GNUNET_HashCode | ||
1323 | hash_hosts (struct GNUNET_TESTBED_Host *reg_host, | ||
1324 | struct GNUNET_TESTBED_Host *host) | ||
1325 | { | ||
1326 | struct GNUNET_HashCode hash; | ||
1327 | uint32_t host_ids[2]; | ||
1328 | |||
1329 | host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host); | ||
1330 | host_ids[1] = GNUNET_TESTBED_host_get_id_ (host); | ||
1331 | GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash); | ||
1332 | return hash; | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * Checks if the given host is registered at the given slave. | ||
1338 | * | ||
1339 | * @param slave the slave where registration has to be checked. The check is | ||
1340 | * actually done through a locally maintained hashmap. No | ||
1341 | * communication with the slave is involved. | ||
1342 | * @param host the host to register | ||
1343 | * @return If the given host is not registered already or the registration is | ||
1344 | * pending, it returns the registration context. Any overlay connects | ||
1345 | * to be forwarded should be queued in the context so that they can be | ||
1346 | * executed when the registration is completed. If the given host is | ||
1347 | * already registered, NULL is returned. | ||
1348 | */ | ||
1349 | static struct RegisteredHostContext * | ||
1350 | register_host (struct Slave *slave, | ||
1351 | struct GNUNET_TESTBED_Host *host) | ||
1352 | { | ||
1353 | struct GNUNET_HashCode hash; | ||
1354 | struct RegisteredHostContext *rhc; | ||
1355 | |||
1356 | rhc = GNUNET_new (struct RegisteredHostContext); | ||
1357 | rhc->reg_host = host; | ||
1358 | rhc->host = GST_host_list[slave->host_id]; | ||
1359 | GNUNET_assert (NULL != rhc->reg_host); | ||
1360 | GNUNET_assert (NULL != rhc->host); | ||
1361 | rhc->state = RHC_INIT; | ||
1362 | hash = hash_hosts (rhc->reg_host, rhc->host); | ||
1363 | if ((GNUNET_NO == | ||
1364 | GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, | ||
1365 | &hash)) || | ||
1366 | (GNUNET_SYSERR != | ||
1367 | GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, | ||
1368 | &hash, | ||
1369 | reghost_match_iterator, | ||
1370 | &rhc))) | ||
1371 | { | ||
1372 | /* create and add a new registered host context */ | ||
1373 | /* add the focc to its queue */ | ||
1374 | GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, | ||
1375 | &hash, | ||
1376 | rhc, | ||
1377 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1378 | GST_queue_host_registration (slave, | ||
1379 | host_registration_comp, | ||
1380 | rhc, | ||
1381 | rhc->reg_host); | ||
1382 | } | ||
1383 | else | ||
1384 | { | ||
1385 | /* rhc is now set to the existing one from the hash map by | ||
1386 | * reghost_match_iterator() */ | ||
1387 | /* if queue is empty then ignore creating focc and proceed with normal | ||
1388 | * forwarding */ | ||
1389 | if (RHC_DONE == rhc->state) | ||
1390 | return NULL; | ||
1391 | } | ||
1392 | return rhc; | ||
1393 | } | ||
1394 | |||
1395 | |||
1396 | /** | ||
1397 | * Forwards the overlay connect request to a slave controller. Before | ||
1398 | * forwarding, any hosts which are needed to be known by the slave controller to | ||
1399 | * execute the overlay connect request are registered at slave. | ||
1400 | * | ||
1401 | * @param msg the overlay connect request message to be forwarded | ||
1402 | * @param client the client to which the status of the forwarded request has to | ||
1403 | * be notified | ||
1404 | */ | ||
1405 | static void | ||
1406 | forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, | ||
1407 | struct GNUNET_SERVICE_Client *client) | ||
1408 | { | ||
1409 | struct ForwardedOperationContext *fopc; | ||
1410 | struct Route *route_to_peer2_host; | ||
1411 | struct Route *route_to_peer1_host; | ||
1412 | struct Peer *peer; | ||
1413 | struct RegisteredHostContext *rhc; | ||
1414 | struct ForwardedOverlayConnectContext *focc; | ||
1415 | uint64_t op_id; | ||
1416 | uint32_t peer2_host_id; | ||
1417 | uint32_t p1; | ||
1418 | uint32_t p2; | ||
1419 | |||
1420 | p1 = ntohl (msg->peer1); | ||
1421 | p2 = ntohl (msg->peer2); | ||
1422 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1423 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1424 | GNUNET_assert (VALID_PEER_ID (p1)); | ||
1425 | GNUNET_assert (VALID_HOST_ID (peer2_host_id)); | ||
1426 | peer = GST_peer_list[p1]; | ||
1427 | GNUNET_assert (GNUNET_YES == peer->is_remote); | ||
1428 | LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", | ||
1429 | (unsigned long long) op_id); | ||
1430 | route_to_peer2_host = GST_find_dest_route (peer2_host_id); | ||
1431 | route_to_peer1_host = GST_find_dest_route | ||
1432 | (peer->details.remote.remote_host_id); | ||
1433 | GNUNET_assert (NULL != route_to_peer1_host); | ||
1434 | if ((NULL != route_to_peer2_host) && | ||
1435 | (route_to_peer1_host->dest == route_to_peer2_host->dest)) | ||
1436 | goto forward; | ||
1437 | /* Peer2 is either with us OR peer1 and peer2 can be reached through | ||
1438 | different subtrees OR peer2 is on a subtree unknown to us */ | ||
1439 | if (NULL != (rhc = register_host (peer->details.remote.slave, | ||
1440 | GST_host_list[peer2_host_id]))) | ||
1441 | { | ||
1442 | LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, | ||
1443 | p2); | ||
1444 | focc = GNUNET_new (struct ForwardedOverlayConnectContext); | ||
1445 | focc->rhc = rhc; | ||
1446 | focc->peer1 = p1; | ||
1447 | focc->peer2 = p2; | ||
1448 | focc->peer2_host_id = peer2_host_id; | ||
1449 | focc->orig_msg = GNUNET_copy_message (&msg->header); | ||
1450 | focc->operation_id = op_id; | ||
1451 | focc->client = client; | ||
1452 | GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, | ||
1453 | rhc->focc_dll_tail, | ||
1454 | focc); | ||
1455 | return; | ||
1456 | } | ||
1457 | |||
1458 | forward: | ||
1459 | LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, | ||
1460 | p2); | ||
1461 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
1462 | fopc->client = client; | ||
1463 | fopc->operation_id = op_id; | ||
1464 | fopc->type = OP_OVERLAY_CONNECT; | ||
1465 | fopc->opc = | ||
1466 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1467 | slave->controller, op_id, | ||
1468 | &msg->header, | ||
1469 | &GST_forwarded_operation_reply_relay, | ||
1470 | fopc); | ||
1471 | fopc->timeout_task = | ||
1472 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1473 | &GST_forwarded_operation_timeout, | ||
1474 | fopc); | ||
1475 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1476 | fopcq_tail, | ||
1477 | fopc); | ||
1478 | } | ||
1479 | |||
1480 | |||
1481 | /** | ||
1482 | * Callback called when a connection to the controller of peer2 has been | ||
1483 | * established | ||
1484 | * | ||
1485 | * @param cls the overlay connect contexts | ||
1486 | * @param c handle to the controller connection | ||
1487 | */ | ||
1488 | static void | ||
1489 | p2_controller_connect_cb (void *cls, | ||
1490 | struct GNUNET_TESTBED_Controller *c) | ||
1491 | { | ||
1492 | struct OverlayConnectContext *occ = cls; | ||
1493 | struct RemotePeer2Context *rp2c; | ||
1494 | struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg; | ||
1495 | |||
1496 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1497 | rp2c = &occ->p2ctx.remote; | ||
1498 | rp2c->ncn = NULL; | ||
1499 | rp2c->p2c = c; | ||
1500 | cmsg.header.size = | ||
1501 | htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); | ||
1502 | cmsg.header.type = | ||
1503 | htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); | ||
1504 | cmsg.peer_id = htonl (occ->other_peer_id); | ||
1505 | cmsg.operation_id = GNUNET_htonll (occ->op_id); | ||
1506 | rp2c->opc = | ||
1507 | GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, | ||
1508 | occ->op_id, | ||
1509 | &cmsg.header, | ||
1510 | &overlay_connect_get_config, | ||
1511 | occ); | ||
1512 | GNUNET_free (occ->emsg); | ||
1513 | GNUNET_asprintf (&occ->emsg, | ||
1514 | "0x%llx: Timeout while getting peer identity of peer " | ||
1515 | "with id: %u", | ||
1516 | (unsigned long long) occ->op_id, | ||
1517 | occ->other_peer_id); | ||
1518 | } | ||
1519 | |||
1520 | |||
1521 | /** | ||
1522 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages | ||
1523 | * | ||
1524 | * @param cls identification of the client | ||
1525 | * @param msg the actual message | ||
1526 | */ | ||
1527 | void | ||
1528 | handle_overlay_connect (void *cls, | ||
1529 | const struct GNUNET_TESTBED_OverlayConnectMessage *msg) | ||
1530 | { | ||
1531 | struct GNUNET_SERVICE_Client *client = cls; | ||
1532 | struct Peer *peer; | ||
1533 | struct Peer *peer2; | ||
1534 | struct OverlayConnectContext *occ; | ||
1535 | struct Neighbour *p2n; | ||
1536 | uint64_t operation_id; | ||
1537 | uint32_t p1; | ||
1538 | uint32_t p2; | ||
1539 | uint32_t peer2_host_id; | ||
1540 | |||
1541 | p1 = ntohl (msg->peer1); | ||
1542 | p2 = ntohl (msg->peer2); | ||
1543 | if (! VALID_PEER_ID (p1)) | ||
1544 | { | ||
1545 | GNUNET_break (0); | ||
1546 | GNUNET_SERVICE_client_drop (client); | ||
1547 | return; | ||
1548 | } | ||
1549 | peer = GST_peer_list[p1]; | ||
1550 | operation_id = GNUNET_ntohll (msg->operation_id); | ||
1551 | LOG_DEBUG | ||
1552 | ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", | ||
1553 | p1, | ||
1554 | p2, | ||
1555 | (unsigned long long) operation_id); | ||
1556 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1557 | if (GNUNET_YES == peer->is_remote) | ||
1558 | { | ||
1559 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1560 | { | ||
1561 | GNUNET_break (0); | ||
1562 | GNUNET_SERVICE_client_drop (client); | ||
1563 | return; | ||
1564 | } | ||
1565 | forward_overlay_connect (msg, client); | ||
1566 | GNUNET_SERVICE_client_continue (client); | ||
1567 | return; | ||
1568 | } | ||
1569 | p2n = NULL; | ||
1570 | occ = GNUNET_new (struct OverlayConnectContext); | ||
1571 | occ->type = OCC_TYPE_LOCAL; | ||
1572 | if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ | ||
1573 | { | ||
1574 | if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) | ||
1575 | { | ||
1576 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1577 | { | ||
1578 | GNUNET_break (0); | ||
1579 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1580 | "0x%llx: Peer %u's host not in our neighbours list\n", | ||
1581 | (unsigned long long) operation_id, p2); | ||
1582 | GNUNET_SERVICE_client_drop (client); | ||
1583 | GNUNET_free (occ); | ||
1584 | return; | ||
1585 | } | ||
1586 | p2n = GST_create_neighbour (GST_host_list[peer2_host_id]); | ||
1587 | } | ||
1588 | occ->type = OCC_TYPE_REMOTE_LATERAL; | ||
1589 | occ->p2ctx.remote.p2n = p2n; | ||
1590 | } | ||
1591 | else if (GNUNET_YES == GST_peer_list[p2]->is_remote) | ||
1592 | { | ||
1593 | occ->type = OCC_TYPE_REMOTE_SLAVE; | ||
1594 | occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller; | ||
1595 | } | ||
1596 | GNUNET_CONTAINER_DLL_insert_tail (occq_head, | ||
1597 | occq_tail, | ||
1598 | occ); | ||
1599 | occ->client = client; | ||
1600 | occ->other_peer_id = p2; | ||
1601 | GST_peer_list[p1]->reference_cnt++; | ||
1602 | occ->peer = GST_peer_list[p1]; | ||
1603 | occ->op_id = operation_id; | ||
1604 | GNUNET_assert (NULL == occ->timeout_task); | ||
1605 | occ->timeout_task = | ||
1606 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1607 | &timeout_overlay_connect, | ||
1608 | occ); | ||
1609 | switch (occ->type) | ||
1610 | { | ||
1611 | case OCC_TYPE_REMOTE_LATERAL: | ||
1612 | GNUNET_asprintf (&occ->emsg, | ||
1613 | "0x%llx: Timeout while acquiring connection to peer %u's " | ||
1614 | "host: %u\n", | ||
1615 | (unsigned long long) occ->op_id, | ||
1616 | occ->other_peer_id, | ||
1617 | peer2_host_id); | ||
1618 | occ->p2ctx.remote.ncn | ||
1619 | = GST_neighbour_get_connection (p2n, | ||
1620 | &p2_controller_connect_cb, | ||
1621 | occ); | ||
1622 | break; | ||
1623 | |||
1624 | case OCC_TYPE_REMOTE_SLAVE: | ||
1625 | p2_controller_connect_cb (occ, | ||
1626 | occ->p2ctx.remote.p2c); | ||
1627 | break; | ||
1628 | |||
1629 | case OCC_TYPE_LOCAL: | ||
1630 | peer2 = GST_peer_list[occ->other_peer_id]; | ||
1631 | peer2->reference_cnt++; | ||
1632 | GNUNET_TESTING_peer_get_identity (peer2->details.local.peer, | ||
1633 | &occ->other_peer_identity); | ||
1634 | GNUNET_asprintf (&occ->emsg, | ||
1635 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1636 | "id: %u", | ||
1637 | (unsigned long long) occ->op_id, | ||
1638 | occ->peer->id); | ||
1639 | occ->cgh_ch = | ||
1640 | GST_connection_pool_get_handle (occ->peer->id, | ||
1641 | occ->peer->details.local.cfg, | ||
1642 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1643 | occ_cache_get_handle_core_cb, occ, | ||
1644 | &occ->other_peer_identity, | ||
1645 | &overlay_connect_notify, occ); | ||
1646 | break; | ||
1647 | } | ||
1648 | GNUNET_SERVICE_client_continue (client); | ||
1649 | } | ||
1650 | |||
1651 | |||
1652 | /** | ||
1653 | * Function to cleanup RemoteOverlayConnectCtx and any associated tasks | ||
1654 | * with it | ||
1655 | * | ||
1656 | * @param rocc the RemoteOverlayConnectCtx | ||
1657 | */ | ||
1658 | static void | ||
1659 | cleanup_rocc (struct RemoteOverlayConnectCtx *rocc) | ||
1660 | { | ||
1661 | LOG_DEBUG ("0x%llx: Cleaning up rocc\n", | ||
1662 | (unsigned long long) rocc->op_id); | ||
1663 | if (NULL != rocc->attempt_connect_task_id) | ||
1664 | GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id); | ||
1665 | if (NULL != rocc->timeout_rocc_task_id) | ||
1666 | GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id); | ||
1667 | if (NULL != rocc->ohh) | ||
1668 | GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh); | ||
1669 | if (NULL != rocc->tcc.csh) | ||
1670 | GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh); | ||
1671 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th); | ||
1672 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats); | ||
1673 | GNUNET_assert (rocc->peer->reference_cnt > 0); | ||
1674 | rocc->peer->reference_cnt--; | ||
1675 | if ((GNUNET_YES == rocc->peer->destroy_flag) && | ||
1676 | (0 == rocc->peer->reference_cnt)) | ||
1677 | GST_destroy_peer (rocc->peer); | ||
1678 | GNUNET_free (rocc->hello); | ||
1679 | GNUNET_CONTAINER_DLL_remove (roccq_head, | ||
1680 | roccq_tail, | ||
1681 | rocc); | ||
1682 | GNUNET_free (rocc); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /** | ||
1687 | * Task to timeout rocc and cleanit up | ||
1688 | * | ||
1689 | * @param cls the RemoteOverlayConnectCtx | ||
1690 | */ | ||
1691 | static void | ||
1692 | timeout_rocc_task (void *cls) | ||
1693 | { | ||
1694 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1695 | |||
1696 | GNUNET_assert (rocc->timeout_rocc_task_id != NULL); | ||
1697 | rocc->timeout_rocc_task_id = NULL; | ||
1698 | LOG_DEBUG ("0x%llx: rocc timed out\n", | ||
1699 | (unsigned long long) rocc->op_id); | ||
1700 | cleanup_rocc (rocc); | ||
1701 | } | ||
1702 | |||
1703 | |||
1704 | /** | ||
1705 | * Function called to notify transport users that another | ||
1706 | * peer connected to us. | ||
1707 | * | ||
1708 | * @param cls the RemoteOverlayConnectContext | ||
1709 | * @param new_peer the peer that connected | ||
1710 | */ | ||
1711 | static void | ||
1712 | cache_transport_peer_connect_notify (void *cls, | ||
1713 | const struct GNUNET_PeerIdentity *new_peer) | ||
1714 | { | ||
1715 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1716 | |||
1717 | LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", | ||
1718 | (unsigned long long) rocc->op_id); | ||
1719 | GNUNET_assert (0 == | ||
1720 | memcmp (new_peer, &rocc->a_id, | ||
1721 | sizeof(struct GNUNET_PeerIdentity))); | ||
1722 | LOG_DEBUG ("0x%llx: Peer %s connected\n", | ||
1723 | (unsigned long long) rocc->op_id, | ||
1724 | GNUNET_i2s (&rocc->a_id)); | ||
1725 | cleanup_rocc (rocc); | ||
1726 | } | ||
1727 | |||
1728 | |||
1729 | /** | ||
1730 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1731 | * whose identity is in RemoteOverlayConnectCtx | ||
1732 | * | ||
1733 | * @param cls the RemoteOverlayConnectCtx | ||
1734 | */ | ||
1735 | static void | ||
1736 | attempt_connect_task (void *cls); | ||
1737 | |||
1738 | |||
1739 | /** | ||
1740 | * Task that is run when hello has been sent If tc->reason = | ||
1741 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
1742 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
1743 | * | ||
1744 | * @param cls the overlay connect context | ||
1745 | */ | ||
1746 | static void | ||
1747 | rocc_hello_sent_cb (void *cls) | ||
1748 | { | ||
1749 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1750 | |||
1751 | rocc->ohh = NULL; | ||
1752 | GNUNET_assert (NULL == rocc->attempt_connect_task_id); | ||
1753 | LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n", | ||
1754 | (unsigned long long) rocc->op_id, | ||
1755 | GNUNET_i2s (&rocc->a_id), | ||
1756 | rocc->peer->id); | ||
1757 | rocc->tcc.cgh_p2_ats = | ||
1758 | GST_connection_pool_get_handle (rocc->peer->id, | ||
1759 | rocc->peer->details.local.cfg, | ||
1760 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
1761 | &occ_cache_get_handle_ats_rocc_cb, | ||
1762 | rocc, NULL, NULL, NULL); | ||
1763 | } | ||
1764 | |||
1765 | |||
1766 | /** | ||
1767 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1768 | * whose identity is in RemoteOverlayConnectCtx | ||
1769 | * | ||
1770 | * @param cls the RemoteOverlayConnectCtx | ||
1771 | */ | ||
1772 | static void | ||
1773 | attempt_connect_task (void *cls) | ||
1774 | { | ||
1775 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1776 | |||
1777 | GNUNET_assert (NULL != rocc->attempt_connect_task_id); | ||
1778 | rocc->attempt_connect_task_id = NULL; | ||
1779 | LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n", | ||
1780 | (unsigned long long) rocc->op_id, | ||
1781 | GNUNET_i2s (&rocc->a_id), | ||
1782 | rocc->peer->id); | ||
1783 | rocc->ohh = | ||
1784 | GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg, | ||
1785 | rocc->hello, | ||
1786 | &rocc_hello_sent_cb, | ||
1787 | rocc); | ||
1788 | if (NULL == rocc->ohh) | ||
1789 | rocc->attempt_connect_task_id = | ||
1790 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1791 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1792 | 100 | ||
1793 | + GNUNET_CRYPTO_random_u32 | ||
1794 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
1795 | &attempt_connect_task, rocc); | ||
1796 | } | ||
1797 | |||
1798 | |||
1799 | /** | ||
1800 | * Callback from cache with needed handles set | ||
1801 | * | ||
1802 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1803 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1804 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1805 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1806 | * @param ignore_ peer identity which is ignored in this callback | ||
1807 | */ | ||
1808 | static void | ||
1809 | rocc_cache_get_handle_transport_cb (void *cls, | ||
1810 | struct GNUNET_CORE_Handle *ch, | ||
1811 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1812 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1813 | const struct GNUNET_PeerIdentity *ignore_, | ||
1814 | const struct | ||
1815 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1816 | { | ||
1817 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1818 | |||
1819 | if (NULL == th) | ||
1820 | { | ||
1821 | rocc->timeout_rocc_task_id = | ||
1822 | GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc); | ||
1823 | return; | ||
1824 | } | ||
1825 | rocc->tcc.th_ = th; | ||
1826 | rocc->tcc.cfg = cfg; | ||
1827 | if (NULL != | ||
1828 | GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_, | ||
1829 | &rocc->a_id)) | ||
1830 | { | ||
1831 | LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n", | ||
1832 | (unsigned long long) rocc->op_id, | ||
1833 | GNUNET_i2s (&rocc->a_id), | ||
1834 | rocc->peer->id); | ||
1835 | cleanup_rocc (rocc); | ||
1836 | return; | ||
1837 | } | ||
1838 | rocc->attempt_connect_task_id = | ||
1839 | GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); | ||
1840 | } | ||
1841 | |||
1842 | |||
1843 | /** | ||
1844 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1845 | * | ||
1846 | * @param cls identification of the client | ||
1847 | * @param msg the actual message | ||
1848 | * @return #GNUNET_OK if @a msg is well-formed | ||
1849 | */ | ||
1850 | int | ||
1851 | check_remote_overlay_connect (void *cls, | ||
1852 | const struct | ||
1853 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1854 | { | ||
1855 | uint32_t peer_id; | ||
1856 | uint16_t msize; | ||
1857 | uint16_t hsize; | ||
1858 | |||
1859 | msize = ntohs (msg->header.size); | ||
1860 | if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)) | ||
1861 | { | ||
1862 | GNUNET_break (0); | ||
1863 | return GNUNET_SYSERR; | ||
1864 | } | ||
1865 | hsize = ntohs (msg->hello->size); | ||
1866 | if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != | ||
1867 | msize) | ||
1868 | { | ||
1869 | GNUNET_break (0); | ||
1870 | return GNUNET_SYSERR; | ||
1871 | } | ||
1872 | peer_id = ntohl (msg->peer); | ||
1873 | if ((peer_id >= GST_peer_list_size) || | ||
1874 | (NULL == GST_peer_list[peer_id])) | ||
1875 | { | ||
1876 | GNUNET_break_op (0); | ||
1877 | return GNUNET_SYSERR; | ||
1878 | } | ||
1879 | return GNUNET_OK; | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | /** | ||
1884 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1885 | * | ||
1886 | * @param cls identification of the client | ||
1887 | * @param msg the actual message | ||
1888 | */ | ||
1889 | void | ||
1890 | handle_remote_overlay_connect (void *cls, | ||
1891 | const struct | ||
1892 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1893 | { | ||
1894 | struct GNUNET_SERVICE_Client *client = cls; | ||
1895 | struct RemoteOverlayConnectCtx *rocc; | ||
1896 | struct Peer *peer; | ||
1897 | struct GNUNET_PeerIdentity pid; | ||
1898 | static char pid_str[16]; | ||
1899 | uint32_t peer_id; | ||
1900 | uint16_t hsize; | ||
1901 | |||
1902 | hsize = ntohs (msg->hello->size); | ||
1903 | peer_id = ntohl (msg->peer); | ||
1904 | peer = GST_peer_list[peer_id]; | ||
1905 | if (GNUNET_YES == peer->is_remote) | ||
1906 | { | ||
1907 | struct GNUNET_MessageHeader *msg2; | ||
1908 | |||
1909 | msg2 = GNUNET_copy_message (&msg->header); | ||
1910 | GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, | ||
1911 | msg2); | ||
1912 | GNUNET_SERVICE_client_continue (client); | ||
1913 | return; | ||
1914 | } | ||
1915 | rocc = GNUNET_new (struct RemoteOverlayConnectCtx); | ||
1916 | rocc->op_id = GNUNET_ntohll (msg->operation_id); | ||
1917 | GNUNET_CONTAINER_DLL_insert_tail (roccq_head, | ||
1918 | roccq_tail, | ||
1919 | rocc); | ||
1920 | rocc->a_id = msg->peer_identity; | ||
1921 | GNUNET_TESTING_peer_get_identity (peer->details.local.peer, | ||
1922 | &pid); | ||
1923 | (void) GNUNET_strlcpy (pid_str, | ||
1924 | GNUNET_i2s (&pid), | ||
1925 | sizeof(pid_str)); | ||
1926 | LOG_DEBUG ( | ||
1927 | "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n", | ||
1928 | (unsigned long long) rocc->op_id, | ||
1929 | pid_str, | ||
1930 | GNUNET_i2s (&rocc->a_id), | ||
1931 | hsize); | ||
1932 | rocc->peer = peer; | ||
1933 | rocc->peer->reference_cnt++; | ||
1934 | rocc->hello = GNUNET_malloc (hsize); | ||
1935 | GNUNET_memcpy (rocc->hello, | ||
1936 | msg->hello, | ||
1937 | hsize); | ||
1938 | rocc->tcc.cgh_p2_th = | ||
1939 | GST_connection_pool_get_handle (peer_id, | ||
1940 | rocc->peer->details.local.cfg, | ||
1941 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1942 | &rocc_cache_get_handle_transport_cb, | ||
1943 | rocc, | ||
1944 | &rocc->a_id, | ||
1945 | &cache_transport_peer_connect_notify, | ||
1946 | rocc); | ||
1947 | rocc->timeout_rocc_task_id = | ||
1948 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1949 | &timeout_rocc_task, | ||
1950 | rocc); | ||
1951 | GNUNET_SERVICE_client_continue (client); | ||
1952 | } | ||
1953 | |||
1954 | |||
1955 | /** | ||
1956 | * Clears all pending overlay connect contexts in queue | ||
1957 | */ | ||
1958 | void | ||
1959 | GST_free_occq () | ||
1960 | { | ||
1961 | struct OverlayConnectContext *occ; | ||
1962 | |||
1963 | while (NULL != (occ = occq_head)) | ||
1964 | cleanup_occ (occ); | ||
1965 | } | ||
1966 | |||
1967 | |||
1968 | /** | ||
1969 | * Clears all pending remote overlay connect contexts in queue | ||
1970 | */ | ||
1971 | void | ||
1972 | GST_free_roccq () | ||
1973 | { | ||
1974 | struct RemoteOverlayConnectCtx *rocc; | ||
1975 | |||
1976 | while (NULL != (rocc = roccq_head)) | ||
1977 | cleanup_rocc (rocc); | ||
1978 | } | ||