diff options
Diffstat (limited to 'src/transport/plugin_transport_wlan.c')
-rw-r--r-- | src/transport/plugin_transport_wlan.c | 2404 |
1 files changed, 0 insertions, 2404 deletions
diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c deleted file mode 100644 index 138fb5080..000000000 --- a/src/transport/plugin_transport_wlan.c +++ /dev/null | |||
@@ -1,2404 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2010-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 transport/plugin_transport_wlan.c | ||
23 | * @brief transport plugin for wlan and/or bluetooth | ||
24 | * @author David Brodski | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * BUILD_WLAN or BUILD_BLUETOOTH must be defined such that the respective | ||
28 | * variant of this code is compiled. | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_hello_lib.h" | ||
33 | #include "gnunet_protocols.h" | ||
34 | #include "gnunet_statistics_service.h" | ||
35 | #include "gnunet_transport_service.h" | ||
36 | #include "gnunet_transport_plugin.h" | ||
37 | #include "plugin_transport_wlan.h" | ||
38 | #include "gnunet_fragmentation_lib.h" | ||
39 | #include "gnunet_constants.h" | ||
40 | |||
41 | |||
42 | #if BUILD_WLAN | ||
43 | /* begin case wlan */ | ||
44 | #define PLUGIN_NAME "wlan" | ||
45 | #define CONFIG_NAME "transport-wlan" | ||
46 | #define HELPER_NAME "gnunet-helper-transport-wlan" | ||
47 | #define DUMMY_HELPER_NAME "gnunet-helper-transport-wlan-dummy" | ||
48 | #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_wlan_init | ||
49 | #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_wlan_done | ||
50 | #define LOG(kind, ...) GNUNET_log_from (kind, "transport-wlan", __VA_ARGS__) | ||
51 | |||
52 | |||
53 | /** | ||
54 | * time out of a mac endpoint | ||
55 | */ | ||
56 | #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
57 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2) | ||
58 | |||
59 | /** | ||
60 | * We reduce the frequence of HELLO beacons in relation to | ||
61 | * the number of MAC addresses currently visible to us. | ||
62 | * This is the multiplication factor. | ||
63 | */ | ||
64 | #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply ( \ | ||
65 | GNUNET_TIME_UNIT_SECONDS, 2) | ||
66 | |||
67 | |||
68 | /* end case wlan */ | ||
69 | #elif BUILD_BLUETOOTH | ||
70 | /* begin case bluetooth */ | ||
71 | |||
72 | #define PLUGIN_NAME "bluetooth" | ||
73 | #define CONFIG_NAME "transport-bluetooth" | ||
74 | #define HELPER_NAME "gnunet-helper-transport-bluetooth" | ||
75 | /* yes, this is correct, we use the same dummy driver as 'wlan' */ | ||
76 | #define DUMMY_HELPER_NAME "gnunet-helper-transport-wlan-dummy" | ||
77 | #define LIBGNUNET_PLUGIN_TRANSPORT_INIT \ | ||
78 | libgnunet_plugin_transport_bluetooth_init | ||
79 | #define LIBGNUNET_PLUGIN_TRANSPORT_DONE \ | ||
80 | libgnunet_plugin_transport_bluetooth_done | ||
81 | #define LOG(kind, ...) GNUNET_log_from (kind, "transport-bluetooth", \ | ||
82 | __VA_ARGS__) | ||
83 | |||
84 | /** | ||
85 | * time out of a mac endpoint | ||
86 | */ | ||
87 | #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
88 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 60) | ||
89 | |||
90 | |||
91 | /** | ||
92 | * We reduce the frequence of HELLO beacons in relation to | ||
93 | * the number of MAC addresses currently visible to us. | ||
94 | * This is the multiplication factor. | ||
95 | */ | ||
96 | #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply ( \ | ||
97 | GNUNET_TIME_UNIT_SECONDS, 60) | ||
98 | |||
99 | /* end case bluetooth */ | ||
100 | #else | ||
101 | #error need to build wlan or bluetooth | ||
102 | #endif | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Functions with this signature are called whenever a | ||
107 | * complete message is received by the tokenizer. | ||
108 | * | ||
109 | * Do not call #GNUNET_SERVER_mst_destroy from within | ||
110 | * the scope of this callback. | ||
111 | * | ||
112 | * @param cls closure | ||
113 | * @param client identification of the client | ||
114 | * @param message the actual message | ||
115 | * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing | ||
116 | */ | ||
117 | typedef int | ||
118 | (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls, | ||
119 | void *client, | ||
120 | const struct | ||
121 | GNUNET_MessageHeader *message); | ||
122 | |||
123 | |||
124 | /* Include legacy message stream tokenizer that was removed from util (for now) */ | ||
125 | #include "tcp_server_mst_legacy.c" | ||
126 | |||
127 | |||
128 | /** | ||
129 | * Max size of packet (that we give to the WLAN driver for transmission) | ||
130 | */ | ||
131 | #define WLAN_MTU 1430 | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Which network scope do we belong to? | ||
136 | */ | ||
137 | #if BUILD_WLAN | ||
138 | static const enum GNUNET_NetworkType scope = GNUNET_NT_WLAN; | ||
139 | #else | ||
140 | static const enum GNUNET_NetworkType scope = GNUNET_NT_BT; | ||
141 | #endif | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Maximum number of messages in defragmentation queue per MAC | ||
146 | */ | ||
147 | #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2 | ||
148 | |||
149 | /** | ||
150 | * Link layer control fields for better compatibility | ||
151 | * (i.e. GNUnet over WLAN is not IP-over-WLAN). | ||
152 | */ | ||
153 | #define WLAN_LLC_DSAP_FIELD 0x1f | ||
154 | #define WLAN_LLC_SSAP_FIELD 0x1f | ||
155 | |||
156 | |||
157 | GNUNET_NETWORK_STRUCT_BEGIN | ||
158 | /** | ||
159 | * Header for messages which need fragmentation. This is the format of | ||
160 | * a message we obtain AFTER defragmentation. We then need to check | ||
161 | * the CRC and then tokenize the payload and pass it to the | ||
162 | * 'receive' callback. | ||
163 | */ | ||
164 | struct WlanHeader | ||
165 | { | ||
166 | /** | ||
167 | * Message type is #GNUNET_MESSAGE_TYPE_WLAN_DATA. | ||
168 | */ | ||
169 | struct GNUNET_MessageHeader header; | ||
170 | |||
171 | /** | ||
172 | * CRC32 checksum (only over the payload), in NBO. | ||
173 | */ | ||
174 | uint32_t crc GNUNET_PACKED; | ||
175 | |||
176 | /** | ||
177 | * Sender of the message. | ||
178 | */ | ||
179 | struct GNUNET_PeerIdentity sender; | ||
180 | |||
181 | /** | ||
182 | * Target of the message. | ||
183 | */ | ||
184 | struct GNUNET_PeerIdentity target; | ||
185 | |||
186 | /* followed by payload, possibly including | ||
187 | multiple messages! */ | ||
188 | }; | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Address format for WLAN. | ||
193 | */ | ||
194 | struct WlanAddress | ||
195 | { | ||
196 | /** | ||
197 | * Options set for the WLAN, in NBO. | ||
198 | */ | ||
199 | uint32_t options GNUNET_PACKED; | ||
200 | |||
201 | /** | ||
202 | * WLAN addresses using MACs. | ||
203 | */ | ||
204 | struct GNUNET_TRANSPORT_WLAN_MacAddress mac; | ||
205 | }; | ||
206 | |||
207 | |||
208 | GNUNET_NETWORK_STRUCT_END | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Information kept for each message that is yet to be fragmented and | ||
213 | * transmitted. | ||
214 | */ | ||
215 | struct PendingMessage | ||
216 | { | ||
217 | /** | ||
218 | * next entry in the DLL | ||
219 | */ | ||
220 | struct PendingMessage *next; | ||
221 | |||
222 | /** | ||
223 | * previous entry in the DLL | ||
224 | */ | ||
225 | struct PendingMessage *prev; | ||
226 | |||
227 | /** | ||
228 | * The pending message | ||
229 | */ | ||
230 | struct WlanHeader *msg; | ||
231 | |||
232 | /** | ||
233 | * Continuation function to call once the message | ||
234 | * has been sent. Can be NULL if there is no | ||
235 | * continuation to call. | ||
236 | */ | ||
237 | GNUNET_TRANSPORT_TransmitContinuation transmit_cont; | ||
238 | |||
239 | /** | ||
240 | * Cls for @e transmit_cont | ||
241 | */ | ||
242 | void *transmit_cont_cls; | ||
243 | |||
244 | /** | ||
245 | * Timeout task (for this message). | ||
246 | */ | ||
247 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
248 | }; | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Session handle for connections with other peers. | ||
253 | */ | ||
254 | struct GNUNET_ATS_Session | ||
255 | { | ||
256 | /** | ||
257 | * To whom are we talking to (set to our identity | ||
258 | * if we are still waiting for the welcome message) | ||
259 | */ | ||
260 | struct GNUNET_PeerIdentity target; | ||
261 | |||
262 | /** | ||
263 | * We keep all sessions in a DLL at their respective | ||
264 | * `struct MACEndpoint *`. | ||
265 | */ | ||
266 | struct GNUNET_ATS_Session *next; | ||
267 | |||
268 | /** | ||
269 | * We keep all sessions in a DLL at their respective | ||
270 | * `struct MACEndpoint *`. | ||
271 | */ | ||
272 | struct GNUNET_ATS_Session *prev; | ||
273 | |||
274 | /** | ||
275 | * MAC endpoint with the address of this peer. | ||
276 | */ | ||
277 | struct MacEndpoint *mac; | ||
278 | |||
279 | /** | ||
280 | * Address associated with this session and MAC endpoint | ||
281 | */ | ||
282 | struct GNUNET_HELLO_Address *address; | ||
283 | |||
284 | /** | ||
285 | * When should this session time out? | ||
286 | */ | ||
287 | struct GNUNET_TIME_Absolute timeout; | ||
288 | |||
289 | /** | ||
290 | * Timeout task (for the session). | ||
291 | */ | ||
292 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
293 | }; | ||
294 | |||
295 | |||
296 | /** | ||
297 | * Struct for messages that are being fragmented in a MAC's transmission queue. | ||
298 | */ | ||
299 | struct FragmentMessage | ||
300 | { | ||
301 | /** | ||
302 | * This is a doubly-linked list. | ||
303 | */ | ||
304 | struct FragmentMessage *next; | ||
305 | |||
306 | /** | ||
307 | * This is a doubly-linked list. | ||
308 | */ | ||
309 | struct FragmentMessage *prev; | ||
310 | |||
311 | /** | ||
312 | * MAC endpoint this message belongs to | ||
313 | */ | ||
314 | struct MacEndpoint *macendpoint; | ||
315 | |||
316 | /** | ||
317 | * Fragmentation context | ||
318 | */ | ||
319 | struct GNUNET_FRAGMENT_Context *fragcontext; | ||
320 | |||
321 | /** | ||
322 | * Transmission handle to helper (to cancel if the frag context | ||
323 | * is destroyed early for some reason). | ||
324 | */ | ||
325 | struct GNUNET_HELPER_SendHandle *sh; | ||
326 | |||
327 | /** | ||
328 | * Intended recipient. | ||
329 | */ | ||
330 | struct GNUNET_PeerIdentity target; | ||
331 | |||
332 | /** | ||
333 | * Timeout value for the message. | ||
334 | */ | ||
335 | struct GNUNET_TIME_Absolute timeout; | ||
336 | |||
337 | /** | ||
338 | * Timeout task. | ||
339 | */ | ||
340 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
341 | |||
342 | /** | ||
343 | * Continuation to call when we're done with this message. | ||
344 | */ | ||
345 | GNUNET_TRANSPORT_TransmitContinuation cont; | ||
346 | |||
347 | /** | ||
348 | * Message we need to fragment and transmit, NULL after the | ||
349 | * @e fragmentcontext has been created. | ||
350 | */ | ||
351 | struct GNUNET_MessageHeader *msg; | ||
352 | |||
353 | /** | ||
354 | * Closure for @e cont | ||
355 | */ | ||
356 | void *cont_cls; | ||
357 | |||
358 | /** | ||
359 | * Size of original message | ||
360 | */ | ||
361 | size_t size_payload; | ||
362 | |||
363 | /** | ||
364 | * Number of bytes used to transmit message | ||
365 | */ | ||
366 | size_t size_on_wire; | ||
367 | }; | ||
368 | |||
369 | |||
370 | /** | ||
371 | * Struct to represent one network card connection | ||
372 | */ | ||
373 | struct MacEndpoint | ||
374 | { | ||
375 | /** | ||
376 | * We keep all MACs in a DLL in the plugin. | ||
377 | */ | ||
378 | struct MacEndpoint *next; | ||
379 | |||
380 | /** | ||
381 | * We keep all MACs in a DLL in the plugin. | ||
382 | */ | ||
383 | struct MacEndpoint *prev; | ||
384 | |||
385 | /** | ||
386 | * Pointer to the global plugin struct. | ||
387 | */ | ||
388 | struct Plugin *plugin; | ||
389 | |||
390 | /** | ||
391 | * Head of sessions that use this MAC. | ||
392 | */ | ||
393 | struct GNUNET_ATS_Session *sessions_head; | ||
394 | |||
395 | /** | ||
396 | * Tail of sessions that use this MAC. | ||
397 | */ | ||
398 | struct GNUNET_ATS_Session *sessions_tail; | ||
399 | |||
400 | /** | ||
401 | * Head of messages we are currently sending to this MAC. | ||
402 | */ | ||
403 | struct FragmentMessage *sending_messages_head; | ||
404 | |||
405 | /** | ||
406 | * Tail of messages we are currently sending to this MAC. | ||
407 | */ | ||
408 | struct FragmentMessage *sending_messages_tail; | ||
409 | |||
410 | /** | ||
411 | * Defrag context for this MAC | ||
412 | */ | ||
413 | struct GNUNET_DEFRAGMENT_Context *defrag; | ||
414 | |||
415 | /** | ||
416 | * When should this endpoint time out? | ||
417 | */ | ||
418 | struct GNUNET_TIME_Absolute timeout; | ||
419 | |||
420 | /** | ||
421 | * Timeout task. | ||
422 | */ | ||
423 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
424 | |||
425 | /** | ||
426 | * count of messages in the fragment out queue for this mac endpoint | ||
427 | */ | ||
428 | unsigned int fragment_messages_out_count; | ||
429 | |||
430 | /** | ||
431 | * peer MAC address | ||
432 | */ | ||
433 | struct WlanAddress wlan_addr; | ||
434 | |||
435 | /** | ||
436 | * Message delay for fragmentation context | ||
437 | */ | ||
438 | struct GNUNET_TIME_Relative msg_delay; | ||
439 | |||
440 | /** | ||
441 | * ACK delay for fragmentation context | ||
442 | */ | ||
443 | struct GNUNET_TIME_Relative ack_delay; | ||
444 | |||
445 | /** | ||
446 | * Desired transmission power for this MAC | ||
447 | */ | ||
448 | uint16_t tx_power; | ||
449 | |||
450 | /** | ||
451 | * Desired transmission rate for this MAC | ||
452 | */ | ||
453 | uint8_t rate; | ||
454 | |||
455 | /** | ||
456 | * Antenna we should use for this MAC | ||
457 | */ | ||
458 | uint8_t antenna; | ||
459 | }; | ||
460 | |||
461 | |||
462 | /** | ||
463 | * Encapsulation of all of the state of the plugin. | ||
464 | */ | ||
465 | struct Plugin | ||
466 | { | ||
467 | /** | ||
468 | * Our environment. | ||
469 | */ | ||
470 | struct GNUNET_TRANSPORT_PluginEnvironment *env; | ||
471 | |||
472 | /** | ||
473 | * Handle to helper process for privileged operations. | ||
474 | */ | ||
475 | struct GNUNET_HELPER_Handle *suid_helper; | ||
476 | |||
477 | /** | ||
478 | * Function to call about session status changes. | ||
479 | */ | ||
480 | GNUNET_TRANSPORT_SessionInfoCallback sic; | ||
481 | |||
482 | /** | ||
483 | * Closure for @e sic. | ||
484 | */ | ||
485 | void *sic_cls; | ||
486 | |||
487 | /** | ||
488 | * ARGV-vector for the helper (all helpers take only the binary | ||
489 | * name, one actual argument, plus the NULL terminator for 'argv'). | ||
490 | */ | ||
491 | char *helper_argv[3]; | ||
492 | |||
493 | /** | ||
494 | * The interface of the wlan card given to us by the user. | ||
495 | */ | ||
496 | char *wlan_interface; | ||
497 | |||
498 | /** | ||
499 | * Tokenizer for demultiplexing of data packets resulting from | ||
500 | * defragmentation. | ||
501 | */ | ||
502 | struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer; | ||
503 | |||
504 | /** | ||
505 | * Tokenizer for demultiplexing of data packets received from the suid helper | ||
506 | */ | ||
507 | struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer; | ||
508 | |||
509 | /** | ||
510 | * Tokenizer for demultiplexing of data packets that follow the WLAN Header | ||
511 | */ | ||
512 | struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer; | ||
513 | |||
514 | /** | ||
515 | * Head of list of open connections. | ||
516 | */ | ||
517 | struct MacEndpoint *mac_head; | ||
518 | |||
519 | /** | ||
520 | * Tail of list of open connections. | ||
521 | */ | ||
522 | struct MacEndpoint *mac_tail; | ||
523 | |||
524 | /** | ||
525 | * Task that periodically sends a HELLO beacon via the helper. | ||
526 | */ | ||
527 | struct GNUNET_SCHEDULER_Task *beacon_task; | ||
528 | |||
529 | /** | ||
530 | * Tracker for bandwidth limit | ||
531 | */ | ||
532 | struct GNUNET_BANDWIDTH_Tracker tracker; | ||
533 | |||
534 | /** | ||
535 | * The mac_address of the wlan card given to us by the helper. | ||
536 | */ | ||
537 | struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address; | ||
538 | |||
539 | /** | ||
540 | * Have we received a control message with our MAC address yet? | ||
541 | */ | ||
542 | int have_mac; | ||
543 | |||
544 | /** | ||
545 | * Number of connections | ||
546 | */ | ||
547 | unsigned int mac_count; | ||
548 | |||
549 | /** | ||
550 | * Options for addresses | ||
551 | */ | ||
552 | uint32_t options; | ||
553 | }; | ||
554 | |||
555 | |||
556 | /** | ||
557 | * Information associated with a message. Can contain | ||
558 | * the session or the MAC endpoint associated with the | ||
559 | * message (or both). | ||
560 | */ | ||
561 | struct MacAndSession | ||
562 | { | ||
563 | /** | ||
564 | * NULL if the identity of the other peer is not known. | ||
565 | */ | ||
566 | struct GNUNET_ATS_Session *session; | ||
567 | |||
568 | /** | ||
569 | * MAC address of the other peer, NULL if not known. | ||
570 | */ | ||
571 | struct MacEndpoint *endpoint; | ||
572 | }; | ||
573 | |||
574 | |||
575 | /** | ||
576 | * Print MAC addresses nicely. | ||
577 | * | ||
578 | * @param mac the mac address | ||
579 | * @return string to a static buffer with | ||
580 | * the human-readable mac, will be overwritten during the next call to | ||
581 | * this function | ||
582 | */ | ||
583 | static const char * | ||
584 | mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac) | ||
585 | { | ||
586 | static char macstr[20]; | ||
587 | |||
588 | GNUNET_snprintf (macstr, | ||
589 | sizeof(macstr), | ||
590 | "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", | ||
591 | mac->mac[0], mac->mac[1], | ||
592 | mac->mac[2], mac->mac[3], | ||
593 | mac->mac[4], mac->mac[5]); | ||
594 | return macstr; | ||
595 | } | ||
596 | |||
597 | |||
598 | /** | ||
599 | * Function called for a quick conversion of the binary address to | ||
600 | * a numeric address. Note that the caller must not free the | ||
601 | * address and that the next call to this function is allowed | ||
602 | * to override the address again. | ||
603 | * | ||
604 | * @param cls closure | ||
605 | * @param addr binary address | ||
606 | * @param addrlen length of the address | ||
607 | * @return string representing the same address | ||
608 | */ | ||
609 | static const char * | ||
610 | wlan_plugin_address_to_string (void *cls, | ||
611 | const void *addr, | ||
612 | size_t addrlen) | ||
613 | { | ||
614 | const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac; | ||
615 | static char macstr[36]; | ||
616 | |||
617 | if (sizeof(struct WlanAddress) != addrlen) | ||
618 | { | ||
619 | GNUNET_break (0); | ||
620 | return NULL; | ||
621 | } | ||
622 | mac = &((struct WlanAddress *) addr)->mac; | ||
623 | GNUNET_snprintf (macstr, | ||
624 | sizeof(macstr), | ||
625 | "%s.%u.%s", | ||
626 | PLUGIN_NAME, | ||
627 | ntohl (((struct WlanAddress *) addr)->options), | ||
628 | mac_to_string (mac)); | ||
629 | return macstr; | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * If a session monitor is attached, notify it about the new | ||
635 | * session state. | ||
636 | * | ||
637 | * @param plugin our plugin | ||
638 | * @param session session that changed state | ||
639 | * @param state new state of the session | ||
640 | */ | ||
641 | static void | ||
642 | notify_session_monitor (struct Plugin *plugin, | ||
643 | struct GNUNET_ATS_Session *session, | ||
644 | enum GNUNET_TRANSPORT_SessionState state) | ||
645 | { | ||
646 | struct GNUNET_TRANSPORT_SessionInfo info; | ||
647 | |||
648 | if (NULL == plugin->sic) | ||
649 | return; | ||
650 | memset (&info, 0, sizeof(info)); | ||
651 | info.state = state; | ||
652 | info.is_inbound = GNUNET_SYSERR; /* hard to say */ | ||
653 | info.num_msg_pending = 0; /* we queue per MAC, not per peer */ | ||
654 | info.num_bytes_pending = 0; /* we queue per MAC, not per peer */ | ||
655 | info.receive_delay = GNUNET_TIME_UNIT_ZERO_ABS; /* not supported by WLAN */ | ||
656 | info.session_timeout = session->timeout; | ||
657 | info.address = session->address; | ||
658 | plugin->sic (plugin->sic_cls, | ||
659 | session, | ||
660 | &info); | ||
661 | } | ||
662 | |||
663 | |||
664 | /** | ||
665 | * Fill the radiotap header | ||
666 | * | ||
667 | * @param endpoint pointer to the endpoint, can be NULL | ||
668 | * @param header pointer to the radiotap header | ||
669 | * @param size total message size | ||
670 | */ | ||
671 | static void | ||
672 | get_radiotap_header (struct MacEndpoint *endpoint, | ||
673 | struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header, | ||
674 | uint16_t size) | ||
675 | { | ||
676 | header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER); | ||
677 | header->header.size = ntohs (size); | ||
678 | if (NULL != endpoint) | ||
679 | { | ||
680 | header->rate = endpoint->rate; | ||
681 | header->tx_power = endpoint->tx_power; | ||
682 | header->antenna = endpoint->antenna; | ||
683 | } | ||
684 | else | ||
685 | { | ||
686 | header->rate = 255; | ||
687 | header->tx_power = 0; | ||
688 | header->antenna = 0; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | |||
693 | /** | ||
694 | * Generate the WLAN hardware header for one packet | ||
695 | * | ||
696 | * @param plugin the plugin handle | ||
697 | * @param header address to write the header to | ||
698 | * @param to_mac_addr address of the recipient | ||
699 | * @param size size of the whole packet, needed to calculate the time to send the packet | ||
700 | */ | ||
701 | static void | ||
702 | get_wlan_header (struct Plugin *plugin, | ||
703 | struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header, | ||
704 | const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, | ||
705 | unsigned int size) | ||
706 | { | ||
707 | const int rate = 11000000; | ||
708 | |||
709 | header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); | ||
710 | header->addr1 = *to_mac_addr; | ||
711 | header->addr2 = plugin->mac_address; | ||
712 | header->addr3 = mac_bssid_gnunet; | ||
713 | header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290); | ||
714 | header->sequence_control = 0; // FIXME? | ||
715 | header->llc[0] = WLAN_LLC_DSAP_FIELD; | ||
716 | header->llc[1] = WLAN_LLC_SSAP_FIELD; | ||
717 | header->llc[2] = 0; // FIXME? | ||
718 | header->llc[3] = 0; // FIXME? | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * Send an ACK for a fragment we received. | ||
724 | * | ||
725 | * @param cls the `struct MacEndpoint *` the ACK must be sent to | ||
726 | * @param msg_id id of the message | ||
727 | * @param hdr pointer to the hdr where the ack is stored | ||
728 | */ | ||
729 | static void | ||
730 | send_ack (void *cls, | ||
731 | uint32_t msg_id, | ||
732 | const struct GNUNET_MessageHeader *hdr) | ||
733 | { | ||
734 | struct MacEndpoint *endpoint = cls; | ||
735 | struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*radio_header; | ||
736 | uint16_t msize = ntohs (hdr->size); | ||
737 | size_t size = sizeof(struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) | ||
738 | + msize; | ||
739 | char buf[size]; | ||
740 | |||
741 | if (NULL == endpoint) | ||
742 | { | ||
743 | GNUNET_break (0); | ||
744 | return; | ||
745 | } | ||
746 | if (size >= GNUNET_MAX_MESSAGE_SIZE) | ||
747 | { | ||
748 | GNUNET_break (0); | ||
749 | return; | ||
750 | } | ||
751 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "Sending ACK to %s\n", | ||
753 | mac_to_string (&endpoint->wlan_addr.mac)); | ||
754 | radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; | ||
755 | get_radiotap_header (endpoint, radio_header, size); | ||
756 | get_wlan_header (endpoint->plugin, | ||
757 | &radio_header->frame, | ||
758 | &endpoint->wlan_addr.mac, | ||
759 | sizeof(endpoint->wlan_addr.mac)); | ||
760 | GNUNET_memcpy (&radio_header[1], hdr, msize); | ||
761 | if (NULL != | ||
762 | GNUNET_HELPER_send (endpoint->plugin->suid_helper, | ||
763 | &radio_header->header, | ||
764 | GNUNET_NO /* dropping ACKs is bad */, | ||
765 | NULL, NULL)) | ||
766 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
767 | _ ("# ACKs sent"), | ||
768 | 1, GNUNET_NO); | ||
769 | } | ||
770 | |||
771 | |||
772 | /** | ||
773 | * Handles the data after all fragments are put together | ||
774 | * | ||
775 | * @param cls macendpoint this messages belongs to | ||
776 | * @param hdr pointer to the data | ||
777 | */ | ||
778 | static void | ||
779 | wlan_data_message_handler (void *cls, | ||
780 | const struct GNUNET_MessageHeader *hdr) | ||
781 | { | ||
782 | struct MacEndpoint *endpoint = cls; | ||
783 | struct Plugin *plugin = endpoint->plugin; | ||
784 | struct MacAndSession mas; | ||
785 | |||
786 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
787 | _ ("# Messages defragmented"), | ||
788 | 1, | ||
789 | GNUNET_NO); | ||
790 | mas.session = NULL; | ||
791 | mas.endpoint = endpoint; | ||
792 | (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer, | ||
793 | &mas, | ||
794 | (const char *) hdr, | ||
795 | ntohs (hdr->size), | ||
796 | GNUNET_YES, GNUNET_NO); | ||
797 | } | ||
798 | |||
799 | |||
800 | /** | ||
801 | * Free a session | ||
802 | * | ||
803 | * @param cls our `struct Plugin`. | ||
804 | * @param session the session free | ||
805 | */ | ||
806 | static int | ||
807 | wlan_plugin_disconnect_session (void *cls, | ||
808 | struct GNUNET_ATS_Session *session) | ||
809 | { | ||
810 | struct MacEndpoint *endpoint = session->mac; | ||
811 | struct Plugin *plugin = endpoint->plugin; | ||
812 | |||
813 | plugin->env->session_end (plugin->env->cls, | ||
814 | session->address, | ||
815 | session); | ||
816 | notify_session_monitor (plugin, | ||
817 | session, | ||
818 | GNUNET_TRANSPORT_SS_DONE); | ||
819 | GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, | ||
820 | endpoint->sessions_tail, | ||
821 | session); | ||
822 | if (session->timeout_task != NULL) | ||
823 | { | ||
824 | GNUNET_SCHEDULER_cancel (session->timeout_task); | ||
825 | session->timeout_task = NULL; | ||
826 | } | ||
827 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
828 | _ ("# Sessions allocated"), | ||
829 | -1, | ||
830 | GNUNET_NO); | ||
831 | GNUNET_HELLO_address_free (session->address); | ||
832 | GNUNET_free (session); | ||
833 | return GNUNET_OK; | ||
834 | } | ||
835 | |||
836 | |||
837 | /** | ||
838 | * Function that is called to get the keepalive factor. | ||
839 | * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to | ||
840 | * calculate the interval between keepalive packets. | ||
841 | * | ||
842 | * @param cls closure with the `struct Plugin` | ||
843 | * @return keepalive factor | ||
844 | */ | ||
845 | static unsigned int | ||
846 | wlan_plugin_query_keepalive_factor (void *cls) | ||
847 | { | ||
848 | return 3; | ||
849 | } | ||
850 | |||
851 | |||
852 | /** | ||
853 | * A session is timing out. Clean up. | ||
854 | * | ||
855 | * @param cls pointer to the Session | ||
856 | */ | ||
857 | static void | ||
858 | session_timeout (void *cls) | ||
859 | { | ||
860 | struct GNUNET_ATS_Session *session = cls; | ||
861 | struct GNUNET_TIME_Relative left; | ||
862 | |||
863 | session->timeout_task = NULL; | ||
864 | left = GNUNET_TIME_absolute_get_remaining (session->timeout); | ||
865 | if (0 != left.rel_value_us) | ||
866 | { | ||
867 | session->timeout_task = | ||
868 | GNUNET_SCHEDULER_add_delayed (left, | ||
869 | &session_timeout, | ||
870 | session); | ||
871 | return; | ||
872 | } | ||
873 | wlan_plugin_disconnect_session (session->mac->plugin, | ||
874 | session); | ||
875 | } | ||
876 | |||
877 | |||
878 | /** | ||
879 | * Lookup a new session | ||
880 | * | ||
881 | * @param endpoint pointer to the mac endpoint of the peer | ||
882 | * @param peer peer identity to use for this session | ||
883 | * @return returns the session or NULL | ||
884 | */ | ||
885 | static struct GNUNET_ATS_Session * | ||
886 | lookup_session (struct MacEndpoint *endpoint, | ||
887 | const struct GNUNET_PeerIdentity *peer) | ||
888 | { | ||
889 | struct GNUNET_ATS_Session *session; | ||
890 | |||
891 | for (session = endpoint->sessions_head; NULL != session; session = | ||
892 | session->next) | ||
893 | if (0 == memcmp (peer, &session->target, sizeof(struct | ||
894 | GNUNET_PeerIdentity))) | ||
895 | return session; | ||
896 | return NULL; | ||
897 | } | ||
898 | |||
899 | |||
900 | /** | ||
901 | * Create a new session | ||
902 | * | ||
903 | * @param endpoint pointer to the mac endpoint of the peer | ||
904 | * @param peer peer identity to use for this session | ||
905 | * @return returns the session or NULL | ||
906 | */ | ||
907 | static struct GNUNET_ATS_Session * | ||
908 | create_session (struct MacEndpoint *endpoint, | ||
909 | const struct GNUNET_PeerIdentity *peer) | ||
910 | { | ||
911 | struct GNUNET_ATS_Session *session; | ||
912 | |||
913 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
914 | _ ("# Sessions allocated"), | ||
915 | 1, | ||
916 | GNUNET_NO); | ||
917 | session = GNUNET_new (struct GNUNET_ATS_Session); | ||
918 | GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head, | ||
919 | endpoint->sessions_tail, | ||
920 | session); | ||
921 | session->address = GNUNET_HELLO_address_allocate (peer, | ||
922 | PLUGIN_NAME, | ||
923 | &endpoint->wlan_addr, | ||
924 | sizeof(endpoint->wlan_addr), | ||
925 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
926 | session->mac = endpoint; | ||
927 | session->target = *peer; | ||
928 | session->timeout = GNUNET_TIME_relative_to_absolute ( | ||
929 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); | ||
930 | session->timeout_task = | ||
931 | GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, | ||
932 | &session_timeout, | ||
933 | session); | ||
934 | notify_session_monitor (endpoint->plugin, | ||
935 | session, | ||
936 | GNUNET_TRANSPORT_SS_INIT); | ||
937 | notify_session_monitor (endpoint->plugin, | ||
938 | session, | ||
939 | GNUNET_TRANSPORT_SS_UP); | ||
940 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
941 | "Created new session %p for peer `%s' with endpoint %s\n", | ||
942 | session, | ||
943 | GNUNET_i2s (peer), | ||
944 | mac_to_string (&endpoint->wlan_addr.mac)); | ||
945 | |||
946 | return session; | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Look up a session for a peer and create a new session if none is found | ||
952 | * | ||
953 | * @param endpoint pointer to the mac endpoint of the peer | ||
954 | * @param peer peer identity to use for this session | ||
955 | * @return returns the session | ||
956 | */ | ||
957 | static struct GNUNET_ATS_Session * | ||
958 | get_session (struct MacEndpoint *endpoint, | ||
959 | const struct GNUNET_PeerIdentity *peer) | ||
960 | { | ||
961 | struct GNUNET_ATS_Session *session; | ||
962 | |||
963 | if (NULL != (session = lookup_session (endpoint, peer))) | ||
964 | return session; | ||
965 | return create_session (endpoint, peer); | ||
966 | } | ||
967 | |||
968 | |||
969 | /** | ||
970 | * Function called once we have successfully given the fragment | ||
971 | * message to the SUID helper process and we are thus ready for | ||
972 | * the next fragment. | ||
973 | * | ||
974 | * @param cls the `struct FragmentMessage *` | ||
975 | * @param result result of the operation (#GNUNET_OK on success, | ||
976 | * #GNUNET_NO if the helper died, #GNUNET_SYSERR | ||
977 | * if the helper was stopped) | ||
978 | */ | ||
979 | static void | ||
980 | fragment_transmission_done (void *cls, | ||
981 | int result) | ||
982 | { | ||
983 | struct FragmentMessage *fm = cls; | ||
984 | |||
985 | fm->sh = NULL; | ||
986 | GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Transmit a fragment of a message. | ||
992 | * | ||
993 | * @param cls `struct FragmentMessage *` this fragment message belongs to | ||
994 | * @param hdr pointer to the start of the fragment message | ||
995 | */ | ||
996 | static void | ||
997 | transmit_fragment (void *cls, | ||
998 | const struct GNUNET_MessageHeader *hdr) | ||
999 | { | ||
1000 | struct FragmentMessage *fm = cls; | ||
1001 | struct MacEndpoint *endpoint = fm->macendpoint; | ||
1002 | size_t size; | ||
1003 | uint16_t msize; | ||
1004 | |||
1005 | if (NULL == endpoint) | ||
1006 | { | ||
1007 | GNUNET_break (0); | ||
1008 | return; | ||
1009 | } | ||
1010 | msize = ntohs (hdr->size); | ||
1011 | size = sizeof(struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize; | ||
1012 | { | ||
1013 | char buf[size]; | ||
1014 | struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header; | ||
1015 | |||
1016 | radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; | ||
1017 | get_radiotap_header (endpoint, radio_header, size); | ||
1018 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1019 | "Sending %u bytes of data to MAC `%s'\n", | ||
1020 | (unsigned int) msize, | ||
1021 | mac_to_string (&endpoint->wlan_addr.mac)); | ||
1022 | |||
1023 | get_wlan_header (endpoint->plugin, | ||
1024 | &radio_header->frame, | ||
1025 | &endpoint->wlan_addr.mac, | ||
1026 | sizeof(endpoint->wlan_addr.mac)); | ||
1027 | GNUNET_memcpy (&radio_header[1], hdr, msize); | ||
1028 | GNUNET_assert (NULL == fm->sh); | ||
1029 | fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper, | ||
1030 | &radio_header->header, | ||
1031 | GNUNET_NO, | ||
1032 | &fragment_transmission_done, fm); | ||
1033 | fm->size_on_wire += size; | ||
1034 | if (NULL != fm->sh) | ||
1035 | { | ||
1036 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
1037 | _ ("# message fragments sent"), | ||
1038 | 1, | ||
1039 | GNUNET_NO); | ||
1040 | } | ||
1041 | else | ||
1042 | { | ||
1043 | GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); | ||
1044 | } | ||
1045 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
1046 | "# bytes currently in buffers", | ||
1047 | -msize, GNUNET_NO); | ||
1048 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
1049 | "# bytes transmitted", | ||
1050 | msize, GNUNET_NO); | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | |||
1055 | /** | ||
1056 | * Frees the space of a message in the fragment queue (send queue) | ||
1057 | * | ||
1058 | * @param fm message to free | ||
1059 | */ | ||
1060 | static void | ||
1061 | free_fragment_message (struct FragmentMessage *fm) | ||
1062 | { | ||
1063 | struct MacEndpoint *endpoint = fm->macendpoint; | ||
1064 | |||
1065 | GNUNET_STATISTICS_update (endpoint->plugin->env->stats, | ||
1066 | _ ("# messages pending (with fragmentation)"), | ||
1067 | -1, GNUNET_NO); | ||
1068 | GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head, | ||
1069 | endpoint->sending_messages_tail, | ||
1070 | fm); | ||
1071 | if (NULL != fm->sh) | ||
1072 | { | ||
1073 | GNUNET_HELPER_send_cancel (fm->sh); | ||
1074 | fm->sh = NULL; | ||
1075 | } | ||
1076 | if (NULL != fm->msg) | ||
1077 | { | ||
1078 | GNUNET_free (fm->msg); | ||
1079 | fm->msg = NULL; | ||
1080 | } | ||
1081 | if (NULL != fm->fragcontext) | ||
1082 | { | ||
1083 | GNUNET_FRAGMENT_context_destroy (fm->fragcontext, | ||
1084 | &endpoint->msg_delay, | ||
1085 | &endpoint->ack_delay); | ||
1086 | fm->fragcontext = NULL; | ||
1087 | } | ||
1088 | if (NULL != fm->timeout_task) | ||
1089 | { | ||
1090 | GNUNET_SCHEDULER_cancel (fm->timeout_task); | ||
1091 | fm->timeout_task = NULL; | ||
1092 | } | ||
1093 | GNUNET_free (fm); | ||
1094 | } | ||
1095 | |||
1096 | |||
1097 | /** | ||
1098 | * A FragmentMessage has timed out. Remove it. | ||
1099 | * | ||
1100 | * @param cls pointer to the 'struct FragmentMessage' | ||
1101 | */ | ||
1102 | static void | ||
1103 | fragmentmessage_timeout (void *cls) | ||
1104 | { | ||
1105 | struct FragmentMessage *fm = cls; | ||
1106 | |||
1107 | fm->timeout_task = NULL; | ||
1108 | if (NULL != fm->cont) | ||
1109 | { | ||
1110 | fm->cont (fm->cont_cls, | ||
1111 | &fm->target, | ||
1112 | GNUNET_SYSERR, | ||
1113 | fm->size_payload, | ||
1114 | fm->size_on_wire); | ||
1115 | fm->cont = NULL; | ||
1116 | } | ||
1117 | free_fragment_message (fm); | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Transmit a message to the given destination with fragmentation. | ||
1123 | * | ||
1124 | * @param endpoint desired destination | ||
1125 | * @param timeout how long can the message wait? | ||
1126 | * @param target peer that should receive the message | ||
1127 | * @param msg message to transmit | ||
1128 | * @param payload_size bytes of payload | ||
1129 | * @param cont continuation to call once the message has | ||
1130 | * been transmitted (or if the transport is ready | ||
1131 | * for the next transmission call; or if the | ||
1132 | * peer disconnected...); can be NULL | ||
1133 | * @param cont_cls closure for @a cont | ||
1134 | */ | ||
1135 | static void | ||
1136 | send_with_fragmentation (struct MacEndpoint *endpoint, | ||
1137 | struct GNUNET_TIME_Relative timeout, | ||
1138 | const struct GNUNET_PeerIdentity *target, | ||
1139 | const struct GNUNET_MessageHeader *msg, | ||
1140 | size_t payload_size, | ||
1141 | GNUNET_TRANSPORT_TransmitContinuation cont, | ||
1142 | void *cont_cls) | ||
1143 | |||
1144 | { | ||
1145 | struct FragmentMessage *fm; | ||
1146 | struct Plugin *plugin; | ||
1147 | |||
1148 | plugin = endpoint->plugin; | ||
1149 | fm = GNUNET_new (struct FragmentMessage); | ||
1150 | fm->macendpoint = endpoint; | ||
1151 | fm->target = *target; | ||
1152 | fm->size_payload = payload_size; | ||
1153 | fm->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1154 | fm->cont = cont; | ||
1155 | fm->cont_cls = cont_cls; | ||
1156 | /* 1 MBit/s typical data rate, 1430 byte fragments => ~100 ms per message */ | ||
1157 | fm->timeout_task = | ||
1158 | GNUNET_SCHEDULER_add_delayed (timeout, | ||
1159 | &fragmentmessage_timeout, | ||
1160 | fm); | ||
1161 | if (GNUNET_YES == plugin->have_mac) | ||
1162 | { | ||
1163 | fm->fragcontext = | ||
1164 | GNUNET_FRAGMENT_context_create (plugin->env->stats, | ||
1165 | WLAN_MTU, | ||
1166 | &plugin->tracker, | ||
1167 | fm->macendpoint->msg_delay, | ||
1168 | fm->macendpoint->ack_delay, | ||
1169 | msg, | ||
1170 | &transmit_fragment, fm); | ||
1171 | } | ||
1172 | else | ||
1173 | { | ||
1174 | fm->msg = GNUNET_copy_message (msg); | ||
1175 | } | ||
1176 | GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head, | ||
1177 | endpoint->sending_messages_tail, | ||
1178 | fm); | ||
1179 | } | ||
1180 | |||
1181 | |||
1182 | /** | ||
1183 | * Free a MAC endpoint. | ||
1184 | * | ||
1185 | * @param endpoint pointer to the MacEndpoint to free | ||
1186 | */ | ||
1187 | static void | ||
1188 | free_macendpoint (struct MacEndpoint *endpoint) | ||
1189 | { | ||
1190 | struct Plugin *plugin = endpoint->plugin; | ||
1191 | struct FragmentMessage *fm; | ||
1192 | struct GNUNET_ATS_Session *session; | ||
1193 | |||
1194 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1195 | _ ("# MAC endpoints allocated"), | ||
1196 | -1, | ||
1197 | GNUNET_NO); | ||
1198 | while (NULL != (session = endpoint->sessions_head)) | ||
1199 | wlan_plugin_disconnect_session (plugin, | ||
1200 | session); | ||
1201 | while (NULL != (fm = endpoint->sending_messages_head)) | ||
1202 | free_fragment_message (fm); | ||
1203 | GNUNET_CONTAINER_DLL_remove (plugin->mac_head, | ||
1204 | plugin->mac_tail, | ||
1205 | endpoint); | ||
1206 | |||
1207 | if (NULL != endpoint->defrag) | ||
1208 | { | ||
1209 | GNUNET_DEFRAGMENT_context_destroy (endpoint->defrag); | ||
1210 | endpoint->defrag = NULL; | ||
1211 | } | ||
1212 | |||
1213 | plugin->mac_count--; | ||
1214 | if (NULL != endpoint->timeout_task) | ||
1215 | { | ||
1216 | GNUNET_SCHEDULER_cancel (endpoint->timeout_task); | ||
1217 | endpoint->timeout_task = NULL; | ||
1218 | } | ||
1219 | GNUNET_free (endpoint); | ||
1220 | } | ||
1221 | |||
1222 | |||
1223 | /** | ||
1224 | * A MAC endpoint is timing out. Clean up. | ||
1225 | * | ||
1226 | * @param cls pointer to the `struct MacEndpoint *` | ||
1227 | */ | ||
1228 | static void | ||
1229 | macendpoint_timeout (void *cls) | ||
1230 | { | ||
1231 | struct MacEndpoint *endpoint = cls; | ||
1232 | struct GNUNET_TIME_Relative timeout; | ||
1233 | |||
1234 | endpoint->timeout_task = NULL; | ||
1235 | timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout); | ||
1236 | if (0 == timeout.rel_value_us) | ||
1237 | { | ||
1238 | free_macendpoint (endpoint); | ||
1239 | return; | ||
1240 | } | ||
1241 | endpoint->timeout_task = | ||
1242 | GNUNET_SCHEDULER_add_delayed (timeout, | ||
1243 | &macendpoint_timeout, | ||
1244 | endpoint); | ||
1245 | } | ||
1246 | |||
1247 | |||
1248 | /** | ||
1249 | * Find (or create) a MacEndpoint with a specific MAC address | ||
1250 | * | ||
1251 | * @param plugin pointer to the plugin struct | ||
1252 | * @param mac the MAC address of the endpoint | ||
1253 | * @return handle to our data structure for this MAC | ||
1254 | */ | ||
1255 | static struct MacEndpoint * | ||
1256 | create_macendpoint (struct Plugin *plugin, | ||
1257 | struct WlanAddress *mac) | ||
1258 | { | ||
1259 | struct MacEndpoint *pos; | ||
1260 | |||
1261 | for (pos = plugin->mac_head; NULL != pos; pos = pos->next) | ||
1262 | if (0 == memcmp (mac, &pos->wlan_addr, sizeof(pos->wlan_addr))) | ||
1263 | return pos; | ||
1264 | pos = GNUNET_new (struct MacEndpoint); | ||
1265 | pos->wlan_addr = (*mac); | ||
1266 | pos->plugin = plugin; | ||
1267 | pos->defrag = | ||
1268 | GNUNET_DEFRAGMENT_context_create (plugin->env->stats, | ||
1269 | WLAN_MTU, | ||
1270 | MESSAGES_IN_DEFRAG_QUEUE_PER_MAC, | ||
1271 | pos, | ||
1272 | &wlan_data_message_handler, | ||
1273 | &send_ack); | ||
1274 | |||
1275 | pos->msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1276 | pos->ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1277 | 100); | ||
1278 | pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT); | ||
1279 | pos->timeout_task = | ||
1280 | GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout, | ||
1281 | pos); | ||
1282 | GNUNET_CONTAINER_DLL_insert (plugin->mac_head, | ||
1283 | plugin->mac_tail, | ||
1284 | pos); | ||
1285 | plugin->mac_count++; | ||
1286 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1287 | _ ("# MAC endpoints allocated"), | ||
1288 | 1, GNUNET_NO); | ||
1289 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1290 | "New MAC endpoint `%s'\n", | ||
1291 | wlan_plugin_address_to_string (NULL, | ||
1292 | &pos->wlan_addr, | ||
1293 | sizeof(struct WlanAddress))); | ||
1294 | return pos; | ||
1295 | } | ||
1296 | |||
1297 | |||
1298 | /** | ||
1299 | * Function obtain the network type for a session | ||
1300 | * | ||
1301 | * @param cls closure (`struct Plugin*`) | ||
1302 | * @param session the session | ||
1303 | * @return the network type in HBO or #GNUNET_SYSERR | ||
1304 | */ | ||
1305 | static enum GNUNET_NetworkType | ||
1306 | wlan_plugin_get_network (void *cls, | ||
1307 | struct GNUNET_ATS_Session *session) | ||
1308 | { | ||
1309 | #if BUILD_WLAN | ||
1310 | return GNUNET_NT_WLAN; | ||
1311 | #else | ||
1312 | return GNUNET_NT_BT; | ||
1313 | #endif | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /** | ||
1318 | * Function obtain the network type for an address. | ||
1319 | * | ||
1320 | * @param cls closure (`struct Plugin *`) | ||
1321 | * @param address the address | ||
1322 | * @return the network type | ||
1323 | */ | ||
1324 | static enum GNUNET_NetworkType | ||
1325 | wlan_plugin_get_network_for_address (void *cls, | ||
1326 | const struct GNUNET_HELLO_Address *address) | ||
1327 | { | ||
1328 | #if BUILD_WLAN | ||
1329 | return GNUNET_NT_WLAN; | ||
1330 | #else | ||
1331 | return GNUNET_NT_BT; | ||
1332 | #endif | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * Creates a new outbound session the transport service will use to | ||
1338 | * send data to the peer | ||
1339 | * | ||
1340 | * @param cls the `struct Plugin *` | ||
1341 | * @param address the address | ||
1342 | * @return the session or NULL of max connections exceeded | ||
1343 | */ | ||
1344 | static struct GNUNET_ATS_Session * | ||
1345 | wlan_plugin_get_session (void *cls, | ||
1346 | const struct GNUNET_HELLO_Address *address) | ||
1347 | { | ||
1348 | struct Plugin *plugin = cls; | ||
1349 | struct MacEndpoint *endpoint; | ||
1350 | |||
1351 | if (NULL == address) | ||
1352 | return NULL; | ||
1353 | if (sizeof(struct WlanAddress) != address->address_length) | ||
1354 | { | ||
1355 | GNUNET_break (0); | ||
1356 | return NULL; | ||
1357 | } | ||
1358 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1359 | "Service asked to create session for peer `%s' with MAC `%s'\n", | ||
1360 | GNUNET_i2s (&address->peer), | ||
1361 | wlan_plugin_address_to_string (NULL, | ||
1362 | address->address, | ||
1363 | address->address_length)); | ||
1364 | endpoint = create_macendpoint (plugin, | ||
1365 | (struct WlanAddress *) address->address); | ||
1366 | return get_session (endpoint, &address->peer); | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Function that can be used to force the plugin to disconnect | ||
1372 | * from the given peer and cancel all previous transmissions | ||
1373 | * (and their continuation). | ||
1374 | * | ||
1375 | * @param cls closure | ||
1376 | * @param target peer from which to disconnect | ||
1377 | */ | ||
1378 | static void | ||
1379 | wlan_plugin_disconnect_peer (void *cls, | ||
1380 | const struct GNUNET_PeerIdentity *target) | ||
1381 | { | ||
1382 | struct Plugin *plugin = cls; | ||
1383 | struct GNUNET_ATS_Session *session; | ||
1384 | struct MacEndpoint *endpoint; | ||
1385 | |||
1386 | for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next) | ||
1387 | for (session = endpoint->sessions_head; NULL != session; session = | ||
1388 | session->next) | ||
1389 | if (0 == memcmp (target, &session->target, | ||
1390 | sizeof(struct GNUNET_PeerIdentity))) | ||
1391 | { | ||
1392 | wlan_plugin_disconnect_session (plugin, session); | ||
1393 | break; /* inner-loop only (in case peer has another MAC as well!) */ | ||
1394 | } | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | /** | ||
1399 | * Function that can be used by the transport service to transmit | ||
1400 | * a message using the plugin. Note that in the case of a | ||
1401 | * peer disconnecting, the continuation MUST be called | ||
1402 | * prior to the disconnect notification itself. This function | ||
1403 | * will be called with this peer's HELLO message to initiate | ||
1404 | * a fresh connection to another peer. | ||
1405 | * | ||
1406 | * @param cls closure | ||
1407 | * @param session which session must be used | ||
1408 | * @param msgbuf the message to transmit | ||
1409 | * @param msgbuf_size number of bytes in @a msgbuf | ||
1410 | * @param priority how important is the message (most plugins will | ||
1411 | * ignore message priority and just FIFO) | ||
1412 | * @param to how long to wait at most for the transmission (does not | ||
1413 | * require plugins to discard the message after the timeout, | ||
1414 | * just advisory for the desired delay; most plugins will ignore | ||
1415 | * this as well) | ||
1416 | * @param cont continuation to call once the message has | ||
1417 | * been transmitted (or if the transport is ready | ||
1418 | * for the next transmission call; or if the | ||
1419 | * peer disconnected...); can be NULL | ||
1420 | * @param cont_cls closure for @a cont | ||
1421 | * @return number of bytes used (on the physical network, with overheads); | ||
1422 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | ||
1423 | * and does NOT mean that the message was not transmitted (DV) | ||
1424 | */ | ||
1425 | static ssize_t | ||
1426 | wlan_plugin_send (void *cls, | ||
1427 | struct GNUNET_ATS_Session *session, | ||
1428 | const char *msgbuf, size_t msgbuf_size, | ||
1429 | unsigned int priority, | ||
1430 | struct GNUNET_TIME_Relative to, | ||
1431 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | ||
1432 | { | ||
1433 | struct Plugin *plugin = cls; | ||
1434 | struct WlanHeader *wlanheader; | ||
1435 | size_t size = msgbuf_size + sizeof(struct WlanHeader); | ||
1436 | char buf[size] GNUNET_ALIGN; | ||
1437 | |||
1438 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1439 | "Transmitting %llu bytes of payload to peer `%s' (starting with %u byte message of type %u)\n", | ||
1440 | (unsigned long long) msgbuf_size, | ||
1441 | GNUNET_i2s (&session->target), | ||
1442 | (unsigned int) ntohs (((struct GNUNET_MessageHeader*) msgbuf)->size), | ||
1443 | (unsigned int) ntohs (((struct GNUNET_MessageHeader*) msgbuf)->type)); | ||
1444 | wlanheader = (struct WlanHeader *) buf; | ||
1445 | wlanheader->header.size = htons (msgbuf_size + sizeof(struct WlanHeader)); | ||
1446 | wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA); | ||
1447 | wlanheader->sender = *plugin->env->my_identity; | ||
1448 | wlanheader->target = session->target; | ||
1449 | wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size)); | ||
1450 | GNUNET_memcpy (&wlanheader[1], | ||
1451 | msgbuf, | ||
1452 | msgbuf_size); | ||
1453 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1454 | "# bytes currently in buffers", | ||
1455 | msgbuf_size, | ||
1456 | GNUNET_NO); | ||
1457 | send_with_fragmentation (session->mac, | ||
1458 | to, | ||
1459 | &session->target, | ||
1460 | &wlanheader->header, | ||
1461 | msgbuf_size, | ||
1462 | cont, cont_cls); | ||
1463 | return size; | ||
1464 | } | ||
1465 | |||
1466 | |||
1467 | /** | ||
1468 | * We have received data from the WLAN via some session. Process depending | ||
1469 | * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK). | ||
1470 | * | ||
1471 | * @param cls pointer to the plugin | ||
1472 | * @param client pointer to the session this message belongs to | ||
1473 | * @param hdr start of the message | ||
1474 | */ | ||
1475 | static int | ||
1476 | process_data (void *cls, | ||
1477 | void *client, | ||
1478 | const struct GNUNET_MessageHeader *hdr) | ||
1479 | { | ||
1480 | struct Plugin *plugin = cls; | ||
1481 | struct GNUNET_HELLO_Address *address; | ||
1482 | struct MacAndSession *mas = client; | ||
1483 | struct FragmentMessage *fm; | ||
1484 | struct GNUNET_PeerIdentity tmpsource; | ||
1485 | const struct WlanHeader *wlanheader; | ||
1486 | int ret; | ||
1487 | uint16_t msize; | ||
1488 | |||
1489 | msize = ntohs (hdr->size); | ||
1490 | |||
1491 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1492 | "# bytes received", | ||
1493 | msize, GNUNET_NO); | ||
1494 | |||
1495 | switch (ntohs (hdr->type)) | ||
1496 | { | ||
1497 | case GNUNET_MESSAGE_TYPE_HELLO: | ||
1498 | |||
1499 | if (GNUNET_OK != | ||
1500 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, | ||
1501 | &tmpsource)) | ||
1502 | { | ||
1503 | GNUNET_break_op (0); | ||
1504 | break; | ||
1505 | } | ||
1506 | if (NULL == mas->endpoint) | ||
1507 | { | ||
1508 | GNUNET_break (0); | ||
1509 | break; | ||
1510 | } | ||
1511 | |||
1512 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1513 | "Processing %u bytes of HELLO from peer `%s' at MAC %s\n", | ||
1514 | (unsigned int) msize, | ||
1515 | GNUNET_i2s (&tmpsource), | ||
1516 | wlan_plugin_address_to_string (NULL, | ||
1517 | &mas->endpoint->wlan_addr, | ||
1518 | sizeof(mas->endpoint->wlan_addr))); | ||
1519 | |||
1520 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1521 | _ ("# HELLO messages received"), 1, | ||
1522 | GNUNET_NO); | ||
1523 | address = GNUNET_HELLO_address_allocate (&tmpsource, | ||
1524 | PLUGIN_NAME, | ||
1525 | &mas->endpoint->wlan_addr, | ||
1526 | sizeof(mas->endpoint->wlan_addr), | ||
1527 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
1528 | mas->session = lookup_session (mas->endpoint, | ||
1529 | &tmpsource); | ||
1530 | if (NULL == mas->session) | ||
1531 | { | ||
1532 | mas->session = create_session (mas->endpoint, | ||
1533 | &tmpsource); | ||
1534 | plugin->env->session_start (plugin->env->cls, | ||
1535 | address, | ||
1536 | mas->session, | ||
1537 | scope); | ||
1538 | } | ||
1539 | plugin->env->receive (plugin->env->cls, | ||
1540 | address, | ||
1541 | mas->session, | ||
1542 | hdr); | ||
1543 | GNUNET_HELLO_address_free (address); | ||
1544 | break; | ||
1545 | |||
1546 | case GNUNET_MESSAGE_TYPE_FRAGMENT: | ||
1547 | if (NULL == mas->endpoint) | ||
1548 | { | ||
1549 | GNUNET_break (0); | ||
1550 | break; | ||
1551 | } | ||
1552 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1553 | "Processing %u bytes of FRAGMENT from MAC %s\n", | ||
1554 | (unsigned int) msize, | ||
1555 | wlan_plugin_address_to_string (NULL, | ||
1556 | &mas->endpoint->wlan_addr, | ||
1557 | sizeof(mas->endpoint->wlan_addr))); | ||
1558 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1559 | _ ("# fragments received"), | ||
1560 | 1, | ||
1561 | GNUNET_NO); | ||
1562 | (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag, | ||
1563 | hdr); | ||
1564 | break; | ||
1565 | |||
1566 | case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK: | ||
1567 | if (NULL == mas->endpoint) | ||
1568 | { | ||
1569 | GNUNET_break (0); | ||
1570 | break; | ||
1571 | } | ||
1572 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1573 | _ ("# ACKs received"), | ||
1574 | 1, GNUNET_NO); | ||
1575 | for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next) | ||
1576 | { | ||
1577 | ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr); | ||
1578 | if (GNUNET_OK == ret) | ||
1579 | { | ||
1580 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1581 | "Got last ACK, finished message transmission to `%s' (%p)\n", | ||
1582 | wlan_plugin_address_to_string (NULL, | ||
1583 | &mas->endpoint->wlan_addr, | ||
1584 | sizeof(mas->endpoint->wlan_addr)), | ||
1585 | fm); | ||
1586 | mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute ( | ||
1587 | MACENDPOINT_TIMEOUT); | ||
1588 | if (NULL != fm->cont) | ||
1589 | { | ||
1590 | fm->cont (fm->cont_cls, | ||
1591 | &fm->target, | ||
1592 | GNUNET_OK, | ||
1593 | fm->size_payload, | ||
1594 | fm->size_on_wire); | ||
1595 | fm->cont = NULL; | ||
1596 | } | ||
1597 | free_fragment_message (fm); | ||
1598 | break; | ||
1599 | } | ||
1600 | if (GNUNET_NO == ret) | ||
1601 | { | ||
1602 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1603 | "Got an ACK, message transmission to `%s' not yet finished\n", | ||
1604 | wlan_plugin_address_to_string (NULL, | ||
1605 | &mas->endpoint->wlan_addr, | ||
1606 | sizeof(mas->endpoint->wlan_addr))); | ||
1607 | break; | ||
1608 | } | ||
1609 | } | ||
1610 | if (NULL == fm) | ||
1611 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1612 | "ACK not matched against any active fragmentation with MAC `%s'\n", | ||
1613 | wlan_plugin_address_to_string (NULL, | ||
1614 | &mas->endpoint->wlan_addr, | ||
1615 | sizeof(mas->endpoint->wlan_addr))); | ||
1616 | break; | ||
1617 | |||
1618 | case GNUNET_MESSAGE_TYPE_WLAN_DATA: | ||
1619 | if (NULL == mas->endpoint) | ||
1620 | { | ||
1621 | GNUNET_break (0); | ||
1622 | break; | ||
1623 | } | ||
1624 | if (msize < sizeof(struct WlanHeader)) | ||
1625 | { | ||
1626 | GNUNET_break (0); | ||
1627 | break; | ||
1628 | } | ||
1629 | wlanheader = (const struct WlanHeader *) hdr; | ||
1630 | if (0 != memcmp (&wlanheader->target, | ||
1631 | plugin->env->my_identity, | ||
1632 | sizeof(struct GNUNET_PeerIdentity))) | ||
1633 | { | ||
1634 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1635 | "Data for `%s', not for me, ignoring\n", | ||
1636 | GNUNET_i2s (&wlanheader->target)); | ||
1637 | break; | ||
1638 | } | ||
1639 | if (ntohl (wlanheader->crc) != | ||
1640 | GNUNET_CRYPTO_crc32_n (&wlanheader[1], | ||
1641 | msize - sizeof(struct WlanHeader))) | ||
1642 | { | ||
1643 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1644 | _ ( | ||
1645 | "# DATA messages discarded due to CRC32 error"), | ||
1646 | 1, | ||
1647 | GNUNET_NO); | ||
1648 | break; | ||
1649 | } | ||
1650 | mas->session = lookup_session (mas->endpoint, | ||
1651 | &wlanheader->sender); | ||
1652 | if (NULL == mas->session) | ||
1653 | { | ||
1654 | mas->session = create_session (mas->endpoint, | ||
1655 | &wlanheader->sender); | ||
1656 | address = GNUNET_HELLO_address_allocate (&wlanheader->sender, | ||
1657 | PLUGIN_NAME, | ||
1658 | &mas->endpoint->wlan_addr, | ||
1659 | sizeof(struct WlanAddress), | ||
1660 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
1661 | plugin->env->session_start (plugin->env->cls, | ||
1662 | address, | ||
1663 | mas->session, | ||
1664 | scope); | ||
1665 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1666 | "Notifying transport about peer `%s''s new session %p \n", | ||
1667 | GNUNET_i2s (&wlanheader->sender), | ||
1668 | mas->session); | ||
1669 | GNUNET_HELLO_address_free (address); | ||
1670 | } | ||
1671 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1672 | "Processing %u bytes of DATA from peer `%s'\n", | ||
1673 | (unsigned int) msize, | ||
1674 | GNUNET_i2s (&wlanheader->sender)); | ||
1675 | mas->session->timeout = GNUNET_TIME_relative_to_absolute ( | ||
1676 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); | ||
1677 | (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer, | ||
1678 | mas, | ||
1679 | (const char *) &wlanheader[1], | ||
1680 | msize - sizeof(struct WlanHeader), | ||
1681 | GNUNET_YES, | ||
1682 | GNUNET_NO); | ||
1683 | break; | ||
1684 | |||
1685 | default: | ||
1686 | if (NULL == mas->endpoint) | ||
1687 | { | ||
1688 | GNUNET_break (0); | ||
1689 | break; | ||
1690 | } | ||
1691 | if (NULL == mas->session) | ||
1692 | { | ||
1693 | GNUNET_break (0); | ||
1694 | break; | ||
1695 | } | ||
1696 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1697 | "Received packet with %u bytes of type %u from peer %s\n", | ||
1698 | (unsigned int) msize, | ||
1699 | (unsigned int) ntohs (hdr->type), | ||
1700 | GNUNET_i2s (&mas->session->target)); | ||
1701 | plugin->env->receive (plugin->env->cls, | ||
1702 | mas->session->address, | ||
1703 | mas->session, | ||
1704 | hdr); | ||
1705 | break; | ||
1706 | } | ||
1707 | return GNUNET_OK; | ||
1708 | } | ||
1709 | |||
1710 | |||
1711 | /** | ||
1712 | * Task to (periodically) send a HELLO beacon | ||
1713 | * | ||
1714 | * @param cls pointer to the plugin struct | ||
1715 | */ | ||
1716 | static void | ||
1717 | send_hello_beacon (void *cls) | ||
1718 | { | ||
1719 | struct Plugin *plugin = cls; | ||
1720 | uint16_t size; | ||
1721 | uint16_t hello_size; | ||
1722 | struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader; | ||
1723 | const struct GNUNET_MessageHeader *hello; | ||
1724 | |||
1725 | hello = plugin->env->get_our_hello (); | ||
1726 | if (NULL != hello) | ||
1727 | { | ||
1728 | hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); | ||
1729 | GNUNET_assert (sizeof(struct WlanHeader) + hello_size <= WLAN_MTU); | ||
1730 | size = sizeof(struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) | ||
1731 | + hello_size; | ||
1732 | { | ||
1733 | char buf[size] GNUNET_ALIGN; | ||
1734 | |||
1735 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1736 | "Sending %u byte HELLO beacon\n", | ||
1737 | (unsigned int) size); | ||
1738 | radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf; | ||
1739 | get_radiotap_header (NULL, radioHeader, size); | ||
1740 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1741 | "Broadcasting %u bytes of data to MAC `%s'\n", | ||
1742 | (unsigned int) size, | ||
1743 | mac_to_string (&bc_all_mac)); | ||
1744 | get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size); | ||
1745 | GNUNET_memcpy (&radioHeader[1], hello, hello_size); | ||
1746 | if (NULL != | ||
1747 | GNUNET_HELPER_send (plugin->suid_helper, | ||
1748 | &radioHeader->header, | ||
1749 | GNUNET_YES /* can drop */, | ||
1750 | NULL, NULL)) | ||
1751 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1752 | _ ("# HELLO beacons sent"), | ||
1753 | 1, GNUNET_NO); | ||
1754 | } | ||
1755 | } | ||
1756 | plugin->beacon_task = | ||
1757 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1758 | (HELLO_BEACON_SCALING_FACTOR, | ||
1759 | plugin->mac_count + 1), | ||
1760 | &send_hello_beacon, | ||
1761 | plugin); | ||
1762 | } | ||
1763 | |||
1764 | |||
1765 | /** | ||
1766 | * Function used for to process the data from the suid process | ||
1767 | * | ||
1768 | * @param cls the plugin handle | ||
1769 | * @param hdr header of the GNUNET_MessageHeader | ||
1770 | */ | ||
1771 | static int | ||
1772 | handle_helper_message (void *cls, | ||
1773 | const struct GNUNET_MessageHeader *hdr) | ||
1774 | { | ||
1775 | struct Plugin *plugin = cls; | ||
1776 | struct GNUNET_HELLO_Address *my_address; | ||
1777 | const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo; | ||
1778 | const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm; | ||
1779 | struct WlanAddress wa; | ||
1780 | struct MacAndSession mas; | ||
1781 | uint16_t msize; | ||
1782 | struct FragmentMessage *fm; | ||
1783 | struct MacEndpoint *endpoint; | ||
1784 | |||
1785 | msize = ntohs (hdr->size); | ||
1786 | switch (ntohs (hdr->type)) | ||
1787 | { | ||
1788 | case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL: | ||
1789 | if (msize != sizeof(struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)) | ||
1790 | { | ||
1791 | GNUNET_break (0); | ||
1792 | break; | ||
1793 | } | ||
1794 | cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr; | ||
1795 | if (GNUNET_YES == plugin->have_mac) | ||
1796 | { | ||
1797 | if (0 == memcmp (&plugin->mac_address, | ||
1798 | &cm->mac, | ||
1799 | sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress))) | ||
1800 | break; /* no change */ | ||
1801 | /* remove old address */ | ||
1802 | memset (&wa, 0, sizeof(struct WlanAddress)); | ||
1803 | wa.mac = plugin->mac_address; | ||
1804 | wa.options = htonl (plugin->options); | ||
1805 | my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, | ||
1806 | PLUGIN_NAME, | ||
1807 | &wa, sizeof(wa), | ||
1808 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
1809 | plugin->env->notify_address (plugin->env->cls, | ||
1810 | GNUNET_NO, | ||
1811 | my_address); | ||
1812 | GNUNET_HELLO_address_free (my_address); | ||
1813 | plugin->mac_address = cm->mac; | ||
1814 | } | ||
1815 | else | ||
1816 | { | ||
1817 | plugin->mac_address = cm->mac; | ||
1818 | plugin->have_mac = GNUNET_YES; | ||
1819 | for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = | ||
1820 | endpoint->next) | ||
1821 | { | ||
1822 | for (fm = endpoint->sending_messages_head; NULL != fm; fm = fm->next) | ||
1823 | { | ||
1824 | if (NULL != fm->fragcontext) | ||
1825 | { | ||
1826 | GNUNET_break (0); /* should not happen */ | ||
1827 | continue; | ||
1828 | } | ||
1829 | fm->fragcontext = | ||
1830 | GNUNET_FRAGMENT_context_create (plugin->env->stats, | ||
1831 | WLAN_MTU, | ||
1832 | &plugin->tracker, | ||
1833 | fm->macendpoint->msg_delay, | ||
1834 | fm->macendpoint->ack_delay, | ||
1835 | fm->msg, | ||
1836 | &transmit_fragment, fm); | ||
1837 | GNUNET_free (fm->msg); | ||
1838 | fm->msg = NULL; | ||
1839 | } | ||
1840 | } | ||
1841 | GNUNET_break (NULL == plugin->beacon_task); | ||
1842 | plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon, | ||
1843 | plugin); | ||
1844 | } | ||
1845 | |||
1846 | memset (&wa, 0, sizeof(struct WlanAddress)); | ||
1847 | wa.mac = plugin->mac_address; | ||
1848 | wa.options = htonl (plugin->options); | ||
1849 | my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, | ||
1850 | PLUGIN_NAME, | ||
1851 | &wa, sizeof(wa), | ||
1852 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
1853 | |||
1854 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1855 | "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n", | ||
1856 | mac_to_string (&cm->mac), | ||
1857 | GNUNET_i2s (plugin->env->my_identity)); | ||
1858 | plugin->env->notify_address (plugin->env->cls, | ||
1859 | GNUNET_YES, | ||
1860 | my_address); | ||
1861 | GNUNET_HELLO_address_free (my_address); | ||
1862 | break; | ||
1863 | |||
1864 | case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER: | ||
1865 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1866 | "Got data message from helper with %u bytes\n", | ||
1867 | msize); | ||
1868 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1869 | _ ("# DATA messages received"), 1, | ||
1870 | GNUNET_NO); | ||
1871 | if (msize < sizeof(struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)) | ||
1872 | { | ||
1873 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1874 | "Size of packet is too small (%llu bytes < %llu)\n", | ||
1875 | (unsigned long long) msize, | ||
1876 | (unsigned long long) sizeof(struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)); | ||
1877 | break; | ||
1878 | } | ||
1879 | rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr; | ||
1880 | |||
1881 | /* check if message is actually for us */ | ||
1882 | if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet, | ||
1883 | sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress))) | ||
1884 | { | ||
1885 | /* Not the GNUnet BSSID */ | ||
1886 | break; | ||
1887 | } | ||
1888 | if ((0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac, | ||
1889 | sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress))) && | ||
1890 | (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address, | ||
1891 | sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress)))) | ||
1892 | { | ||
1893 | /* Neither broadcast nor specifically for us */ | ||
1894 | break; | ||
1895 | } | ||
1896 | if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address, | ||
1897 | sizeof(struct GNUNET_TRANSPORT_WLAN_MacAddress))) | ||
1898 | { | ||
1899 | /* packet is FROM us, thus not FOR us */ | ||
1900 | break; | ||
1901 | } | ||
1902 | |||
1903 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1904 | _ ("# DATA messages processed"), | ||
1905 | 1, GNUNET_NO); | ||
1906 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1907 | "Receiving %u bytes of data from MAC `%s'\n", | ||
1908 | (unsigned int) (msize - sizeof(struct | ||
1909 | GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)), | ||
1910 | mac_to_string (&rxinfo->frame.addr2)); | ||
1911 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1912 | "Receiving %u bytes of data to MAC `%s'\n", | ||
1913 | (unsigned int) (msize - sizeof(struct | ||
1914 | GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)), | ||
1915 | mac_to_string (&rxinfo->frame.addr1)); | ||
1916 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1917 | "Receiving %u bytes of data with BSSID MAC `%s'\n", | ||
1918 | (unsigned int) (msize - sizeof(struct | ||
1919 | GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)), | ||
1920 | mac_to_string (&rxinfo->frame.addr3)); | ||
1921 | wa.mac = rxinfo->frame.addr2; | ||
1922 | wa.options = htonl (0); | ||
1923 | mas.endpoint = create_macendpoint (plugin, &wa); | ||
1924 | mas.session = NULL; | ||
1925 | (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer, | ||
1926 | &mas, | ||
1927 | (const char *) &rxinfo[1], | ||
1928 | msize - sizeof(struct | ||
1929 | GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage), | ||
1930 | GNUNET_YES, GNUNET_NO); | ||
1931 | break; | ||
1932 | |||
1933 | default: | ||
1934 | GNUNET_break (0); | ||
1935 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1936 | "Unexpected message of type %u (%u bytes)", | ||
1937 | ntohs (hdr->type), | ||
1938 | ntohs (hdr->size)); | ||
1939 | break; | ||
1940 | } | ||
1941 | return GNUNET_OK; | ||
1942 | } | ||
1943 | |||
1944 | |||
1945 | /** | ||
1946 | * Another peer has suggested an address for this | ||
1947 | * peer and transport plugin. Check that this could be a valid | ||
1948 | * address. If so, consider adding it to the list | ||
1949 | * of addresses. | ||
1950 | * | ||
1951 | * @param cls closure | ||
1952 | * @param addr pointer to the address | ||
1953 | * @param addrlen length of @a addr | ||
1954 | * @return #GNUNET_OK if this is a plausible address for this peer | ||
1955 | * and transport | ||
1956 | */ | ||
1957 | static int | ||
1958 | wlan_plugin_address_suggested (void *cls, | ||
1959 | const void *addr, | ||
1960 | size_t addrlen) | ||
1961 | { | ||
1962 | struct Plugin *plugin = cls; | ||
1963 | struct WlanAddress *wa = (struct WlanAddress *) addr; | ||
1964 | |||
1965 | if (addrlen != sizeof(struct WlanAddress)) | ||
1966 | { | ||
1967 | GNUNET_break_op (0); | ||
1968 | return GNUNET_SYSERR; | ||
1969 | } | ||
1970 | if (GNUNET_YES != plugin->have_mac) | ||
1971 | { | ||
1972 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1973 | "Rejecting MAC `%s': I don't know my MAC!\n", | ||
1974 | mac_to_string (addr)); | ||
1975 | return GNUNET_NO; /* don't know my MAC */ | ||
1976 | } | ||
1977 | if (0 != memcmp (&wa->mac, | ||
1978 | &plugin->mac_address, | ||
1979 | sizeof(wa->mac))) | ||
1980 | { | ||
1981 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1982 | "Rejecting MAC `%s': not my MAC!\n", | ||
1983 | mac_to_string (addr)); | ||
1984 | return GNUNET_NO; /* not my MAC */ | ||
1985 | } | ||
1986 | return GNUNET_OK; | ||
1987 | } | ||
1988 | |||
1989 | |||
1990 | /** | ||
1991 | * Convert the transports address to a nice, human-readable format. | ||
1992 | * | ||
1993 | * @param cls closure | ||
1994 | * @param type name of the transport that generated the address | ||
1995 | * @param addr one of the addresses of the host, NULL for the last address | ||
1996 | * the specific address format depends on the transport | ||
1997 | * @param addrlen length of the address | ||
1998 | * @param numeric should (IP) addresses be displayed in numeric form? | ||
1999 | * @param timeout after how long should we give up? | ||
2000 | * @param asc function to call on each string | ||
2001 | * @param asc_cls closure for @a asc | ||
2002 | */ | ||
2003 | static void | ||
2004 | wlan_plugin_address_pretty_printer (void *cls, | ||
2005 | const char *type, | ||
2006 | const void *addr, | ||
2007 | size_t addrlen, | ||
2008 | int numeric, | ||
2009 | struct GNUNET_TIME_Relative timeout, | ||
2010 | GNUNET_TRANSPORT_AddressStringCallback asc, | ||
2011 | void *asc_cls) | ||
2012 | { | ||
2013 | const char *ret; | ||
2014 | |||
2015 | if (sizeof(struct WlanAddress) == addrlen) | ||
2016 | ret = wlan_plugin_address_to_string (NULL, | ||
2017 | addr, | ||
2018 | addrlen); | ||
2019 | else | ||
2020 | ret = NULL; | ||
2021 | asc (asc_cls, | ||
2022 | ret, | ||
2023 | (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK); | ||
2024 | asc (asc_cls, NULL, GNUNET_OK); | ||
2025 | } | ||
2026 | |||
2027 | |||
2028 | /** | ||
2029 | * Exit point from the plugin. | ||
2030 | * | ||
2031 | * @param cls pointer to the api struct | ||
2032 | */ | ||
2033 | void * | ||
2034 | LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) | ||
2035 | { | ||
2036 | struct WlanAddress wa; | ||
2037 | struct GNUNET_HELLO_Address *address; | ||
2038 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | ||
2039 | struct Plugin *plugin = api->cls; | ||
2040 | struct MacEndpoint *endpoint; | ||
2041 | struct MacEndpoint *endpoint_next; | ||
2042 | |||
2043 | if (NULL == plugin) | ||
2044 | { | ||
2045 | GNUNET_free (api); | ||
2046 | return NULL; | ||
2047 | } | ||
2048 | if (GNUNET_YES == plugin->have_mac) | ||
2049 | { | ||
2050 | memset (&wa, 0, sizeof(wa)); | ||
2051 | wa.options = htonl (plugin->options); | ||
2052 | wa.mac = plugin->mac_address; | ||
2053 | address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, | ||
2054 | PLUGIN_NAME, | ||
2055 | &wa, sizeof(struct WlanAddress), | ||
2056 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
2057 | |||
2058 | plugin->env->notify_address (plugin->env->cls, | ||
2059 | GNUNET_NO, | ||
2060 | address); | ||
2061 | plugin->have_mac = GNUNET_NO; | ||
2062 | GNUNET_HELLO_address_free (address); | ||
2063 | } | ||
2064 | |||
2065 | if (NULL != plugin->beacon_task) | ||
2066 | { | ||
2067 | GNUNET_SCHEDULER_cancel (plugin->beacon_task); | ||
2068 | plugin->beacon_task = NULL; | ||
2069 | } | ||
2070 | if (NULL != plugin->suid_helper) | ||
2071 | { | ||
2072 | GNUNET_HELPER_stop (plugin->suid_helper, | ||
2073 | GNUNET_NO); | ||
2074 | plugin->suid_helper = NULL; | ||
2075 | } | ||
2076 | endpoint_next = plugin->mac_head; | ||
2077 | while (NULL != (endpoint = endpoint_next)) | ||
2078 | { | ||
2079 | endpoint_next = endpoint->next; | ||
2080 | free_macendpoint (endpoint); | ||
2081 | } | ||
2082 | if (NULL != plugin->fragment_data_tokenizer) | ||
2083 | { | ||
2084 | GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer); | ||
2085 | plugin->fragment_data_tokenizer = NULL; | ||
2086 | } | ||
2087 | if (NULL != plugin->wlan_header_payload_tokenizer) | ||
2088 | { | ||
2089 | GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer); | ||
2090 | plugin->wlan_header_payload_tokenizer = NULL; | ||
2091 | } | ||
2092 | if (NULL != plugin->helper_payload_tokenizer) | ||
2093 | { | ||
2094 | GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer); | ||
2095 | plugin->helper_payload_tokenizer = NULL; | ||
2096 | } | ||
2097 | GNUNET_free (plugin->wlan_interface); | ||
2098 | GNUNET_free (plugin); | ||
2099 | GNUNET_free (api); | ||
2100 | return NULL; | ||
2101 | } | ||
2102 | |||
2103 | |||
2104 | /** | ||
2105 | * Function called to convert a string address to | ||
2106 | * a binary address. | ||
2107 | * | ||
2108 | * @param cls closure (`struct Plugin *`) | ||
2109 | * @param addr string address | ||
2110 | * @param addrlen length of the address | ||
2111 | * @param buf location to store the buffer | ||
2112 | * @param added location to store the number of bytes in the buffer. | ||
2113 | * If the function returns #GNUNET_SYSERR, its contents are undefined. | ||
2114 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
2115 | */ | ||
2116 | static int | ||
2117 | wlan_plugin_string_to_address (void *cls, | ||
2118 | const char *addr, | ||
2119 | uint16_t addrlen, | ||
2120 | void **buf, | ||
2121 | size_t *added) | ||
2122 | { | ||
2123 | struct WlanAddress *wa; | ||
2124 | unsigned int a[6]; | ||
2125 | unsigned int i; | ||
2126 | char plugin[5]; | ||
2127 | uint32_t options; | ||
2128 | |||
2129 | if ((NULL == addr) || (0 == addrlen)) | ||
2130 | { | ||
2131 | GNUNET_break (0); | ||
2132 | return GNUNET_SYSERR; | ||
2133 | } | ||
2134 | if ('\0' != addr[addrlen - 1]) | ||
2135 | { | ||
2136 | GNUNET_break (0); | ||
2137 | return GNUNET_SYSERR; | ||
2138 | } | ||
2139 | if (strlen (addr) != addrlen - 1) | ||
2140 | { | ||
2141 | GNUNET_break (0); | ||
2142 | return GNUNET_SYSERR; | ||
2143 | } | ||
2144 | |||
2145 | if (8 != sscanf (addr, | ||
2146 | "%4s.%u.%X:%X:%X:%X:%X:%X", | ||
2147 | plugin, &options, | ||
2148 | &a[0], &a[1], &a[2], | ||
2149 | &a[3], &a[4], &a[5])) | ||
2150 | { | ||
2151 | GNUNET_break (0); | ||
2152 | return GNUNET_SYSERR; | ||
2153 | } | ||
2154 | wa = GNUNET_new (struct WlanAddress); | ||
2155 | for (i = 0; i < 6; i++) | ||
2156 | wa->mac.mac[i] = a[i]; | ||
2157 | wa->options = htonl (0); | ||
2158 | *buf = wa; | ||
2159 | *added = sizeof(struct WlanAddress); | ||
2160 | return GNUNET_OK; | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | /** | ||
2165 | * Begin monitoring sessions of a plugin. There can only | ||
2166 | * be one active monitor per plugin (i.e. if there are | ||
2167 | * multiple monitors, the transport service needs to | ||
2168 | * multiplex the generated events over all of them). | ||
2169 | * | ||
2170 | * @param cls closure of the plugin | ||
2171 | * @param sic callback to invoke, NULL to disable monitor; | ||
2172 | * plugin will being by iterating over all active | ||
2173 | * sessions immediately and then enter monitor mode | ||
2174 | * @param sic_cls closure for @a sic | ||
2175 | */ | ||
2176 | static void | ||
2177 | wlan_plugin_setup_monitor (void *cls, | ||
2178 | GNUNET_TRANSPORT_SessionInfoCallback sic, | ||
2179 | void *sic_cls) | ||
2180 | { | ||
2181 | struct Plugin *plugin = cls; | ||
2182 | struct MacEndpoint *mac; | ||
2183 | struct GNUNET_ATS_Session *session; | ||
2184 | |||
2185 | plugin->sic = sic; | ||
2186 | plugin->sic_cls = sic_cls; | ||
2187 | if (NULL != sic) | ||
2188 | { | ||
2189 | for (mac = plugin->mac_head; NULL != mac; mac = mac->next) | ||
2190 | for (session = mac->sessions_head; NULL != session; session = | ||
2191 | session->next) | ||
2192 | { | ||
2193 | notify_session_monitor (plugin, | ||
2194 | session, | ||
2195 | GNUNET_TRANSPORT_SS_INIT); | ||
2196 | notify_session_monitor (plugin, | ||
2197 | session, | ||
2198 | GNUNET_TRANSPORT_SS_UP); | ||
2199 | } | ||
2200 | sic (sic_cls, NULL, NULL); | ||
2201 | } | ||
2202 | } | ||
2203 | |||
2204 | |||
2205 | /** | ||
2206 | * Function that will be called whenever the transport service wants to | ||
2207 | * notify the plugin that a session is still active and in use and | ||
2208 | * therefore the session timeout for this session has to be updated | ||
2209 | * | ||
2210 | * @param cls closure | ||
2211 | * @param peer which peer was the session for | ||
2212 | * @param session which session is being updated | ||
2213 | */ | ||
2214 | static void | ||
2215 | wlan_plugin_update_session_timeout (void *cls, | ||
2216 | const struct GNUNET_PeerIdentity *peer, | ||
2217 | struct GNUNET_ATS_Session *session) | ||
2218 | { | ||
2219 | GNUNET_assert (NULL != session->timeout_task); | ||
2220 | session->timeout = GNUNET_TIME_relative_to_absolute ( | ||
2221 | GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); | ||
2222 | } | ||
2223 | |||
2224 | |||
2225 | /** | ||
2226 | * Function that will be called whenever the transport service wants to | ||
2227 | * notify the plugin that the inbound quota changed and that the plugin | ||
2228 | * should update it's delay for the next receive value | ||
2229 | * | ||
2230 | * @param cls closure | ||
2231 | * @param peer which peer was the session for | ||
2232 | * @param session which session is being updated | ||
2233 | * @param delay new delay to use for receiving | ||
2234 | */ | ||
2235 | static void | ||
2236 | wlan_plugin_update_inbound_delay (void *cls, | ||
2237 | const struct GNUNET_PeerIdentity *peer, | ||
2238 | struct GNUNET_ATS_Session *session, | ||
2239 | struct GNUNET_TIME_Relative delay) | ||
2240 | { | ||
2241 | /* does nothing, as inbound delay is not supported by WLAN */ | ||
2242 | } | ||
2243 | |||
2244 | |||
2245 | /** | ||
2246 | * Entry point for the plugin. | ||
2247 | * | ||
2248 | * @param cls closure, the `struct GNUNET_TRANSPORT_PluginEnvironment *` | ||
2249 | * @return the `struct GNUNET_TRANSPORT_PluginFunctions *` or NULL on error | ||
2250 | */ | ||
2251 | void * | ||
2252 | LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) | ||
2253 | { | ||
2254 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; | ||
2255 | struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
2256 | struct Plugin *plugin; | ||
2257 | char *wlan_interface; | ||
2258 | unsigned long long testmode; | ||
2259 | char *binary; | ||
2260 | |||
2261 | /* check for 'special' mode */ | ||
2262 | if (NULL == env->receive) | ||
2263 | { | ||
2264 | /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully | ||
2265 | initialize the plugin or the API */ | ||
2266 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); | ||
2267 | api->cls = NULL; | ||
2268 | api->address_pretty_printer = &wlan_plugin_address_pretty_printer; | ||
2269 | api->address_to_string = &wlan_plugin_address_to_string; | ||
2270 | api->string_to_address = &wlan_plugin_string_to_address; | ||
2271 | return api; | ||
2272 | } | ||
2273 | |||
2274 | testmode = 0; | ||
2275 | /* check configuration */ | ||
2276 | if ((GNUNET_YES == | ||
2277 | GNUNET_CONFIGURATION_have_value (env->cfg, | ||
2278 | CONFIG_NAME, | ||
2279 | "TESTMODE")) && | ||
2280 | ((GNUNET_SYSERR == | ||
2281 | GNUNET_CONFIGURATION_get_value_number (env->cfg, | ||
2282 | CONFIG_NAME, | ||
2283 | "TESTMODE", | ||
2284 | &testmode)) || | ||
2285 | (testmode > 2))) | ||
2286 | { | ||
2287 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
2288 | CONFIG_NAME, | ||
2289 | "TESTMODE"); | ||
2290 | return NULL; | ||
2291 | } | ||
2292 | binary = GNUNET_OS_get_libexec_binary_path (HELPER_NAME); | ||
2293 | if ((0 == testmode) && | ||
2294 | (GNUNET_YES != | ||
2295 | GNUNET_OS_check_helper_binary (binary, | ||
2296 | GNUNET_YES, | ||
2297 | NULL))) | ||
2298 | { | ||
2299 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
2300 | _ ("Helper binary `%s' not SUID, cannot run WLAN transport\n"), | ||
2301 | HELPER_NAME); | ||
2302 | GNUNET_free (binary); | ||
2303 | return NULL; | ||
2304 | } | ||
2305 | GNUNET_free (binary); | ||
2306 | if (GNUNET_YES != | ||
2307 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2308 | CONFIG_NAME, | ||
2309 | "INTERFACE", | ||
2310 | &wlan_interface)) | ||
2311 | { | ||
2312 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
2313 | CONFIG_NAME, | ||
2314 | "INTERFACE"); | ||
2315 | return NULL; | ||
2316 | } | ||
2317 | |||
2318 | plugin = GNUNET_new (struct Plugin); | ||
2319 | plugin->wlan_interface = wlan_interface; | ||
2320 | plugin->env = env; | ||
2321 | GNUNET_STATISTICS_set (plugin->env->stats, | ||
2322 | _ ("# sessions allocated"), | ||
2323 | 0, GNUNET_NO); | ||
2324 | GNUNET_STATISTICS_set (plugin->env->stats, | ||
2325 | _ ("# MAC endpoints allocated"), | ||
2326 | 0, 0); | ||
2327 | GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, NULL, NULL, | ||
2328 | GNUNET_BANDWIDTH_value_init (100 * 1024 | ||
2329 | * 1024 / 8), | ||
2330 | 100); | ||
2331 | plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, | ||
2332 | plugin); | ||
2333 | plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create ( | ||
2334 | &process_data, | ||
2335 | plugin); | ||
2336 | plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, | ||
2337 | plugin); | ||
2338 | |||
2339 | plugin->options = 0; | ||
2340 | |||
2341 | /* some compilers do not like switch on 'long long'... */ | ||
2342 | switch ((unsigned int) testmode) | ||
2343 | { | ||
2344 | case 0: /* normal */ | ||
2345 | plugin->helper_argv[0] = (char *) HELPER_NAME; | ||
2346 | plugin->helper_argv[1] = wlan_interface; | ||
2347 | plugin->helper_argv[2] = NULL; | ||
2348 | plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, | ||
2349 | HELPER_NAME, | ||
2350 | plugin->helper_argv, | ||
2351 | &handle_helper_message, | ||
2352 | NULL, | ||
2353 | plugin); | ||
2354 | break; | ||
2355 | |||
2356 | case 1: /* testmode, peer 1 */ | ||
2357 | plugin->helper_argv[0] = (char *) DUMMY_HELPER_NAME; | ||
2358 | plugin->helper_argv[1] = (char *) "1"; | ||
2359 | plugin->helper_argv[2] = NULL; | ||
2360 | plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, | ||
2361 | DUMMY_HELPER_NAME, | ||
2362 | plugin->helper_argv, | ||
2363 | &handle_helper_message, | ||
2364 | NULL, | ||
2365 | plugin); | ||
2366 | break; | ||
2367 | |||
2368 | case 2: /* testmode, peer 2 */ | ||
2369 | plugin->helper_argv[0] = (char *) DUMMY_HELPER_NAME; | ||
2370 | plugin->helper_argv[1] = (char *) "2"; | ||
2371 | plugin->helper_argv[2] = NULL; | ||
2372 | plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, | ||
2373 | DUMMY_HELPER_NAME, | ||
2374 | plugin->helper_argv, | ||
2375 | &handle_helper_message, | ||
2376 | NULL, | ||
2377 | plugin); | ||
2378 | break; | ||
2379 | |||
2380 | default: | ||
2381 | GNUNET_assert (0); | ||
2382 | } | ||
2383 | |||
2384 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); | ||
2385 | api->cls = plugin; | ||
2386 | api->send = &wlan_plugin_send; | ||
2387 | api->get_session = &wlan_plugin_get_session; | ||
2388 | api->disconnect_peer = &wlan_plugin_disconnect_peer; | ||
2389 | api->disconnect_session = &wlan_plugin_disconnect_session; | ||
2390 | api->query_keepalive_factor = &wlan_plugin_query_keepalive_factor; | ||
2391 | api->address_pretty_printer = &wlan_plugin_address_pretty_printer; | ||
2392 | api->check_address = &wlan_plugin_address_suggested; | ||
2393 | api->address_to_string = &wlan_plugin_address_to_string; | ||
2394 | api->string_to_address = &wlan_plugin_string_to_address; | ||
2395 | api->get_network = &wlan_plugin_get_network; | ||
2396 | api->get_network_for_address = &wlan_plugin_get_network_for_address; | ||
2397 | api->update_session_timeout = &wlan_plugin_update_session_timeout; | ||
2398 | api->update_inbound_delay = &wlan_plugin_update_inbound_delay; | ||
2399 | api->setup_monitor = &wlan_plugin_setup_monitor; | ||
2400 | return api; | ||
2401 | } | ||
2402 | |||
2403 | |||
2404 | /* end of plugin_transport_wlan.c */ | ||