diff options
Diffstat (limited to 'src/testbed/gnunet-service-testbed_oc.c')
-rw-r--r-- | src/testbed/gnunet-service-testbed_oc.c | 1996 |
1 files changed, 0 insertions, 1996 deletions
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c deleted file mode 100644 index b13a3b7e0..000000000 --- a/src/testbed/gnunet-service-testbed_oc.c +++ /dev/null | |||
@@ -1,1996 +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 | GNUNET_memcmp (new_peer, | ||
689 | &occ->peer_identity)) | ||
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 | GNUNET_memcmp (new_peer, | ||
695 | &occ->other_peer_identity)) | ||
696 | { | ||
697 | LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n", | ||
698 | new_peer_str, | ||
699 | other_peer_str); | ||
700 | GNUNET_free (new_peer_str); | ||
701 | GNUNET_free (other_peer_str); | ||
702 | return; | ||
703 | } | ||
704 | GNUNET_free (new_peer_str); | ||
705 | LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n", | ||
706 | (unsigned long long) occ->op_id, | ||
707 | other_peer_str, | ||
708 | GNUNET_i2s (&occ->peer_identity)); | ||
709 | GNUNET_free (other_peer_str); | ||
710 | if (NULL != occ->send_hello_task) | ||
711 | { | ||
712 | GNUNET_SCHEDULER_cancel (occ->send_hello_task); | ||
713 | occ->send_hello_task = NULL; | ||
714 | } | ||
715 | GNUNET_assert (NULL != occ->timeout_task); | ||
716 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
717 | occ->timeout_task = NULL; | ||
718 | switch (occ->type) | ||
719 | { | ||
720 | case OCC_TYPE_LOCAL: | ||
721 | cleanup_occ_lp2c (&occ->p2ctx.local); | ||
722 | break; | ||
723 | |||
724 | case OCC_TYPE_REMOTE_SLAVE: | ||
725 | case OCC_TYPE_REMOTE_LATERAL: | ||
726 | cleanup_occ_rp2c (&occ->p2ctx.remote); | ||
727 | break; | ||
728 | } | ||
729 | GNUNET_free (occ->emsg); | ||
730 | occ->emsg = NULL; | ||
731 | send_overlay_connect_success_msg (occ); | ||
732 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, | ||
733 | occ); | ||
734 | } | ||
735 | |||
736 | |||
737 | /** | ||
738 | * Callback from cache with needed ATS handle set | ||
739 | * | ||
740 | * @param cls a `struct OverlayConnectCtx *` | ||
741 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
742 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
743 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
744 | * @param my_identity the identity of our peer | ||
745 | * @param cfg configuration of the peer | ||
746 | */ | ||
747 | static void | ||
748 | occ_cache_get_handle_ats_occ_cb (void *cls, | ||
749 | struct GNUNET_CORE_Handle *ch, | ||
750 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
751 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
752 | const struct GNUNET_PeerIdentity *my_identity, | ||
753 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
754 | { | ||
755 | struct OverlayConnectContext *occ = cls; | ||
756 | struct LocalPeer2Context *lp2c; | ||
757 | |||
758 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
759 | GNUNET_assert (NULL != occ->timeout_task); | ||
760 | GNUNET_free (occ->emsg); | ||
761 | if (NULL == ac) | ||
762 | { | ||
763 | GNUNET_asprintf (&occ->emsg, | ||
764 | "0x%llx: Failed to connect to ATS of peer with id: %u", | ||
765 | (unsigned long long) occ->op_id, | ||
766 | occ->peer->id); | ||
767 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
768 | occ->timeout_task = | ||
769 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, | ||
770 | occ); | ||
771 | return; | ||
772 | } | ||
773 | occ->emsg = NULL; | ||
774 | |||
775 | GNUNET_asprintf (&occ->emsg, | ||
776 | "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s", | ||
777 | (unsigned long long) occ->op_id, | ||
778 | GNUNET_i2s (&occ->other_peer_identity)); | ||
779 | |||
780 | lp2c = &occ->p2ctx.local; | ||
781 | lp2c->tcc.csh = | ||
782 | GNUNET_ATS_connectivity_suggest (ac, | ||
783 | &occ->peer_identity, | ||
784 | 1); | ||
785 | } | ||
786 | |||
787 | |||
788 | /** | ||
789 | * Callback from cache with needed ATS handle set | ||
790 | * | ||
791 | * @param cls a `struct RemoteOverlayConnectCtx *` | ||
792 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
793 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
794 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
795 | * @param my_identity the identity of our peer | ||
796 | */ | ||
797 | static void | ||
798 | occ_cache_get_handle_ats_rocc_cb (void *cls, | ||
799 | struct GNUNET_CORE_Handle *ch, | ||
800 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
801 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
802 | const struct GNUNET_PeerIdentity *my_identity, | ||
803 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
804 | { | ||
805 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
806 | |||
807 | rocc->tcc.csh = | ||
808 | GNUNET_ATS_connectivity_suggest (ac, | ||
809 | &rocc->a_id, | ||
810 | 1); | ||
811 | } | ||
812 | |||
813 | |||
814 | /** | ||
815 | * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to | ||
816 | * peer 1. | ||
817 | * | ||
818 | * @param cls the OverlayConnectContext | ||
819 | */ | ||
820 | static void | ||
821 | send_hello (void *cls); | ||
822 | |||
823 | |||
824 | /** | ||
825 | * Task that is run when hello has been sent If tc->reason = | ||
826 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
827 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
828 | * | ||
829 | * @param cls the overlay connect context | ||
830 | */ | ||
831 | static void | ||
832 | occ_hello_sent_cb (void *cls) | ||
833 | { | ||
834 | struct OverlayConnectContext *occ = cls; | ||
835 | struct LocalPeer2Context *lp2c; | ||
836 | struct Peer *peer2; | ||
837 | |||
838 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
839 | GNUNET_assert (NULL != occ->timeout_task); | ||
840 | lp2c = &occ->p2ctx.local; | ||
841 | lp2c->ohh = NULL; | ||
842 | |||
843 | GNUNET_assert (NULL == occ->send_hello_task); | ||
844 | GNUNET_free (occ->emsg); | ||
845 | |||
846 | GNUNET_asprintf (&occ->emsg, | ||
847 | "0x%llx: Timeout while acquiring ATS of %s from cache", | ||
848 | (unsigned long long) occ->op_id, | ||
849 | GNUNET_i2s (&occ->other_peer_identity)); | ||
850 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
851 | lp2c->tcc.cgh_p2_ats = | ||
852 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
853 | peer2->details.local.cfg, | ||
854 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
855 | &occ_cache_get_handle_ats_occ_cb, | ||
856 | occ, NULL, NULL, NULL); | ||
857 | } | ||
858 | |||
859 | |||
860 | /** | ||
861 | * Sends the HELLO of peer1 to peer2's controller through remote overlay connect | ||
862 | * request. | ||
863 | * | ||
864 | * @param occ the overlay connect context. Its type must be either | ||
865 | * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL | ||
866 | */ | ||
867 | static void | ||
868 | send_hello_thru_rocc (struct OverlayConnectContext *occ) | ||
869 | { | ||
870 | struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; | ||
871 | char *other_peer_str; | ||
872 | uint16_t msize; | ||
873 | uint16_t hello_size; | ||
874 | |||
875 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
876 | GNUNET_assert (NULL != occ->hello); | ||
877 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
878 | LOG_DEBUG ( | ||
879 | "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n", | ||
880 | (unsigned long long) occ->op_id, | ||
881 | GNUNET_i2s (&occ->peer_identity), | ||
882 | ntohs (occ->hello->size), | ||
883 | other_peer_str); | ||
884 | GNUNET_free (other_peer_str); | ||
885 | hello_size = ntohs (occ->hello->size); | ||
886 | msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) | ||
887 | + hello_size; | ||
888 | msg = GNUNET_malloc (msize); | ||
889 | msg->header.type = | ||
890 | htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT); | ||
891 | msg->header.size = htons (msize); | ||
892 | msg->peer = htonl (occ->other_peer_id); | ||
893 | msg->operation_id = GNUNET_htonll (occ->op_id); | ||
894 | msg->peer_identity = occ->peer_identity; | ||
895 | GNUNET_memcpy (msg->hello, | ||
896 | occ->hello, | ||
897 | hello_size); | ||
898 | GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, | ||
899 | &msg->header); | ||
900 | } | ||
901 | |||
902 | |||
903 | /** | ||
904 | * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered | ||
905 | * using its TRANSPORT connection; if remote the HELLO is sent remotely by using | ||
906 | * send_hello_thru_rocc() | ||
907 | * | ||
908 | * @param cls the OverlayConnectContext | ||
909 | */ | ||
910 | static void | ||
911 | send_hello (void *cls) | ||
912 | { | ||
913 | struct OverlayConnectContext *occ = cls; | ||
914 | struct LocalPeer2Context *lp2c; | ||
915 | char *other_peer_str; | ||
916 | |||
917 | occ->send_hello_task = NULL; | ||
918 | GNUNET_assert (NULL != occ->timeout_task); | ||
919 | GNUNET_assert (NULL != occ->hello); | ||
920 | if (OCC_TYPE_LOCAL != occ->type) | ||
921 | { | ||
922 | send_hello_thru_rocc (occ); | ||
923 | return; | ||
924 | } | ||
925 | lp2c = &occ->p2ctx.local; | ||
926 | other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); | ||
927 | LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", | ||
928 | (unsigned long long) occ->op_id, | ||
929 | GNUNET_i2s (&occ->peer_identity), | ||
930 | other_peer_str); | ||
931 | GNUNET_free (other_peer_str); | ||
932 | lp2c->ohh = | ||
933 | GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg, | ||
934 | occ->hello, | ||
935 | &occ_hello_sent_cb, | ||
936 | occ); | ||
937 | if (NULL == lp2c->ohh) | ||
938 | { | ||
939 | GNUNET_break (0); | ||
940 | occ->send_hello_task = | ||
941 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
942 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
943 | 100 | ||
944 | + GNUNET_CRYPTO_random_u32 | ||
945 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
946 | &send_hello, occ); | ||
947 | } | ||
948 | } | ||
949 | |||
950 | |||
951 | /** | ||
952 | * Callback from cache with needed handles set | ||
953 | * | ||
954 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
955 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
956 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
957 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
958 | * @param ignore_ peer identity which is ignored in this callback | ||
959 | * @param cfg configuration of the peer | ||
960 | */ | ||
961 | static void | ||
962 | p2_transport_connect_cache_callback (void *cls, | ||
963 | struct GNUNET_CORE_Handle *ch, | ||
964 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
965 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
966 | const struct GNUNET_PeerIdentity *ignore_, | ||
967 | const struct | ||
968 | GNUNET_CONFIGURATION_Handle *cfg) | ||
969 | { | ||
970 | struct OverlayConnectContext *occ = cls; | ||
971 | |||
972 | GNUNET_assert (OCC_TYPE_LOCAL == occ->type); | ||
973 | if (NULL == th) | ||
974 | { | ||
975 | GNUNET_asprintf (&occ->emsg, | ||
976 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
977 | (unsigned long long) occ->op_id, | ||
978 | GNUNET_i2s (&occ->other_peer_identity)); | ||
979 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
980 | occ->timeout_task = | ||
981 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
982 | return; | ||
983 | } | ||
984 | occ->p2ctx.local.tcc.th_ = th; | ||
985 | occ->p2ctx.local.tcc.cfg = cfg; | ||
986 | GNUNET_asprintf (&occ->emsg, | ||
987 | "0x%llx: Timeout while offering HELLO to %s", | ||
988 | (unsigned long long) occ->op_id, | ||
989 | GNUNET_i2s (&occ->other_peer_identity)); | ||
990 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
991 | } | ||
992 | |||
993 | |||
994 | /** | ||
995 | * Connects to the transport of the other peer if it is a local peer and | ||
996 | * schedules the send hello task | ||
997 | * | ||
998 | * @param occ the overlay connect context | ||
999 | */ | ||
1000 | static void | ||
1001 | p2_transport_connect (struct OverlayConnectContext *occ) | ||
1002 | { | ||
1003 | struct Peer *peer2; | ||
1004 | |||
1005 | /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the | ||
1006 | HELLO! */ | ||
1007 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1008 | "Connecting to transport of peer %s to obtain HELLO\n", | ||
1009 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1010 | GNUNET_assert (NULL == occ->emsg); | ||
1011 | GNUNET_assert (NULL != occ->hello); | ||
1012 | GNUNET_assert (NULL == occ->ghh); | ||
1013 | GNUNET_assert (NULL == occ->p1th_); | ||
1014 | GNUNET_assert (NULL == occ->cgh_p1th); | ||
1015 | if (OCC_TYPE_LOCAL == occ->type) | ||
1016 | { | ||
1017 | GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); | ||
1018 | occ->p2ctx.local.tcc.cgh_p2_th = | ||
1019 | GST_connection_pool_get_handle (occ->other_peer_id, | ||
1020 | peer2->details.local.cfg, | ||
1021 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1022 | &p2_transport_connect_cache_callback, | ||
1023 | occ, NULL, NULL, NULL); | ||
1024 | return; | ||
1025 | } | ||
1026 | GNUNET_asprintf (&occ->emsg, | ||
1027 | "0x%llx: Timeout while offering HELLO to %s", | ||
1028 | (unsigned long long) occ->op_id, | ||
1029 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1030 | occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); | ||
1031 | } | ||
1032 | |||
1033 | |||
1034 | /** | ||
1035 | * Test for checking whether HELLO message is empty | ||
1036 | * | ||
1037 | * @param cls empty flag to set | ||
1038 | * @param address the HELLO | ||
1039 | * @param expiration expiration of the HELLO | ||
1040 | * @return #GNUNET_OK | ||
1041 | */ | ||
1042 | static int | ||
1043 | test_address (void *cls, | ||
1044 | const struct GNUNET_HELLO_Address *address, | ||
1045 | struct GNUNET_TIME_Absolute expiration) | ||
1046 | { | ||
1047 | int *empty = cls; | ||
1048 | |||
1049 | *empty = GNUNET_NO; | ||
1050 | return GNUNET_OK; | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /** | ||
1055 | * Function called whenever there is an update to the HELLO of peers in the | ||
1056 | * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's | ||
1057 | * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1 | ||
1058 | * | ||
1059 | * @param cls closure | ||
1060 | * @param hello our updated HELLO | ||
1061 | */ | ||
1062 | static void | ||
1063 | hello_update_cb (void *cls, | ||
1064 | const struct GNUNET_MessageHeader *hello) | ||
1065 | { | ||
1066 | struct OverlayConnectContext *occ = cls; | ||
1067 | int empty; | ||
1068 | uint16_t msize; | ||
1069 | |||
1070 | msize = ntohs (hello->size); | ||
1071 | empty = GNUNET_YES; | ||
1072 | (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) | ||
1073 | hello, GNUNET_NO, | ||
1074 | &test_address, | ||
1075 | &empty); | ||
1076 | if (GNUNET_YES == empty) | ||
1077 | { | ||
1078 | LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", | ||
1079 | (unsigned long long) occ->op_id, | ||
1080 | GNUNET_i2s (&occ->peer_identity)); | ||
1081 | return; | ||
1082 | } | ||
1083 | LOG_DEBUG ("0x%llx: Received HELLO of %s\n", | ||
1084 | (unsigned long long) occ->op_id, | ||
1085 | GNUNET_i2s (&occ->peer_identity)); | ||
1086 | occ->hello = GNUNET_malloc (msize); | ||
1087 | GST_cache_add_hello (occ->peer->id, hello); | ||
1088 | GNUNET_memcpy (occ->hello, hello, msize); | ||
1089 | GNUNET_TRANSPORT_hello_get_cancel (occ->ghh); | ||
1090 | occ->ghh = NULL; | ||
1091 | GST_connection_pool_get_handle_done (occ->cgh_p1th); | ||
1092 | occ->cgh_p1th = NULL; | ||
1093 | occ->p1th_ = NULL; | ||
1094 | GNUNET_free (occ->emsg); | ||
1095 | occ->emsg = NULL; | ||
1096 | p2_transport_connect (occ); | ||
1097 | } | ||
1098 | |||
1099 | |||
1100 | /** | ||
1101 | * Callback from cache with needed handles set | ||
1102 | * | ||
1103 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1104 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1105 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1106 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1107 | * @param ignore_ peer identity which is ignored in this callback | ||
1108 | */ | ||
1109 | static void | ||
1110 | p1_transport_connect_cache_callback (void *cls, | ||
1111 | struct GNUNET_CORE_Handle *ch, | ||
1112 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1113 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1114 | const struct GNUNET_PeerIdentity *ignore_, | ||
1115 | const struct | ||
1116 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1117 | { | ||
1118 | struct OverlayConnectContext *occ = cls; | ||
1119 | |||
1120 | GNUNET_free (occ->emsg); | ||
1121 | occ->emsg = NULL; | ||
1122 | if (NULL == th) | ||
1123 | { | ||
1124 | GNUNET_asprintf (&occ->emsg, | ||
1125 | "0x%llx: Cannot connect to TRANSPORT of %s", | ||
1126 | (unsigned long long) occ->op_id, | ||
1127 | GNUNET_i2s (&occ->peer_identity)); | ||
1128 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1129 | occ->timeout_task = | ||
1130 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1131 | return; | ||
1132 | } | ||
1133 | GNUNET_assert (NULL == occ->p1th_); | ||
1134 | GNUNET_assert (NULL != occ->cgh_p1th); | ||
1135 | occ->p1th_ = th; | ||
1136 | GNUNET_asprintf (&occ->emsg, | ||
1137 | "0x%llx: Timeout while acquiring HELLO of peer %s", | ||
1138 | (unsigned long long) occ->op_id, | ||
1139 | GNUNET_i2s (&occ->peer_identity)); | ||
1140 | occ->ghh = GNUNET_TRANSPORT_hello_get (cfg, | ||
1141 | GNUNET_TRANSPORT_AC_ANY, | ||
1142 | &hello_update_cb, | ||
1143 | occ); | ||
1144 | } | ||
1145 | |||
1146 | |||
1147 | /** | ||
1148 | * Callback from cache with needed CORE handle set | ||
1149 | * | ||
1150 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1151 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1152 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1153 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1154 | * @param my_identity the identity of our peer | ||
1155 | */ | ||
1156 | static void | ||
1157 | occ_cache_get_handle_core_cb (void *cls, | ||
1158 | struct GNUNET_CORE_Handle *ch, | ||
1159 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1160 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1161 | const struct GNUNET_PeerIdentity *my_identity, | ||
1162 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1163 | { | ||
1164 | struct OverlayConnectContext *occ = cls; | ||
1165 | const struct GNUNET_MessageHeader *hello; | ||
1166 | |||
1167 | GNUNET_assert (NULL != occ->timeout_task); | ||
1168 | GNUNET_free (occ->emsg); | ||
1169 | if ((NULL == ch) || (NULL == my_identity)) | ||
1170 | { | ||
1171 | GNUNET_asprintf (&occ->emsg, | ||
1172 | "0x%llx: Failed to connect to CORE of peer with " | ||
1173 | "id: %u", | ||
1174 | (unsigned long long) occ->op_id, | ||
1175 | occ->peer->id); | ||
1176 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1177 | occ->timeout_task = | ||
1178 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1179 | return; | ||
1180 | } | ||
1181 | occ->emsg = NULL; | ||
1182 | occ->peer_identity = *my_identity; | ||
1183 | if (NULL != | ||
1184 | GNUNET_CORE_get_mq (ch, | ||
1185 | &occ->other_peer_identity)) | ||
1186 | { | ||
1187 | LOG_DEBUG ("0x%llx: Target peer %s already connected\n", | ||
1188 | (unsigned long long) occ->op_id, | ||
1189 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1190 | LOG_DEBUG ("0x%llx: Target peer %s connected\n", | ||
1191 | (unsigned long long) occ->op_id, | ||
1192 | GNUNET_i2s (&occ->peer_identity)); | ||
1193 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1194 | occ->timeout_task = NULL; | ||
1195 | send_overlay_connect_success_msg (occ); | ||
1196 | occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); | ||
1197 | return; | ||
1198 | } | ||
1199 | LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", | ||
1200 | (unsigned long long) occ->op_id, | ||
1201 | GNUNET_i2s (&occ->peer_identity)); | ||
1202 | /* Lookup for HELLO in hello cache */ | ||
1203 | if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id))) | ||
1204 | { | ||
1205 | LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", | ||
1206 | (unsigned long long) occ->op_id, | ||
1207 | GNUNET_i2s (&occ->peer_identity)); | ||
1208 | occ->hello = GNUNET_copy_message (hello); | ||
1209 | p2_transport_connect (occ); | ||
1210 | return; | ||
1211 | } | ||
1212 | GNUNET_asprintf (&occ->emsg, | ||
1213 | "0x%llx: Timeout while acquiring TRANSPORT of %s from cache", | ||
1214 | (unsigned long long) occ->op_id, | ||
1215 | GNUNET_i2s (&occ->peer_identity)); | ||
1216 | occ->cgh_p1th = | ||
1217 | GST_connection_pool_get_handle (occ->peer->id, | ||
1218 | occ->peer->details.local.cfg, | ||
1219 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1220 | p1_transport_connect_cache_callback, | ||
1221 | occ, | ||
1222 | NULL, NULL, NULL); | ||
1223 | } | ||
1224 | |||
1225 | |||
1226 | /** | ||
1227 | * Callback to be called when forwarded get peer config operation as part of | ||
1228 | * overlay connect is successful. Connection to Peer 1's core is made and is | ||
1229 | * checked for new connection from peer 2 | ||
1230 | * | ||
1231 | * @param cls ForwardedOperationContext | ||
1232 | * @param msg the peer create success message | ||
1233 | */ | ||
1234 | static void | ||
1235 | overlay_connect_get_config (void *cls, | ||
1236 | const struct GNUNET_MessageHeader *msg) | ||
1237 | { | ||
1238 | struct OverlayConnectContext *occ = cls; | ||
1239 | struct RemotePeer2Context *rp2c; | ||
1240 | const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg; | ||
1241 | |||
1242 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1243 | rp2c = &occ->p2ctx.remote; | ||
1244 | rp2c->opc = NULL; | ||
1245 | GNUNET_assert (NULL != occ->timeout_task); | ||
1246 | if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type)) | ||
1247 | { | ||
1248 | GNUNET_SCHEDULER_cancel (occ->timeout_task); | ||
1249 | occ->timeout_task = | ||
1250 | GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); | ||
1251 | } | ||
1252 | cmsg = | ||
1253 | (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; | ||
1254 | occ->other_peer_identity = cmsg->peer_identity; | ||
1255 | GNUNET_free (occ->emsg); | ||
1256 | GNUNET_asprintf (&occ->emsg, | ||
1257 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1258 | "id: %u", | ||
1259 | (unsigned long long) occ->op_id, | ||
1260 | occ->peer->id); | ||
1261 | occ->cgh_ch = | ||
1262 | GST_connection_pool_get_handle (occ->peer->id, | ||
1263 | occ->peer->details.local.cfg, | ||
1264 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1265 | &occ_cache_get_handle_core_cb, | ||
1266 | occ, | ||
1267 | &occ->other_peer_identity, | ||
1268 | &overlay_connect_notify, | ||
1269 | occ); | ||
1270 | } | ||
1271 | |||
1272 | |||
1273 | /** | ||
1274 | * Callback which will be called after a host registration succeeded or failed | ||
1275 | * | ||
1276 | * @param cls the RegisteredHostContext | ||
1277 | * @param emsg the error message; NULL if host registration is successful | ||
1278 | */ | ||
1279 | static void | ||
1280 | host_registration_comp (void *cls, const char *emsg) | ||
1281 | { | ||
1282 | struct RegisteredHostContext *rhc = cls; | ||
1283 | |||
1284 | rhc->state = RHC_DONE; | ||
1285 | GST_process_next_focc (rhc); | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /** | ||
1290 | * Iterator to match a registered host context | ||
1291 | * | ||
1292 | * @param cls pointer 2 pointer of RegisteredHostContext | ||
1293 | * @param key current key code | ||
1294 | * @param value value in the hash map | ||
1295 | * @return #GNUNET_YES if we should continue to | ||
1296 | * iterate, | ||
1297 | * #GNUNET_NO if not. | ||
1298 | */ | ||
1299 | static int | ||
1300 | reghost_match_iterator (void *cls, | ||
1301 | const struct GNUNET_HashCode *key, | ||
1302 | void *value) | ||
1303 | { | ||
1304 | struct RegisteredHostContext **rh = cls; | ||
1305 | struct RegisteredHostContext *rh_val = value; | ||
1306 | |||
1307 | if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host)) | ||
1308 | { | ||
1309 | GNUNET_free (*rh); | ||
1310 | *rh = rh_val; | ||
1311 | return GNUNET_NO; | ||
1312 | } | ||
1313 | return GNUNET_YES; | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /** | ||
1318 | * Function to generate the hashcode corresponding to a RegisteredHostContext | ||
1319 | * | ||
1320 | * @param reg_host the host which is being registered in RegisteredHostContext | ||
1321 | * @param host the host of the controller which has to connect to the above rhost | ||
1322 | * @return the hashcode | ||
1323 | */ | ||
1324 | static struct GNUNET_HashCode | ||
1325 | hash_hosts (struct GNUNET_TESTBED_Host *reg_host, | ||
1326 | struct GNUNET_TESTBED_Host *host) | ||
1327 | { | ||
1328 | struct GNUNET_HashCode hash; | ||
1329 | uint32_t host_ids[2]; | ||
1330 | |||
1331 | host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host); | ||
1332 | host_ids[1] = GNUNET_TESTBED_host_get_id_ (host); | ||
1333 | GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash); | ||
1334 | return hash; | ||
1335 | } | ||
1336 | |||
1337 | |||
1338 | /** | ||
1339 | * Checks if the given host is registered at the given slave. | ||
1340 | * | ||
1341 | * @param slave the slave where registration has to be checked. The check is | ||
1342 | * actually done through a locally maintained hashmap. No | ||
1343 | * communication with the slave is involved. | ||
1344 | * @param host the host to register | ||
1345 | * @return If the given host is not registered already or the registration is | ||
1346 | * pending, it returns the registration context. Any overlay connects | ||
1347 | * to be forwarded should be queued in the context so that they can be | ||
1348 | * executed when the registration is completed. If the given host is | ||
1349 | * already registered, NULL is returned. | ||
1350 | */ | ||
1351 | static struct RegisteredHostContext * | ||
1352 | register_host (struct Slave *slave, | ||
1353 | struct GNUNET_TESTBED_Host *host) | ||
1354 | { | ||
1355 | struct GNUNET_HashCode hash; | ||
1356 | struct RegisteredHostContext *rhc; | ||
1357 | |||
1358 | rhc = GNUNET_new (struct RegisteredHostContext); | ||
1359 | rhc->reg_host = host; | ||
1360 | rhc->host = GST_host_list[slave->host_id]; | ||
1361 | GNUNET_assert (NULL != rhc->reg_host); | ||
1362 | GNUNET_assert (NULL != rhc->host); | ||
1363 | rhc->state = RHC_INIT; | ||
1364 | hash = hash_hosts (rhc->reg_host, rhc->host); | ||
1365 | if ((GNUNET_NO == | ||
1366 | GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, | ||
1367 | &hash)) || | ||
1368 | (GNUNET_SYSERR != | ||
1369 | GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, | ||
1370 | &hash, | ||
1371 | reghost_match_iterator, | ||
1372 | &rhc))) | ||
1373 | { | ||
1374 | /* create and add a new registered host context */ | ||
1375 | /* add the focc to its queue */ | ||
1376 | GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, | ||
1377 | &hash, | ||
1378 | rhc, | ||
1379 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1380 | GST_queue_host_registration (slave, | ||
1381 | host_registration_comp, | ||
1382 | rhc, | ||
1383 | rhc->reg_host); | ||
1384 | } | ||
1385 | else | ||
1386 | { | ||
1387 | /* rhc is now set to the existing one from the hash map by | ||
1388 | * reghost_match_iterator() */ | ||
1389 | /* if queue is empty then ignore creating focc and proceed with normal | ||
1390 | * forwarding */ | ||
1391 | if (RHC_DONE == rhc->state) | ||
1392 | return NULL; | ||
1393 | } | ||
1394 | return rhc; | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | /** | ||
1399 | * Forwards the overlay connect request to a slave controller. Before | ||
1400 | * forwarding, any hosts which are needed to be known by the slave controller to | ||
1401 | * execute the overlay connect request are registered at slave. | ||
1402 | * | ||
1403 | * @param msg the overlay connect request message to be forwarded | ||
1404 | * @param client the client to which the status of the forwarded request has to | ||
1405 | * be notified | ||
1406 | */ | ||
1407 | static void | ||
1408 | forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, | ||
1409 | struct GNUNET_SERVICE_Client *client) | ||
1410 | { | ||
1411 | struct ForwardedOperationContext *fopc; | ||
1412 | struct Route *route_to_peer2_host; | ||
1413 | struct Route *route_to_peer1_host; | ||
1414 | struct Peer *peer; | ||
1415 | struct RegisteredHostContext *rhc; | ||
1416 | struct ForwardedOverlayConnectContext *focc; | ||
1417 | uint64_t op_id; | ||
1418 | uint32_t peer2_host_id; | ||
1419 | uint32_t p1; | ||
1420 | uint32_t p2; | ||
1421 | |||
1422 | p1 = ntohl (msg->peer1); | ||
1423 | p2 = ntohl (msg->peer2); | ||
1424 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1425 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1426 | GNUNET_assert (VALID_PEER_ID (p1)); | ||
1427 | GNUNET_assert (VALID_HOST_ID (peer2_host_id)); | ||
1428 | peer = GST_peer_list[p1]; | ||
1429 | GNUNET_assert (GNUNET_YES == peer->is_remote); | ||
1430 | LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", | ||
1431 | (unsigned long long) op_id); | ||
1432 | route_to_peer2_host = GST_find_dest_route (peer2_host_id); | ||
1433 | route_to_peer1_host = GST_find_dest_route | ||
1434 | (peer->details.remote.remote_host_id); | ||
1435 | GNUNET_assert (NULL != route_to_peer1_host); | ||
1436 | if ((NULL != route_to_peer2_host) && | ||
1437 | (route_to_peer1_host->dest == route_to_peer2_host->dest)) | ||
1438 | goto forward; | ||
1439 | /* Peer2 is either with us OR peer1 and peer2 can be reached through | ||
1440 | different subtrees OR peer2 is on a subtree unknown to us */ | ||
1441 | if (NULL != (rhc = register_host (peer->details.remote.slave, | ||
1442 | GST_host_list[peer2_host_id]))) | ||
1443 | { | ||
1444 | LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, | ||
1445 | p2); | ||
1446 | focc = GNUNET_new (struct ForwardedOverlayConnectContext); | ||
1447 | focc->rhc = rhc; | ||
1448 | focc->peer1 = p1; | ||
1449 | focc->peer2 = p2; | ||
1450 | focc->peer2_host_id = peer2_host_id; | ||
1451 | focc->orig_msg = GNUNET_copy_message (&msg->header); | ||
1452 | focc->operation_id = op_id; | ||
1453 | focc->client = client; | ||
1454 | GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, | ||
1455 | rhc->focc_dll_tail, | ||
1456 | focc); | ||
1457 | return; | ||
1458 | } | ||
1459 | |||
1460 | forward: | ||
1461 | LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, | ||
1462 | p2); | ||
1463 | fopc = GNUNET_new (struct ForwardedOperationContext); | ||
1464 | fopc->client = client; | ||
1465 | fopc->operation_id = op_id; | ||
1466 | fopc->type = OP_OVERLAY_CONNECT; | ||
1467 | fopc->opc = | ||
1468 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1469 | slave->controller, op_id, | ||
1470 | &msg->header, | ||
1471 | &GST_forwarded_operation_reply_relay, | ||
1472 | fopc); | ||
1473 | fopc->timeout_task = | ||
1474 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1475 | &GST_forwarded_operation_timeout, | ||
1476 | fopc); | ||
1477 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, | ||
1478 | fopcq_tail, | ||
1479 | fopc); | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | /** | ||
1484 | * Callback called when a connection to the controller of peer2 has been | ||
1485 | * established | ||
1486 | * | ||
1487 | * @param cls the overlay connect contexts | ||
1488 | * @param c handle to the controller connection | ||
1489 | */ | ||
1490 | static void | ||
1491 | p2_controller_connect_cb (void *cls, | ||
1492 | struct GNUNET_TESTBED_Controller *c) | ||
1493 | { | ||
1494 | struct OverlayConnectContext *occ = cls; | ||
1495 | struct RemotePeer2Context *rp2c; | ||
1496 | struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg; | ||
1497 | |||
1498 | GNUNET_assert (OCC_TYPE_LOCAL != occ->type); | ||
1499 | rp2c = &occ->p2ctx.remote; | ||
1500 | rp2c->ncn = NULL; | ||
1501 | rp2c->p2c = c; | ||
1502 | cmsg.header.size = | ||
1503 | htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage)); | ||
1504 | cmsg.header.type = | ||
1505 | htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); | ||
1506 | cmsg.peer_id = htonl (occ->other_peer_id); | ||
1507 | cmsg.operation_id = GNUNET_htonll (occ->op_id); | ||
1508 | rp2c->opc = | ||
1509 | GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, | ||
1510 | occ->op_id, | ||
1511 | &cmsg.header, | ||
1512 | &overlay_connect_get_config, | ||
1513 | occ); | ||
1514 | GNUNET_free (occ->emsg); | ||
1515 | GNUNET_asprintf (&occ->emsg, | ||
1516 | "0x%llx: Timeout while getting peer identity of peer " | ||
1517 | "with id: %u", | ||
1518 | (unsigned long long) occ->op_id, | ||
1519 | occ->other_peer_id); | ||
1520 | } | ||
1521 | |||
1522 | |||
1523 | /** | ||
1524 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages | ||
1525 | * | ||
1526 | * @param cls identification of the client | ||
1527 | * @param msg the actual message | ||
1528 | */ | ||
1529 | void | ||
1530 | handle_overlay_connect (void *cls, | ||
1531 | const struct GNUNET_TESTBED_OverlayConnectMessage *msg) | ||
1532 | { | ||
1533 | struct GNUNET_SERVICE_Client *client = cls; | ||
1534 | struct Peer *peer; | ||
1535 | struct Peer *peer2; | ||
1536 | struct OverlayConnectContext *occ; | ||
1537 | struct Neighbour *p2n; | ||
1538 | uint64_t operation_id; | ||
1539 | uint32_t p1; | ||
1540 | uint32_t p2; | ||
1541 | uint32_t peer2_host_id; | ||
1542 | |||
1543 | p1 = ntohl (msg->peer1); | ||
1544 | p2 = ntohl (msg->peer2); | ||
1545 | if (p1 == p2) | ||
1546 | { | ||
1547 | GNUNET_break (0); | ||
1548 | GNUNET_SERVICE_client_drop (client); | ||
1549 | return; | ||
1550 | } | ||
1551 | if (! VALID_PEER_ID (p1)) | ||
1552 | { | ||
1553 | GNUNET_break (0); | ||
1554 | GNUNET_SERVICE_client_drop (client); | ||
1555 | return; | ||
1556 | } | ||
1557 | peer = GST_peer_list[p1]; | ||
1558 | operation_id = GNUNET_ntohll (msg->operation_id); | ||
1559 | LOG_DEBUG | ||
1560 | ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", | ||
1561 | p1, | ||
1562 | p2, | ||
1563 | (unsigned long long) operation_id); | ||
1564 | peer2_host_id = ntohl (msg->peer2_host_id); | ||
1565 | if (GNUNET_YES == peer->is_remote) | ||
1566 | { | ||
1567 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1568 | { | ||
1569 | GNUNET_break (0); | ||
1570 | GNUNET_SERVICE_client_drop (client); | ||
1571 | return; | ||
1572 | } | ||
1573 | forward_overlay_connect (msg, client); | ||
1574 | GNUNET_SERVICE_client_continue (client); | ||
1575 | return; | ||
1576 | } | ||
1577 | p2n = NULL; | ||
1578 | occ = GNUNET_new (struct OverlayConnectContext); | ||
1579 | occ->type = OCC_TYPE_LOCAL; | ||
1580 | if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ | ||
1581 | { | ||
1582 | if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) | ||
1583 | { | ||
1584 | if (! VALID_HOST_ID (peer2_host_id)) | ||
1585 | { | ||
1586 | GNUNET_break (0); | ||
1587 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1588 | "0x%llx: Peer %u's host not in our neighbours list\n", | ||
1589 | (unsigned long long) operation_id, p2); | ||
1590 | GNUNET_SERVICE_client_drop (client); | ||
1591 | GNUNET_free (occ); | ||
1592 | return; | ||
1593 | } | ||
1594 | p2n = GST_create_neighbour (GST_host_list[peer2_host_id]); | ||
1595 | } | ||
1596 | occ->type = OCC_TYPE_REMOTE_LATERAL; | ||
1597 | occ->p2ctx.remote.p2n = p2n; | ||
1598 | } | ||
1599 | else if (GNUNET_YES == GST_peer_list[p2]->is_remote) | ||
1600 | { | ||
1601 | occ->type = OCC_TYPE_REMOTE_SLAVE; | ||
1602 | occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller; | ||
1603 | } | ||
1604 | GNUNET_CONTAINER_DLL_insert_tail (occq_head, | ||
1605 | occq_tail, | ||
1606 | occ); | ||
1607 | occ->client = client; | ||
1608 | occ->other_peer_id = p2; | ||
1609 | GST_peer_list[p1]->reference_cnt++; | ||
1610 | occ->peer = GST_peer_list[p1]; | ||
1611 | occ->op_id = operation_id; | ||
1612 | GNUNET_assert (NULL == occ->timeout_task); | ||
1613 | occ->timeout_task = | ||
1614 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1615 | &timeout_overlay_connect, | ||
1616 | occ); | ||
1617 | switch (occ->type) | ||
1618 | { | ||
1619 | case OCC_TYPE_REMOTE_LATERAL: | ||
1620 | GNUNET_asprintf (&occ->emsg, | ||
1621 | "0x%llx: Timeout while acquiring connection to peer %u's " | ||
1622 | "host: %u\n", | ||
1623 | (unsigned long long) occ->op_id, | ||
1624 | occ->other_peer_id, | ||
1625 | peer2_host_id); | ||
1626 | occ->p2ctx.remote.ncn | ||
1627 | = GST_neighbour_get_connection (p2n, | ||
1628 | &p2_controller_connect_cb, | ||
1629 | occ); | ||
1630 | break; | ||
1631 | case OCC_TYPE_REMOTE_SLAVE: | ||
1632 | p2_controller_connect_cb (occ, | ||
1633 | occ->p2ctx.remote.p2c); | ||
1634 | break; | ||
1635 | case OCC_TYPE_LOCAL: | ||
1636 | peer2 = GST_peer_list[occ->other_peer_id]; | ||
1637 | peer2->reference_cnt++; | ||
1638 | GNUNET_TESTING_peer_get_identity (peer2->details.local.peer, | ||
1639 | &occ->other_peer_identity); | ||
1640 | GNUNET_asprintf (&occ->emsg, | ||
1641 | "0x%llx: Timeout while connecting to CORE of peer with " | ||
1642 | "id: %u", | ||
1643 | (unsigned long long) occ->op_id, | ||
1644 | occ->peer->id); | ||
1645 | LOG_DEBUG ("Peer %u has PID %s\n", | ||
1646 | occ->other_peer_id, | ||
1647 | GNUNET_i2s (&occ->other_peer_identity)); | ||
1648 | { | ||
1649 | struct GNUNET_PeerIdentity lpid; | ||
1650 | |||
1651 | GNUNET_TESTING_peer_get_identity (peer->details.local.peer, | ||
1652 | &lpid); | ||
1653 | LOG_DEBUG ("Peer %u has PID %s\n", | ||
1654 | p1, | ||
1655 | GNUNET_i2s (&lpid)); | ||
1656 | } | ||
1657 | occ->cgh_ch = | ||
1658 | GST_connection_pool_get_handle (occ->peer->id, | ||
1659 | occ->peer->details.local.cfg, | ||
1660 | GST_CONNECTIONPOOL_SERVICE_CORE, | ||
1661 | &occ_cache_get_handle_core_cb, occ, | ||
1662 | &occ->other_peer_identity, | ||
1663 | &overlay_connect_notify, occ); | ||
1664 | break; | ||
1665 | } | ||
1666 | GNUNET_SERVICE_client_continue (client); | ||
1667 | } | ||
1668 | |||
1669 | |||
1670 | /** | ||
1671 | * Function to cleanup RemoteOverlayConnectCtx and any associated tasks | ||
1672 | * with it | ||
1673 | * | ||
1674 | * @param rocc the RemoteOverlayConnectCtx | ||
1675 | */ | ||
1676 | static void | ||
1677 | cleanup_rocc (struct RemoteOverlayConnectCtx *rocc) | ||
1678 | { | ||
1679 | LOG_DEBUG ("0x%llx: Cleaning up rocc\n", | ||
1680 | (unsigned long long) rocc->op_id); | ||
1681 | if (NULL != rocc->attempt_connect_task_id) | ||
1682 | GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id); | ||
1683 | if (NULL != rocc->timeout_rocc_task_id) | ||
1684 | GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id); | ||
1685 | if (NULL != rocc->ohh) | ||
1686 | GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh); | ||
1687 | if (NULL != rocc->tcc.csh) | ||
1688 | GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh); | ||
1689 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th); | ||
1690 | GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats); | ||
1691 | GNUNET_assert (rocc->peer->reference_cnt > 0); | ||
1692 | rocc->peer->reference_cnt--; | ||
1693 | if ((GNUNET_YES == rocc->peer->destroy_flag) && | ||
1694 | (0 == rocc->peer->reference_cnt)) | ||
1695 | GST_destroy_peer (rocc->peer); | ||
1696 | GNUNET_free (rocc->hello); | ||
1697 | GNUNET_CONTAINER_DLL_remove (roccq_head, | ||
1698 | roccq_tail, | ||
1699 | rocc); | ||
1700 | GNUNET_free (rocc); | ||
1701 | } | ||
1702 | |||
1703 | |||
1704 | /** | ||
1705 | * Task to timeout rocc and cleanit up | ||
1706 | * | ||
1707 | * @param cls the RemoteOverlayConnectCtx | ||
1708 | */ | ||
1709 | static void | ||
1710 | timeout_rocc_task (void *cls) | ||
1711 | { | ||
1712 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1713 | |||
1714 | GNUNET_assert (rocc->timeout_rocc_task_id != NULL); | ||
1715 | rocc->timeout_rocc_task_id = NULL; | ||
1716 | LOG_DEBUG ("0x%llx: rocc timed out\n", | ||
1717 | (unsigned long long) rocc->op_id); | ||
1718 | cleanup_rocc (rocc); | ||
1719 | } | ||
1720 | |||
1721 | |||
1722 | /** | ||
1723 | * Function called to notify transport users that another | ||
1724 | * peer connected to us. | ||
1725 | * | ||
1726 | * @param cls the RemoteOverlayConnectContext | ||
1727 | * @param new_peer the peer that connected | ||
1728 | */ | ||
1729 | static void | ||
1730 | cache_transport_peer_connect_notify (void *cls, | ||
1731 | const struct GNUNET_PeerIdentity *new_peer) | ||
1732 | { | ||
1733 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1734 | |||
1735 | LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", | ||
1736 | (unsigned long long) rocc->op_id); | ||
1737 | GNUNET_assert (0 == | ||
1738 | memcmp (new_peer, &rocc->a_id, | ||
1739 | sizeof(struct GNUNET_PeerIdentity))); | ||
1740 | LOG_DEBUG ("0x%llx: Peer %s connected\n", | ||
1741 | (unsigned long long) rocc->op_id, | ||
1742 | GNUNET_i2s (&rocc->a_id)); | ||
1743 | cleanup_rocc (rocc); | ||
1744 | } | ||
1745 | |||
1746 | |||
1747 | /** | ||
1748 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1749 | * whose identity is in RemoteOverlayConnectCtx | ||
1750 | * | ||
1751 | * @param cls the RemoteOverlayConnectCtx | ||
1752 | */ | ||
1753 | static void | ||
1754 | attempt_connect_task (void *cls); | ||
1755 | |||
1756 | |||
1757 | /** | ||
1758 | * Task that is run when hello has been sent If tc->reason = | ||
1759 | * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if | ||
1760 | * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded | ||
1761 | * | ||
1762 | * @param cls the overlay connect context | ||
1763 | */ | ||
1764 | static void | ||
1765 | rocc_hello_sent_cb (void *cls) | ||
1766 | { | ||
1767 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1768 | |||
1769 | rocc->ohh = NULL; | ||
1770 | GNUNET_assert (NULL == rocc->attempt_connect_task_id); | ||
1771 | LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n", | ||
1772 | (unsigned long long) rocc->op_id, | ||
1773 | GNUNET_i2s (&rocc->a_id), | ||
1774 | rocc->peer->id); | ||
1775 | rocc->tcc.cgh_p2_ats = | ||
1776 | GST_connection_pool_get_handle (rocc->peer->id, | ||
1777 | rocc->peer->details.local.cfg, | ||
1778 | GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY, | ||
1779 | &occ_cache_get_handle_ats_rocc_cb, | ||
1780 | rocc, NULL, NULL, NULL); | ||
1781 | } | ||
1782 | |||
1783 | |||
1784 | /** | ||
1785 | * Task to offer the HELLO message to the peer and ask it to connect to the peer | ||
1786 | * whose identity is in RemoteOverlayConnectCtx | ||
1787 | * | ||
1788 | * @param cls the RemoteOverlayConnectCtx | ||
1789 | */ | ||
1790 | static void | ||
1791 | attempt_connect_task (void *cls) | ||
1792 | { | ||
1793 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1794 | |||
1795 | GNUNET_assert (NULL != rocc->attempt_connect_task_id); | ||
1796 | rocc->attempt_connect_task_id = NULL; | ||
1797 | LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n", | ||
1798 | (unsigned long long) rocc->op_id, | ||
1799 | GNUNET_i2s (&rocc->a_id), | ||
1800 | rocc->peer->id); | ||
1801 | rocc->ohh = | ||
1802 | GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg, | ||
1803 | rocc->hello, | ||
1804 | &rocc_hello_sent_cb, | ||
1805 | rocc); | ||
1806 | if (NULL == rocc->ohh) | ||
1807 | rocc->attempt_connect_task_id = | ||
1808 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1809 | (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1810 | 100 | ||
1811 | + GNUNET_CRYPTO_random_u32 | ||
1812 | (GNUNET_CRYPTO_QUALITY_WEAK, 500)), | ||
1813 | &attempt_connect_task, rocc); | ||
1814 | } | ||
1815 | |||
1816 | |||
1817 | /** | ||
1818 | * Callback from cache with needed handles set | ||
1819 | * | ||
1820 | * @param cls the closure passed to GST_cache_get_handle_transport() | ||
1821 | * @param ch the handle to CORE. Can be NULL if it is not requested | ||
1822 | * @param th the handle to TRANSPORT. Can be NULL if it is not requested | ||
1823 | * @param ac the handle to ATS. Can be NULL if it is not requested | ||
1824 | * @param ignore_ peer identity which is ignored in this callback | ||
1825 | */ | ||
1826 | static void | ||
1827 | rocc_cache_get_handle_transport_cb (void *cls, | ||
1828 | struct GNUNET_CORE_Handle *ch, | ||
1829 | struct GNUNET_TRANSPORT_CoreHandle *th, | ||
1830 | struct GNUNET_ATS_ConnectivityHandle *ac, | ||
1831 | const struct GNUNET_PeerIdentity *ignore_, | ||
1832 | const struct | ||
1833 | GNUNET_CONFIGURATION_Handle *cfg) | ||
1834 | { | ||
1835 | struct RemoteOverlayConnectCtx *rocc = cls; | ||
1836 | |||
1837 | if (NULL == th) | ||
1838 | { | ||
1839 | rocc->timeout_rocc_task_id = | ||
1840 | GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc); | ||
1841 | return; | ||
1842 | } | ||
1843 | rocc->tcc.th_ = th; | ||
1844 | rocc->tcc.cfg = cfg; | ||
1845 | if (NULL != | ||
1846 | GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_, | ||
1847 | &rocc->a_id)) | ||
1848 | { | ||
1849 | LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n", | ||
1850 | (unsigned long long) rocc->op_id, | ||
1851 | GNUNET_i2s (&rocc->a_id), | ||
1852 | rocc->peer->id); | ||
1853 | cleanup_rocc (rocc); | ||
1854 | return; | ||
1855 | } | ||
1856 | rocc->attempt_connect_task_id = | ||
1857 | GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); | ||
1858 | } | ||
1859 | |||
1860 | |||
1861 | /** | ||
1862 | * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1863 | * | ||
1864 | * @param cls identification of the client | ||
1865 | * @param msg the actual message | ||
1866 | * @return #GNUNET_OK if @a msg is well-formed | ||
1867 | */ | ||
1868 | int | ||
1869 | check_remote_overlay_connect (void *cls, | ||
1870 | const struct | ||
1871 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1872 | { | ||
1873 | uint32_t peer_id; | ||
1874 | uint16_t msize; | ||
1875 | uint16_t hsize; | ||
1876 | |||
1877 | msize = ntohs (msg->header.size); | ||
1878 | if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)) | ||
1879 | { | ||
1880 | GNUNET_break (0); | ||
1881 | return GNUNET_SYSERR; | ||
1882 | } | ||
1883 | hsize = ntohs (msg->hello->size); | ||
1884 | if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != | ||
1885 | msize) | ||
1886 | { | ||
1887 | GNUNET_break (0); | ||
1888 | return GNUNET_SYSERR; | ||
1889 | } | ||
1890 | peer_id = ntohl (msg->peer); | ||
1891 | if ((peer_id >= GST_peer_list_size) || | ||
1892 | (NULL == GST_peer_list[peer_id])) | ||
1893 | { | ||
1894 | GNUNET_break_op (0); | ||
1895 | return GNUNET_SYSERR; | ||
1896 | } | ||
1897 | return GNUNET_OK; | ||
1898 | } | ||
1899 | |||
1900 | |||
1901 | /** | ||
1902 | * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages | ||
1903 | * | ||
1904 | * @param cls identification of the client | ||
1905 | * @param msg the actual message | ||
1906 | */ | ||
1907 | void | ||
1908 | handle_remote_overlay_connect (void *cls, | ||
1909 | const struct | ||
1910 | GNUNET_TESTBED_RemoteOverlayConnectMessage *msg) | ||
1911 | { | ||
1912 | struct GNUNET_SERVICE_Client *client = cls; | ||
1913 | struct RemoteOverlayConnectCtx *rocc; | ||
1914 | struct Peer *peer; | ||
1915 | struct GNUNET_PeerIdentity pid; | ||
1916 | static char pid_str[16]; | ||
1917 | uint32_t peer_id; | ||
1918 | uint16_t hsize; | ||
1919 | |||
1920 | hsize = ntohs (msg->hello->size); | ||
1921 | peer_id = ntohl (msg->peer); | ||
1922 | peer = GST_peer_list[peer_id]; | ||
1923 | if (GNUNET_YES == peer->is_remote) | ||
1924 | { | ||
1925 | struct GNUNET_MessageHeader *msg2; | ||
1926 | |||
1927 | msg2 = GNUNET_copy_message (&msg->header); | ||
1928 | GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, | ||
1929 | msg2); | ||
1930 | GNUNET_SERVICE_client_continue (client); | ||
1931 | return; | ||
1932 | } | ||
1933 | rocc = GNUNET_new (struct RemoteOverlayConnectCtx); | ||
1934 | rocc->op_id = GNUNET_ntohll (msg->operation_id); | ||
1935 | GNUNET_CONTAINER_DLL_insert_tail (roccq_head, | ||
1936 | roccq_tail, | ||
1937 | rocc); | ||
1938 | rocc->a_id = msg->peer_identity; | ||
1939 | GNUNET_TESTING_peer_get_identity (peer->details.local.peer, | ||
1940 | &pid); | ||
1941 | (void) GNUNET_strlcpy (pid_str, | ||
1942 | GNUNET_i2s (&pid), | ||
1943 | sizeof(pid_str)); | ||
1944 | LOG_DEBUG ( | ||
1945 | "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n", | ||
1946 | (unsigned long long) rocc->op_id, | ||
1947 | pid_str, | ||
1948 | GNUNET_i2s (&rocc->a_id), | ||
1949 | hsize); | ||
1950 | rocc->peer = peer; | ||
1951 | rocc->peer->reference_cnt++; | ||
1952 | rocc->hello = GNUNET_malloc (hsize); | ||
1953 | GNUNET_memcpy (rocc->hello, | ||
1954 | msg->hello, | ||
1955 | hsize); | ||
1956 | rocc->tcc.cgh_p2_th = | ||
1957 | GST_connection_pool_get_handle (peer_id, | ||
1958 | rocc->peer->details.local.cfg, | ||
1959 | GST_CONNECTIONPOOL_SERVICE_TRANSPORT, | ||
1960 | &rocc_cache_get_handle_transport_cb, | ||
1961 | rocc, | ||
1962 | &rocc->a_id, | ||
1963 | &cache_transport_peer_connect_notify, | ||
1964 | rocc); | ||
1965 | rocc->timeout_rocc_task_id = | ||
1966 | GNUNET_SCHEDULER_add_delayed (GST_timeout, | ||
1967 | &timeout_rocc_task, | ||
1968 | rocc); | ||
1969 | GNUNET_SERVICE_client_continue (client); | ||
1970 | } | ||
1971 | |||
1972 | |||
1973 | /** | ||
1974 | * Clears all pending overlay connect contexts in queue | ||
1975 | */ | ||
1976 | void | ||
1977 | GST_free_occq () | ||
1978 | { | ||
1979 | struct OverlayConnectContext *occ; | ||
1980 | |||
1981 | while (NULL != (occ = occq_head)) | ||
1982 | cleanup_occ (occ); | ||
1983 | } | ||
1984 | |||
1985 | |||
1986 | /** | ||
1987 | * Clears all pending remote overlay connect contexts in queue | ||
1988 | */ | ||
1989 | void | ||
1990 | GST_free_roccq () | ||
1991 | { | ||
1992 | struct RemoteOverlayConnectCtx *rocc; | ||
1993 | |||
1994 | while (NULL != (rocc = roccq_head)) | ||
1995 | cleanup_rocc (rocc); | ||
1996 | } | ||