diff options
Diffstat (limited to 'src/dv/plugin_transport_dv.c')
-rw-r--r-- | src/dv/plugin_transport_dv.c | 910 |
1 files changed, 0 insertions, 910 deletions
diff --git a/src/dv/plugin_transport_dv.c b/src/dv/plugin_transport_dv.c deleted file mode 100644 index a99c170d7..000000000 --- a/src/dv/plugin_transport_dv.c +++ /dev/null | |||
@@ -1,910 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2002--2014 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 dv/plugin_transport_dv.c | ||
23 | * @brief DV transport service, takes incoming DV requests and deals with | ||
24 | * the DV service | ||
25 | * @author Nathan Evans | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_statistics_service.h" | ||
32 | #include "gnunet_dv_service.h" | ||
33 | #include "gnunet_transport_service.h" | ||
34 | #include "gnunet_transport_plugin.h" | ||
35 | #include "dv.h" | ||
36 | |||
37 | |||
38 | #define LOG(kind,...) GNUNET_log_from (kind, "transport-dv",__VA_ARGS__) | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Encapsulation of all of the state of the plugin. | ||
43 | */ | ||
44 | struct Plugin; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Session handle for connections. | ||
49 | */ | ||
50 | struct GNUNET_ATS_Session | ||
51 | { | ||
52 | /** | ||
53 | * Pointer to the global plugin struct. | ||
54 | */ | ||
55 | struct Plugin *plugin; | ||
56 | |||
57 | /** | ||
58 | * Address we use for the other peer. | ||
59 | */ | ||
60 | struct GNUNET_HELLO_Address *address; | ||
61 | |||
62 | /** | ||
63 | * To whom are we talking to. | ||
64 | */ | ||
65 | struct GNUNET_PeerIdentity sender; | ||
66 | |||
67 | /** | ||
68 | * Number of bytes waiting for transmission to this peer. | ||
69 | * FIXME: not set yet. | ||
70 | */ | ||
71 | unsigned long long bytes_in_queue; | ||
72 | |||
73 | /** | ||
74 | * Number of messages waiting for transmission to this peer. | ||
75 | * FIXME: not set yet. | ||
76 | */ | ||
77 | unsigned int msgs_in_queue; | ||
78 | |||
79 | /** | ||
80 | * Current distance to the given peer. | ||
81 | */ | ||
82 | uint32_t distance; | ||
83 | |||
84 | /** | ||
85 | * Current network the next hop peer is located in | ||
86 | */ | ||
87 | enum GNUNET_NetworkType network; | ||
88 | |||
89 | /** | ||
90 | * Does the transport service know about this session (and we thus | ||
91 | * need to call `session_end` when it is released?) | ||
92 | */ | ||
93 | int active; | ||
94 | |||
95 | }; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Encapsulation of all of the state of the plugin. | ||
100 | */ | ||
101 | struct Plugin | ||
102 | { | ||
103 | /** | ||
104 | * Our environment. | ||
105 | */ | ||
106 | struct GNUNET_TRANSPORT_PluginEnvironment *env; | ||
107 | |||
108 | /** | ||
109 | * Hash map of sessions (active and inactive). | ||
110 | */ | ||
111 | struct GNUNET_CONTAINER_MultiPeerMap *sessions; | ||
112 | |||
113 | /** | ||
114 | * Copy of the handler array where the closures are | ||
115 | * set to this struct's instance. | ||
116 | */ | ||
117 | struct GNUNET_SERVER_MessageHandler *handlers; | ||
118 | |||
119 | /** | ||
120 | * Handle to the DV service | ||
121 | */ | ||
122 | struct GNUNET_DV_ServiceHandle *dvh; | ||
123 | |||
124 | /** | ||
125 | * Tokenizer for boxed messages. | ||
126 | */ | ||
127 | struct GNUNET_SERVER_MessageStreamTokenizer *mst; | ||
128 | |||
129 | /** | ||
130 | * Function to call about session status changes. | ||
131 | */ | ||
132 | GNUNET_TRANSPORT_SessionInfoCallback sic; | ||
133 | |||
134 | /** | ||
135 | * Closure for @e sic. | ||
136 | */ | ||
137 | void *sic_cls; | ||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * If a session monitor is attached, notify it about the new | ||
143 | * session state. | ||
144 | * | ||
145 | * @param plugin our plugin | ||
146 | * @param session session that changed state | ||
147 | * @param state new state of the session | ||
148 | */ | ||
149 | static void | ||
150 | notify_session_monitor (struct Plugin *plugin, | ||
151 | struct GNUNET_ATS_Session *session, | ||
152 | enum GNUNET_TRANSPORT_SessionState state) | ||
153 | { | ||
154 | struct GNUNET_TRANSPORT_SessionInfo info; | ||
155 | |||
156 | if (NULL == plugin->sic) | ||
157 | return; | ||
158 | memset (&info, 0, sizeof (info)); | ||
159 | info.state = state; | ||
160 | info.is_inbound = GNUNET_SYSERR; /* hard to say */ | ||
161 | info.num_msg_pending = session->msgs_in_queue; | ||
162 | info.num_bytes_pending = session->bytes_in_queue; | ||
163 | /* info.receive_delay remains zero as this is not supported by DV | ||
164 | (cannot selectively not receive from 'core') */ | ||
165 | info.session_timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
166 | info.address = session->address; | ||
167 | plugin->sic (plugin->sic_cls, | ||
168 | session, | ||
169 | &info); | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Notify transport service about the change in distance. | ||
175 | * | ||
176 | * @param session session where the distance changed | ||
177 | */ | ||
178 | static void | ||
179 | notify_distance_change (struct GNUNET_ATS_Session *session) | ||
180 | { | ||
181 | struct Plugin *plugin = session->plugin; | ||
182 | |||
183 | if (GNUNET_YES != session->active) | ||
184 | return; | ||
185 | plugin->env->update_address_distance (plugin->env->cls, | ||
186 | session->address, | ||
187 | session->distance); | ||
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Function called by MST on each message from the box. | ||
193 | * | ||
194 | * @param cls closure with the `struct Plugin *` | ||
195 | * @param client identification of the client (with the 'struct GNUNET_ATS_Session') | ||
196 | * @param message the actual message | ||
197 | * @return #GNUNET_OK on success | ||
198 | */ | ||
199 | static int | ||
200 | unbox_cb (void *cls, | ||
201 | void *client, | ||
202 | const struct GNUNET_MessageHeader *message) | ||
203 | { | ||
204 | struct Plugin *plugin = cls; | ||
205 | struct GNUNET_ATS_Session *session = client; | ||
206 | |||
207 | session->active = GNUNET_YES; | ||
208 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
209 | "Delivering message of type %u with %u bytes from peer `%s'\n", | ||
210 | ntohs (message->type), | ||
211 | ntohs (message->size), | ||
212 | GNUNET_i2s (&session->sender)); | ||
213 | plugin->env->receive (plugin->env->cls, | ||
214 | session->address, | ||
215 | session, | ||
216 | message); | ||
217 | plugin->env->update_address_distance (plugin->env->cls, | ||
218 | session->address, | ||
219 | session->distance); | ||
220 | return GNUNET_OK; | ||
221 | } | ||
222 | |||
223 | |||
224 | /** | ||
225 | * Handler for messages received from the DV service. | ||
226 | * | ||
227 | * @param cls closure with the plugin | ||
228 | * @param sender sender of the message | ||
229 | * @param distance how far did the message travel | ||
230 | * @param msg actual message payload | ||
231 | */ | ||
232 | static void | ||
233 | handle_dv_message_received (void *cls, | ||
234 | const struct GNUNET_PeerIdentity *sender, | ||
235 | uint32_t distance, | ||
236 | const struct GNUNET_MessageHeader *msg) | ||
237 | { | ||
238 | struct Plugin *plugin = cls; | ||
239 | struct GNUNET_ATS_Session *session; | ||
240 | |||
241 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Received DV_MESSAGE_RECEIVED message for peer `%s': new distance %u\n", | ||
243 | GNUNET_i2s (sender), | ||
244 | distance); | ||
245 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
246 | sender); | ||
247 | if (NULL == session) | ||
248 | { | ||
249 | GNUNET_break (0); | ||
250 | return; | ||
251 | } | ||
252 | if (GNUNET_MESSAGE_TYPE_DV_BOX == ntohs (msg->type)) | ||
253 | { | ||
254 | /* need to unbox using MST */ | ||
255 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
256 | "Unboxing DV message using MST\n"); | ||
257 | GNUNET_SERVER_mst_receive (plugin->mst, | ||
258 | session, | ||
259 | (const char *) &msg[1], | ||
260 | ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader), | ||
261 | GNUNET_YES, | ||
262 | GNUNET_NO); | ||
263 | return; | ||
264 | } | ||
265 | session->active = GNUNET_YES; | ||
266 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
267 | "Delivering message of type %u with %u bytes from peer `%s'\n", | ||
268 | ntohs (msg->type), | ||
269 | ntohs (msg->size), | ||
270 | GNUNET_i2s (sender)); | ||
271 | plugin->env->receive (plugin->env->cls, | ||
272 | session->address, | ||
273 | session, | ||
274 | msg); | ||
275 | plugin->env->update_address_distance (plugin->env->cls, | ||
276 | session->address, | ||
277 | session->distance); | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Function called if DV starts to be able to talk to a peer. | ||
283 | * | ||
284 | * @param cls closure with `struct Plugin *` | ||
285 | * @param peer newly connected peer | ||
286 | * @param distance distance to the peer | ||
287 | * @param network the network the next hop is located in | ||
288 | */ | ||
289 | static void | ||
290 | handle_dv_connect (void *cls, | ||
291 | const struct GNUNET_PeerIdentity *peer, | ||
292 | uint32_t distance, | ||
293 | enum GNUNET_NetworkType network) | ||
294 | { | ||
295 | struct Plugin *plugin = cls; | ||
296 | struct GNUNET_ATS_Session *session; | ||
297 | |||
298 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
299 | /** | ||
300 | * This requires transport plugin to be linked to libgnunetats. | ||
301 | * If you remove it, also remove libgnunetats linkage from Makefile.am | ||
302 | */ | ||
303 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
304 | "Received DV_CONNECT message for peer `%s' with next hop in network %s\n", | ||
305 | GNUNET_i2s (peer), | ||
306 | GNUNET_NT_to_string (network)); | ||
307 | |||
308 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
309 | peer); | ||
310 | if (NULL != session) | ||
311 | { | ||
312 | GNUNET_break (0); | ||
313 | session->distance = distance; | ||
314 | notify_distance_change (session); | ||
315 | return; /* nothing to do */ | ||
316 | } | ||
317 | |||
318 | session = GNUNET_new (struct GNUNET_ATS_Session); | ||
319 | session->address = GNUNET_HELLO_address_allocate (peer, "dv", | ||
320 | NULL, 0, | ||
321 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
322 | session->sender = *peer; | ||
323 | session->plugin = plugin; | ||
324 | session->distance = distance; | ||
325 | session->network = network; | ||
326 | GNUNET_assert(GNUNET_YES == | ||
327 | GNUNET_CONTAINER_multipeermap_put (plugin->sessions, | ||
328 | &session->sender, session, | ||
329 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
330 | |||
331 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
332 | "Creating new DV session %p for peer `%s' at distance %u\n", | ||
333 | session, | ||
334 | GNUNET_i2s (peer), | ||
335 | distance); | ||
336 | |||
337 | session->active = GNUNET_YES; | ||
338 | plugin->env->session_start (plugin->env->cls, | ||
339 | session->address, | ||
340 | session, | ||
341 | network); | ||
342 | plugin->env->update_address_distance (plugin->env->cls, | ||
343 | session->address, | ||
344 | session->distance); | ||
345 | |||
346 | notify_session_monitor (session->plugin, | ||
347 | session, | ||
348 | GNUNET_TRANSPORT_SS_UP); | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Function called if DV distance to a peer is changed. | ||
354 | * | ||
355 | * @param cls closure with `struct Plugin *` | ||
356 | * @param peer connected peer | ||
357 | * @param distance new distance to the peer | ||
358 | * @param network network type used for the connection | ||
359 | */ | ||
360 | static void | ||
361 | handle_dv_distance_changed (void *cls, | ||
362 | const struct GNUNET_PeerIdentity *peer, | ||
363 | uint32_t distance, | ||
364 | enum GNUNET_NetworkType network) | ||
365 | { | ||
366 | struct Plugin *plugin = cls; | ||
367 | struct GNUNET_ATS_Session *session; | ||
368 | |||
369 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
370 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
371 | "Received `%s' message for peer `%s': new distance %u\n", | ||
372 | "DV_DISTANCE_CHANGED", | ||
373 | GNUNET_i2s (peer), | ||
374 | distance); | ||
375 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
376 | peer); | ||
377 | if (NULL == session) | ||
378 | { | ||
379 | GNUNET_break (0); | ||
380 | handle_dv_connect (plugin, peer, distance, network); | ||
381 | return; | ||
382 | } | ||
383 | session->distance = distance; | ||
384 | notify_distance_change (session); | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Release session object and clean up associated resources. | ||
390 | * | ||
391 | * @param session session to clean up | ||
392 | */ | ||
393 | static void | ||
394 | free_session (struct GNUNET_ATS_Session *session) | ||
395 | { | ||
396 | struct Plugin *plugin = session->plugin; | ||
397 | |||
398 | GNUNET_assert (GNUNET_YES == | ||
399 | GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, | ||
400 | &session->sender, | ||
401 | session)); | ||
402 | |||
403 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
404 | "Freeing session %p for peer `%s'\n", | ||
405 | session, | ||
406 | GNUNET_i2s (&session->sender)); | ||
407 | if (GNUNET_YES == session->active) | ||
408 | { | ||
409 | notify_session_monitor (session->plugin, | ||
410 | session, | ||
411 | GNUNET_TRANSPORT_SS_DONE); | ||
412 | plugin->env->session_end (plugin->env->cls, | ||
413 | session->address, | ||
414 | session); | ||
415 | session->active = GNUNET_NO; | ||
416 | } | ||
417 | GNUNET_HELLO_address_free (session->address); | ||
418 | GNUNET_free (session); | ||
419 | } | ||
420 | |||
421 | |||
422 | /** | ||
423 | * Function called if DV is no longer able to talk to a peer. | ||
424 | * | ||
425 | * @param cls closure with `struct Plugin *` | ||
426 | * @param peer peer that disconnected | ||
427 | */ | ||
428 | static void | ||
429 | handle_dv_disconnect (void *cls, | ||
430 | const struct GNUNET_PeerIdentity *peer) | ||
431 | { | ||
432 | struct Plugin *plugin = cls; | ||
433 | struct GNUNET_ATS_Session *session; | ||
434 | |||
435 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
436 | "Received `%s' message for peer `%s'\n", | ||
437 | "DV_DISCONNECT", | ||
438 | GNUNET_i2s (peer)); | ||
439 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
440 | peer); | ||
441 | if (NULL == session) | ||
442 | return; /* nothing to do */ | ||
443 | free_session (session); | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * Function that can be used by the transport service to transmit | ||
449 | * a message using the plugin. | ||
450 | * | ||
451 | * @param cls closure | ||
452 | * @param session the session used | ||
453 | * @param priority how important is the message | ||
454 | * @param msgbuf the message to transmit | ||
455 | * @param msgbuf_size number of bytes in 'msgbuf' | ||
456 | * @param timeout when should we time out | ||
457 | * @param cont continuation to call once the message has | ||
458 | * been transmitted (or if the transport is ready | ||
459 | * for the next transmission call; or if the | ||
460 | * peer disconnected...) | ||
461 | * @param cont_cls closure for @a cont | ||
462 | * @return number of bytes used (on the physical network, with overheads); | ||
463 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | ||
464 | * and does NOT mean that the message was not transmitted (DV) | ||
465 | */ | ||
466 | static ssize_t | ||
467 | dv_plugin_send (void *cls, | ||
468 | struct GNUNET_ATS_Session *session, | ||
469 | const char *msgbuf, | ||
470 | size_t msgbuf_size, | ||
471 | unsigned int priority, | ||
472 | struct GNUNET_TIME_Relative timeout, | ||
473 | GNUNET_TRANSPORT_TransmitContinuation cont, | ||
474 | void *cont_cls) | ||
475 | { | ||
476 | struct Plugin *plugin = cls; | ||
477 | const struct GNUNET_MessageHeader *msg; | ||
478 | struct GNUNET_MessageHeader *box; | ||
479 | |||
480 | box = NULL; | ||
481 | msg = (const struct GNUNET_MessageHeader *) msgbuf; | ||
482 | if (ntohs (msg->size) != msgbuf_size) | ||
483 | { | ||
484 | /* need to box */ | ||
485 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
486 | "Boxing DV message\n"); | ||
487 | box = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); | ||
488 | box->type = htons (GNUNET_MESSAGE_TYPE_DV_BOX); | ||
489 | box->size = htons (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); | ||
490 | GNUNET_memcpy (&box[1], msgbuf, msgbuf_size); | ||
491 | msg = box; | ||
492 | } | ||
493 | GNUNET_DV_send (plugin->dvh, | ||
494 | &session->sender, | ||
495 | msg); | ||
496 | cont (cont_cls, | ||
497 | &session->sender, | ||
498 | GNUNET_OK, | ||
499 | msgbuf_size, 0); | ||
500 | GNUNET_free_non_null (box); | ||
501 | return 0; /* DV */ | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Function that can be used to force the plugin to disconnect | ||
507 | * from the given peer and cancel all previous transmissions | ||
508 | * (and their continuations). | ||
509 | * | ||
510 | * @param cls closure with the `struct Plugin *` | ||
511 | * @param target peer from which to disconnect | ||
512 | */ | ||
513 | static void | ||
514 | dv_plugin_disconnect_peer (void *cls, | ||
515 | const struct GNUNET_PeerIdentity *target) | ||
516 | { | ||
517 | struct Plugin *plugin = cls; | ||
518 | struct GNUNET_ATS_Session *session; | ||
519 | |||
520 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
521 | target); | ||
522 | if (NULL == session) | ||
523 | return; /* nothing to do */ | ||
524 | session->active = GNUNET_NO; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Function that can be used to force the plugin to disconnect | ||
530 | * from the given peer and cancel all previous transmissions | ||
531 | * (and their continuations). | ||
532 | * | ||
533 | * @param cls closure with the `struct Plugin *` | ||
534 | * @param session which session to disconnect | ||
535 | * @return #GNUNET_OK | ||
536 | */ | ||
537 | static int | ||
538 | dv_plugin_disconnect_session (void *cls, | ||
539 | struct GNUNET_ATS_Session *session) | ||
540 | { | ||
541 | session->active = GNUNET_NO; | ||
542 | return GNUNET_OK; | ||
543 | } | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Convert the transports address to a nice, human-readable | ||
548 | * format. | ||
549 | * | ||
550 | * @param cls closure | ||
551 | * @param type name of the transport that generated the address | ||
552 | * @param addr one of the addresses of the host, NULL for the last address | ||
553 | * the specific address format depends on the transport | ||
554 | * @param addrlen length of the address | ||
555 | * @param numeric should (IP) addresses be displayed in numeric form? | ||
556 | * @param timeout after how long should we give up? | ||
557 | * @param asc function to call on each string | ||
558 | * @param asc_cls closure for @a asc | ||
559 | */ | ||
560 | static void | ||
561 | dv_plugin_address_pretty_printer (void *cls, | ||
562 | const char *type, | ||
563 | const void *addr, | ||
564 | size_t addrlen, | ||
565 | int numeric, | ||
566 | struct GNUNET_TIME_Relative timeout, | ||
567 | GNUNET_TRANSPORT_AddressStringCallback asc, | ||
568 | void *asc_cls) | ||
569 | { | ||
570 | if ( (0 == addrlen) && | ||
571 | (0 == strcmp (type, "dv")) ) | ||
572 | asc (asc_cls, | ||
573 | "dv", | ||
574 | GNUNET_OK); | ||
575 | else | ||
576 | asc (asc_cls, | ||
577 | NULL, | ||
578 | GNUNET_SYSERR); | ||
579 | asc (asc_cls, | ||
580 | NULL, | ||
581 | GNUNET_OK); | ||
582 | } | ||
583 | |||
584 | |||
585 | /** | ||
586 | * Convert the DV address to a pretty string. | ||
587 | * | ||
588 | * @param cls closure | ||
589 | * @param addr the (hopefully) DV address | ||
590 | * @param addrlen the length of the @a addr | ||
591 | * @return string representing the DV address | ||
592 | */ | ||
593 | static const char * | ||
594 | dv_plugin_address_to_string (void *cls, | ||
595 | const void *addr, | ||
596 | size_t addrlen) | ||
597 | { | ||
598 | if (0 != addrlen) | ||
599 | { | ||
600 | GNUNET_break (0); /* malformed */ | ||
601 | return NULL; | ||
602 | } | ||
603 | return "dv"; | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Another peer has suggested an address for this peer and transport | ||
609 | * plugin. Check that this could be a valid address. This function | ||
610 | * is not expected to 'validate' the address in the sense of trying to | ||
611 | * connect to it but simply to see if the binary format is technically | ||
612 | * legal for establishing a connection to this peer (and make sure that | ||
613 | * the address really corresponds to our network connection/settings | ||
614 | * and not some potential man-in-the-middle). | ||
615 | * | ||
616 | * @param cls closure | ||
617 | * @param addr pointer to the address | ||
618 | * @param addrlen length of @a addr | ||
619 | * @return #GNUNET_OK if this is a plausible address for this peer | ||
620 | * and transport, #GNUNET_SYSERR if not | ||
621 | * | ||
622 | */ | ||
623 | static int | ||
624 | dv_plugin_check_address (void *cls, | ||
625 | const void *addr, | ||
626 | size_t addrlen) | ||
627 | { | ||
628 | if (0 != addrlen) | ||
629 | return GNUNET_SYSERR; | ||
630 | return GNUNET_OK; | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Create a new session to transmit data to the target | ||
636 | * This session will used to send data to this peer and the plugin will | ||
637 | * notify us by calling the env->session_end function | ||
638 | * | ||
639 | * @param cls the plugin | ||
640 | * @param address the address | ||
641 | * @return the session if the address is valid, NULL otherwise | ||
642 | */ | ||
643 | static struct GNUNET_ATS_Session * | ||
644 | dv_get_session (void *cls, | ||
645 | const struct GNUNET_HELLO_Address *address) | ||
646 | { | ||
647 | struct Plugin *plugin = cls; | ||
648 | struct GNUNET_ATS_Session *session; | ||
649 | |||
650 | if (0 != address->address_length) | ||
651 | return NULL; | ||
652 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
653 | &address->peer); | ||
654 | if (NULL == session) | ||
655 | return NULL; /* not valid right now */ | ||
656 | session->active = GNUNET_YES; | ||
657 | return session; | ||
658 | } | ||
659 | |||
660 | |||
661 | /** | ||
662 | * Function called to convert a string address to | ||
663 | * a binary address. | ||
664 | * | ||
665 | * @param cls closure ('struct Plugin*') | ||
666 | * @param addr string address | ||
667 | * @param addrlen length of the @a addr including \0 termination | ||
668 | * @param buf location to store the buffer | ||
669 | * If the function returns #GNUNET_SYSERR, its contents are undefined. | ||
670 | * @param added length of created address | ||
671 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
672 | */ | ||
673 | static int | ||
674 | dv_plugin_string_to_address (void *cls, | ||
675 | const char *addr, | ||
676 | uint16_t addrlen, | ||
677 | void **buf, | ||
678 | size_t *added) | ||
679 | { | ||
680 | if ( (addrlen == 3) && | ||
681 | (0 == strcmp ("dv", addr)) ) | ||
682 | { | ||
683 | *added = 0; | ||
684 | return GNUNET_OK; | ||
685 | } | ||
686 | return GNUNET_SYSERR; | ||
687 | } | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Function that will be called whenever the transport service wants to | ||
692 | * notify the plugin that a session is still active and in use and | ||
693 | * therefore the session timeout for this session has to be updated | ||
694 | * | ||
695 | * @param cls closure (`struct Plugin *`) | ||
696 | * @param peer which peer was the session for | ||
697 | * @param session which session is being updated | ||
698 | */ | ||
699 | static void | ||
700 | dv_plugin_update_session_timeout (void *cls, | ||
701 | const struct GNUNET_PeerIdentity *peer, | ||
702 | struct GNUNET_ATS_Session *session) | ||
703 | { | ||
704 | /* DV currently doesn't time out like "normal" plugins, | ||
705 | so it should be safe to do nothing, right? | ||
706 | (or should we add an internal timeout?) */ | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Function to obtain the network type for a session | ||
712 | * FIXME: we should probably look at the network type | ||
713 | * used by the next hop here. Or find some other way | ||
714 | * to properly allow ATS-DV resource allocation. | ||
715 | * | ||
716 | * @param cls closure (`struct Plugin *`) | ||
717 | * @param session the session | ||
718 | * @return the network type | ||
719 | */ | ||
720 | static enum GNUNET_NetworkType | ||
721 | dv_get_network (void *cls, | ||
722 | struct GNUNET_ATS_Session *session) | ||
723 | { | ||
724 | GNUNET_assert (NULL != session); | ||
725 | return session->network; | ||
726 | } | ||
727 | |||
728 | |||
729 | /** | ||
730 | * Function obtain the network type for an address. | ||
731 | * | ||
732 | * @param cls closure (`struct Plugin *`) | ||
733 | * @param address the address | ||
734 | * @return the network type | ||
735 | */ | ||
736 | static enum GNUNET_NetworkType | ||
737 | dv_plugin_get_network_for_address (void *cls, | ||
738 | const struct GNUNET_HELLO_Address *address) | ||
739 | { | ||
740 | return GNUNET_NT_WAN; /* FOR NOW */ | ||
741 | } | ||
742 | |||
743 | |||
744 | /** | ||
745 | * Function that is called to get the keepalive factor. | ||
746 | * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to | ||
747 | * calculate the interval between keepalive packets. | ||
748 | * | ||
749 | * @param cls closure with the `struct Plugin` | ||
750 | * @return keepalive factor | ||
751 | */ | ||
752 | static unsigned int | ||
753 | dv_plugin_query_keepalive_factor (void *cls) | ||
754 | { | ||
755 | return 3; | ||
756 | } | ||
757 | |||
758 | |||
759 | /** | ||
760 | * Return information about the given session to the | ||
761 | * monitor callback. | ||
762 | * | ||
763 | * @param cls the `struct Plugin` with the monitor callback (`sic`) | ||
764 | * @param peer peer we send information about | ||
765 | * @param value our `struct GNUNET_ATS_Session` to send information about | ||
766 | * @return #GNUNET_OK (continue to iterate) | ||
767 | */ | ||
768 | static int | ||
769 | send_session_info_iter (void *cls, | ||
770 | const struct GNUNET_PeerIdentity *peer, | ||
771 | void *value) | ||
772 | { | ||
773 | struct Plugin *plugin = cls; | ||
774 | struct GNUNET_ATS_Session *session = value; | ||
775 | |||
776 | if (GNUNET_YES != session->active) | ||
777 | return GNUNET_OK; | ||
778 | notify_session_monitor (plugin, | ||
779 | session, | ||
780 | GNUNET_TRANSPORT_SS_UP); | ||
781 | return GNUNET_OK; | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | ||
786 | * Begin monitoring sessions of a plugin. There can only | ||
787 | * be one active monitor per plugin (i.e. if there are | ||
788 | * multiple monitors, the transport service needs to | ||
789 | * multiplex the generated events over all of them). | ||
790 | * | ||
791 | * @param cls closure of the plugin | ||
792 | * @param sic callback to invoke, NULL to disable monitor; | ||
793 | * plugin will being by iterating over all active | ||
794 | * sessions immediately and then enter monitor mode | ||
795 | * @param sic_cls closure for @a sic | ||
796 | */ | ||
797 | static void | ||
798 | dv_plugin_setup_monitor (void *cls, | ||
799 | GNUNET_TRANSPORT_SessionInfoCallback sic, | ||
800 | void *sic_cls) | ||
801 | { | ||
802 | struct Plugin *plugin = cls; | ||
803 | |||
804 | plugin->sic = sic; | ||
805 | plugin->sic_cls = sic_cls; | ||
806 | if (NULL != sic) | ||
807 | { | ||
808 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, | ||
809 | &send_session_info_iter, | ||
810 | plugin); | ||
811 | /* signal end of first iteration */ | ||
812 | sic (sic_cls, NULL, NULL); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Entry point for the plugin. | ||
819 | * | ||
820 | * @param cls closure with the plugin environment | ||
821 | * @return plugin API | ||
822 | */ | ||
823 | void * | ||
824 | libgnunet_plugin_transport_dv_init (void *cls) | ||
825 | { | ||
826 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; | ||
827 | struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
828 | struct Plugin *plugin; | ||
829 | |||
830 | plugin = GNUNET_new (struct Plugin); | ||
831 | plugin->env = env; | ||
832 | plugin->sessions = GNUNET_CONTAINER_multipeermap_create (1024 * 8, GNUNET_YES); | ||
833 | plugin->mst = GNUNET_SERVER_mst_create (&unbox_cb, | ||
834 | plugin); | ||
835 | plugin->dvh = GNUNET_DV_service_connect (env->cfg, | ||
836 | plugin, | ||
837 | &handle_dv_connect, | ||
838 | &handle_dv_distance_changed, | ||
839 | &handle_dv_disconnect, | ||
840 | &handle_dv_message_received); | ||
841 | if (NULL == plugin->dvh) | ||
842 | { | ||
843 | GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); | ||
844 | GNUNET_SERVER_mst_destroy (plugin->mst); | ||
845 | GNUNET_free (plugin); | ||
846 | return NULL; | ||
847 | } | ||
848 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); | ||
849 | api->cls = plugin; | ||
850 | api->send = &dv_plugin_send; | ||
851 | api->disconnect_peer = &dv_plugin_disconnect_peer; | ||
852 | api->disconnect_session = &dv_plugin_disconnect_session; | ||
853 | api->address_pretty_printer = &dv_plugin_address_pretty_printer; | ||
854 | api->check_address = &dv_plugin_check_address; | ||
855 | api->address_to_string = &dv_plugin_address_to_string; | ||
856 | api->string_to_address = &dv_plugin_string_to_address; | ||
857 | api->query_keepalive_factor = &dv_plugin_query_keepalive_factor; | ||
858 | api->get_session = &dv_get_session; | ||
859 | api->get_network = &dv_get_network; | ||
860 | api->get_network_for_address = &dv_plugin_get_network_for_address; | ||
861 | api->update_session_timeout = &dv_plugin_update_session_timeout; | ||
862 | api->setup_monitor = &dv_plugin_setup_monitor; | ||
863 | return api; | ||
864 | } | ||
865 | |||
866 | |||
867 | /** | ||
868 | * Function called to free a session. | ||
869 | * | ||
870 | * @param cls NULL | ||
871 | * @param key unused | ||
872 | * @param value session to free | ||
873 | * @return #GNUNET_OK (continue to iterate) | ||
874 | */ | ||
875 | static int | ||
876 | free_session_iterator (void *cls, | ||
877 | const struct GNUNET_PeerIdentity *key, | ||
878 | void *value) | ||
879 | { | ||
880 | struct GNUNET_ATS_Session *session = value; | ||
881 | |||
882 | free_session (session); | ||
883 | return GNUNET_OK; | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Exit point from the plugin. | ||
889 | * | ||
890 | * @param cls plugin API | ||
891 | * @return NULL | ||
892 | */ | ||
893 | void * | ||
894 | libgnunet_plugin_transport_dv_done (void *cls) | ||
895 | { | ||
896 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | ||
897 | struct Plugin *plugin = api->cls; | ||
898 | |||
899 | GNUNET_DV_service_disconnect (plugin->dvh); | ||
900 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, | ||
901 | &free_session_iterator, | ||
902 | NULL); | ||
903 | GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); | ||
904 | GNUNET_SERVER_mst_destroy (plugin->mst); | ||
905 | GNUNET_free (plugin); | ||
906 | GNUNET_free (api); | ||
907 | return NULL; | ||
908 | } | ||
909 | |||
910 | /* end of plugin_transport_dv.c */ | ||