2 This file is part of GNUnet
3 Copyright (C) 2010-2014 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file transport/plugin_transport_wlan.c
23 * @brief transport plugin for wlan and/or bluetooth
24 * @author David Brodski
25 * @author Christian Grothoff
27 * BUILD_WLAN or BUILD_BLUETOOTH must be defined such that the respective
28 * variant of this code is compiled.
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"
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__)
54 * time out of a mac endpoint
56 #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
59 * We reduce the frequence of HELLO beacons in relation to
60 * the number of MAC addresses currently visible to us.
61 * This is the multiplication factor.
63 #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
68 /* begin case bluetooth */
70 #define PLUGIN_NAME "bluetooth"
71 #define CONFIG_NAME "transport-bluetooth"
72 #define HELPER_NAME "gnunet-helper-transport-bluetooth"
73 /* yes, this is correct, we use the same dummy driver as 'wlan' */
74 #define DUMMY_HELPER_NAME "gnunet-helper-transport-wlan-dummy"
75 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_bluetooth_init
76 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_bluetooth_done
77 #define LOG(kind,...) GNUNET_log_from (kind, "transport-bluetooth",__VA_ARGS__)
80 * time out of a mac endpoint
82 #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 60)
86 * We reduce the frequence of HELLO beacons in relation to
87 * the number of MAC addresses currently visible to us.
88 * This is the multiplication factor.
90 #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
92 /* end case bluetooth */
94 #error need to build wlan or bluetooth
100 * Functions with this signature are called whenever a
101 * complete message is received by the tokenizer.
103 * Do not call #GNUNET_SERVER_mst_destroy from within
104 * the scope of this callback.
107 * @param client identification of the client
108 * @param message the actual message
109 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
112 (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls,
114 const struct GNUNET_MessageHeader *message);
117 /* Include legacy message stream tokenizer that was removed from util (for now) */
118 #include "tcp_server_mst_legacy.c"
122 * Max size of packet (that we give to the WLAN driver for transmission)
124 #define WLAN_MTU 1430
128 * Which network scope do we belong to?
131 static const enum GNUNET_ATS_Network_Type scope = GNUNET_ATS_NET_WLAN;
133 static const enum GNUNET_ATS_Network_Type scope = GNUNET_ATS_NET_BT;
138 * Maximum number of messages in defragmentation queue per MAC
140 #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2
143 * Link layer control fields for better compatibility
144 * (i.e. GNUnet over WLAN is not IP-over-WLAN).
146 #define WLAN_LLC_DSAP_FIELD 0x1f
147 #define WLAN_LLC_SSAP_FIELD 0x1f
150 GNUNET_NETWORK_STRUCT_BEGIN
152 * Header for messages which need fragmentation. This is the format of
153 * a message we obtain AFTER defragmentation. We then need to check
154 * the CRC and then tokenize the payload and pass it to the
155 * 'receive' callback.
161 * Message type is #GNUNET_MESSAGE_TYPE_WLAN_DATA.
163 struct GNUNET_MessageHeader header;
166 * CRC32 checksum (only over the payload), in NBO.
168 uint32_t crc GNUNET_PACKED;
171 * Sender of the message.
173 struct GNUNET_PeerIdentity sender;
176 * Target of the message.
178 struct GNUNET_PeerIdentity target;
180 /* followed by payload, possibly including
181 multiple messages! */
187 * Address format for WLAN.
192 * Options set for the WLAN, in NBO.
194 uint32_t options GNUNET_PACKED;
197 * WLAN addresses using MACs.
199 struct GNUNET_TRANSPORT_WLAN_MacAddress mac;
203 GNUNET_NETWORK_STRUCT_END
207 * Information kept for each message that is yet to be fragmented and
210 struct PendingMessage
213 * next entry in the DLL
215 struct PendingMessage *next;
218 * previous entry in the DLL
220 struct PendingMessage *prev;
223 * The pending message
225 struct WlanHeader *msg;
228 * Continuation function to call once the message
229 * has been sent. Can be NULL if there is no
230 * continuation to call.
232 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
235 * Cls for @e transmit_cont
237 void *transmit_cont_cls;
240 * Timeout task (for this message).
242 struct GNUNET_SCHEDULER_Task * timeout_task;
248 * Session handle for connections with other peers.
250 struct GNUNET_ATS_Session
253 * To whom are we talking to (set to our identity
254 * if we are still waiting for the welcome message)
256 struct GNUNET_PeerIdentity target;
259 * We keep all sessions in a DLL at their respective
260 * `struct MACEndpoint *`.
262 struct GNUNET_ATS_Session *next;
265 * We keep all sessions in a DLL at their respective
266 * `struct MACEndpoint *`.
268 struct GNUNET_ATS_Session *prev;
271 * MAC endpoint with the address of this peer.
273 struct MacEndpoint *mac;
276 * Address associated with this session and MAC endpoint
278 struct GNUNET_HELLO_Address *address;
281 * When should this session time out?
283 struct GNUNET_TIME_Absolute timeout;
286 * Timeout task (for the session).
288 struct GNUNET_SCHEDULER_Task * timeout_task;
294 * Struct for messages that are being fragmented in a MAC's transmission queue.
296 struct FragmentMessage
300 * This is a doubly-linked list.
302 struct FragmentMessage *next;
305 * This is a doubly-linked list.
307 struct FragmentMessage *prev;
310 * MAC endpoint this message belongs to
312 struct MacEndpoint *macendpoint;
315 * Fragmentation context
317 struct GNUNET_FRAGMENT_Context *fragcontext;
320 * Transmission handle to helper (to cancel if the frag context
321 * is destroyed early for some reason).
323 struct GNUNET_HELPER_SendHandle *sh;
326 * Intended recipient.
328 struct GNUNET_PeerIdentity target;
331 * Timeout value for the message.
333 struct GNUNET_TIME_Absolute timeout;
338 struct GNUNET_SCHEDULER_Task * timeout_task;
341 * Continuation to call when we're done with this message.
343 GNUNET_TRANSPORT_TransmitContinuation cont;
346 * Message we need to fragment and transmit, NULL after the
347 * @e fragmentcontext has been created.
349 struct GNUNET_MessageHeader *msg;
352 * Closure for @e cont
357 * Size of original message
362 * Number of bytes used to transmit message
370 * Struct to represent one network card connection
376 * We keep all MACs in a DLL in the plugin.
378 struct MacEndpoint *next;
381 * We keep all MACs in a DLL in the plugin.
383 struct MacEndpoint *prev;
386 * Pointer to the global plugin struct.
388 struct Plugin *plugin;
391 * Head of sessions that use this MAC.
393 struct GNUNET_ATS_Session *sessions_head;
396 * Tail of sessions that use this MAC.
398 struct GNUNET_ATS_Session *sessions_tail;
401 * Head of messages we are currently sending to this MAC.
403 struct FragmentMessage *sending_messages_head;
406 * Tail of messages we are currently sending to this MAC.
408 struct FragmentMessage *sending_messages_tail;
411 * Defrag context for this MAC
413 struct GNUNET_DEFRAGMENT_Context *defrag;
416 * When should this endpoint time out?
418 struct GNUNET_TIME_Absolute timeout;
423 struct GNUNET_SCHEDULER_Task * timeout_task;
426 * count of messages in the fragment out queue for this mac endpoint
428 unsigned int fragment_messages_out_count;
433 struct WlanAddress wlan_addr;
436 * Message delay for fragmentation context
438 struct GNUNET_TIME_Relative msg_delay;
441 * ACK delay for fragmentation context
443 struct GNUNET_TIME_Relative ack_delay;
446 * Desired transmission power for this MAC
451 * Desired transmission rate for this MAC
456 * Antenna we should use for this MAC
464 * Encapsulation of all of the state of the plugin.
471 struct GNUNET_TRANSPORT_PluginEnvironment *env;
474 * Handle to helper process for priviledged operations.
476 struct GNUNET_HELPER_Handle *suid_helper;
479 * Function to call about session status changes.
481 GNUNET_TRANSPORT_SessionInfoCallback sic;
484 * Closure for @e sic.
489 * ARGV-vector for the helper (all helpers take only the binary
490 * name, one actual argument, plus the NULL terminator for 'argv').
492 char *helper_argv[3];
495 * The interface of the wlan card given to us by the user.
497 char *wlan_interface;
500 * Tokenizer for demultiplexing of data packets resulting from
503 struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer;
506 * Tokenizer for demultiplexing of data packets received from the suid helper
508 struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer;
511 * Tokenizer for demultiplexing of data packets that follow the WLAN Header
513 struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer;
516 * Head of list of open connections.
518 struct MacEndpoint *mac_head;
521 * Tail of list of open connections.
523 struct MacEndpoint *mac_tail;
526 * Task that periodically sends a HELLO beacon via the helper.
528 struct GNUNET_SCHEDULER_Task *beacon_task;
531 * Tracker for bandwidth limit
533 struct GNUNET_BANDWIDTH_Tracker tracker;
536 * The mac_address of the wlan card given to us by the helper.
538 struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
541 * Have we received a control message with our MAC address yet?
546 * Number of connections
548 unsigned int mac_count;
551 * Options for addresses
559 * Information associated with a message. Can contain
560 * the session or the MAC endpoint associated with the
566 * NULL if the identity of the other peer is not known.
568 struct GNUNET_ATS_Session *session;
571 * MAC address of the other peer, NULL if not known.
573 struct MacEndpoint *endpoint;
578 * Print MAC addresses nicely.
580 * @param mac the mac address
581 * @return string to a static buffer with
582 * the human-readable mac, will be overwritten during the next call to
586 mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
588 static char macstr[20];
590 GNUNET_snprintf (macstr,
592 "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
593 mac->mac[0], mac->mac[1],
594 mac->mac[2], mac->mac[3],
595 mac->mac[4], mac->mac[5]);
601 * Function called for a quick conversion of the binary address to
602 * a numeric address. Note that the caller must not free the
603 * address and that the next call to this function is allowed
604 * to override the address again.
607 * @param addr binary address
608 * @param addrlen length of the address
609 * @return string representing the same address
612 wlan_plugin_address_to_string (void *cls,
616 const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
617 static char macstr[36];
619 if (sizeof (struct WlanAddress) != addrlen)
624 mac = &((struct WlanAddress *) addr)->mac;
625 GNUNET_snprintf (macstr,
629 ntohl (((struct WlanAddress *) addr)->options),
630 mac_to_string (mac));
636 * If a session monitor is attached, notify it about the new
639 * @param plugin our plugin
640 * @param session session that changed state
641 * @param state new state of the session
644 notify_session_monitor (struct Plugin *plugin,
645 struct GNUNET_ATS_Session *session,
646 enum GNUNET_TRANSPORT_SessionState state)
648 struct GNUNET_TRANSPORT_SessionInfo info;
650 if (NULL == plugin->sic)
652 memset (&info, 0, sizeof (info));
654 info.is_inbound = GNUNET_SYSERR; /* hard to say */
655 info.num_msg_pending = 0; /* we queue per MAC, not per peer */
656 info.num_bytes_pending = 0; /* we queue per MAC, not per peer */
657 info.receive_delay = GNUNET_TIME_UNIT_ZERO_ABS; /* not supported by WLAN */
658 info.session_timeout = session->timeout;
659 info.address = session->address;
660 plugin->sic (plugin->sic_cls,
667 * Fill the radiotap header
669 * @param endpoint pointer to the endpoint, can be NULL
670 * @param header pointer to the radiotap header
671 * @param size total message size
674 get_radiotap_header (struct MacEndpoint *endpoint,
675 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
678 header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
679 header->header.size = ntohs (size);
680 if (NULL != endpoint)
682 header->rate = endpoint->rate;
683 header->tx_power = endpoint->tx_power;
684 header->antenna = endpoint->antenna;
689 header->tx_power = 0;
696 * Generate the WLAN hardware header for one packet
698 * @param plugin the plugin handle
699 * @param header address to write the header to
700 * @param to_mac_addr address of the recipient
701 * @param size size of the whole packet, needed to calculate the time to send the packet
704 get_wlan_header (struct Plugin *plugin,
705 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header,
706 const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
709 const int rate = 11000000;
711 header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
712 header->addr1 = *to_mac_addr;
713 header->addr2 = plugin->mac_address;
714 header->addr3 = mac_bssid_gnunet;
715 header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
716 header->sequence_control = 0; // FIXME?
717 header->llc[0] = WLAN_LLC_DSAP_FIELD;
718 header->llc[1] = WLAN_LLC_SSAP_FIELD;
719 header->llc[2] = 0; // FIXME?
720 header->llc[3] = 0; // FIXME?
725 * Send an ACK for a fragment we received.
727 * @param cls the `struct MacEndpoint *` the ACK must be sent to
728 * @param msg_id id of the message
729 * @param hdr pointer to the hdr where the ack is stored
734 const struct GNUNET_MessageHeader *hdr)
736 struct MacEndpoint *endpoint = cls;
737 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header;
738 uint16_t msize = ntohs (hdr->size);
739 size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
742 if (NULL == endpoint)
747 if (size >= GNUNET_MAX_MESSAGE_SIZE)
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Sending ACK to %s\n",
754 mac_to_string (&endpoint->wlan_addr.mac));
755 radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
756 get_radiotap_header (endpoint, radio_header, size);
757 get_wlan_header (endpoint->plugin,
758 &radio_header->frame,
759 &endpoint->wlan_addr.mac,
760 sizeof (endpoint->wlan_addr.mac));
761 GNUNET_memcpy (&radio_header[1], hdr, msize);
763 GNUNET_HELPER_send (endpoint->plugin->suid_helper,
764 &radio_header->header,
765 GNUNET_NO /* dropping ACKs is bad */,
767 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
774 * Handles the data after all fragments are put together
776 * @param cls macendpoint this messages belongs to
777 * @param hdr pointer to the data
780 wlan_data_message_handler (void *cls,
781 const struct GNUNET_MessageHeader *hdr)
783 struct MacEndpoint *endpoint = cls;
784 struct Plugin *plugin = endpoint->plugin;
785 struct MacAndSession mas;
787 GNUNET_STATISTICS_update (plugin->env->stats,
788 _("# Messages defragmented"),
792 mas.endpoint = endpoint;
793 (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer,
797 GNUNET_YES, GNUNET_NO);
804 * @param cls our `struct Plugin`.
805 * @param session the session free
808 wlan_plugin_disconnect_session (void *cls,
809 struct GNUNET_ATS_Session *session)
811 struct MacEndpoint *endpoint = session->mac;
812 struct Plugin *plugin = endpoint->plugin;
814 plugin->env->session_end (plugin->env->cls,
817 notify_session_monitor (plugin,
819 GNUNET_TRANSPORT_SS_DONE);
820 GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head,
821 endpoint->sessions_tail,
823 if (session->timeout_task != NULL)
825 GNUNET_SCHEDULER_cancel (session->timeout_task);
826 session->timeout_task = NULL;
828 GNUNET_STATISTICS_update (plugin->env->stats,
829 _("# Sessions allocated"),
832 GNUNET_HELLO_address_free (session->address);
833 GNUNET_free (session);
839 * Function that is called to get the keepalive factor.
840 * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
841 * calculate the interval between keepalive packets.
843 * @param cls closure with the `struct Plugin`
844 * @return keepalive factor
847 wlan_plugin_query_keepalive_factor (void *cls)
854 * A session is timing out. Clean up.
856 * @param cls pointer to the Session
859 session_timeout (void *cls)
861 struct GNUNET_ATS_Session *session = cls;
862 struct GNUNET_TIME_Relative left;
864 session->timeout_task = NULL;
865 left = GNUNET_TIME_absolute_get_remaining (session->timeout);
866 if (0 != left.rel_value_us)
868 session->timeout_task =
869 GNUNET_SCHEDULER_add_delayed (left,
874 wlan_plugin_disconnect_session (session->mac->plugin,
881 * Lookup a new session
883 * @param endpoint pointer to the mac endpoint of the peer
884 * @param peer peer identity to use for this session
885 * @return returns the session or NULL
887 static struct GNUNET_ATS_Session *
888 lookup_session (struct MacEndpoint *endpoint,
889 const struct GNUNET_PeerIdentity *peer)
891 struct GNUNET_ATS_Session *session;
893 for (session = endpoint->sessions_head; NULL != session; session = session->next)
894 if (0 == memcmp (peer, &session->target, sizeof (struct GNUNET_PeerIdentity)))
901 * Create a new session
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
907 static struct GNUNET_ATS_Session *
908 create_session (struct MacEndpoint *endpoint,
909 const struct GNUNET_PeerIdentity *peer)
911 struct GNUNET_ATS_Session *session;
913 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
914 _("# Sessions allocated"),
917 session = GNUNET_new (struct GNUNET_ATS_Session);
918 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
919 endpoint->sessions_tail,
921 session->address = GNUNET_HELLO_address_allocate (peer,
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 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
929 session->timeout_task =
930 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout,
932 notify_session_monitor (endpoint->plugin,
934 GNUNET_TRANSPORT_SS_INIT);
935 notify_session_monitor (endpoint->plugin,
937 GNUNET_TRANSPORT_SS_UP);
938 LOG (GNUNET_ERROR_TYPE_DEBUG,
939 "Created new session %p for peer `%s' with endpoint %s\n",
942 mac_to_string (&endpoint->wlan_addr.mac));
949 * Look up a session for a peer and create a new session if none is found
951 * @param endpoint pointer to the mac endpoint of the peer
952 * @param peer peer identity to use for this session
953 * @return returns the session
955 static struct GNUNET_ATS_Session *
956 get_session (struct MacEndpoint *endpoint,
957 const struct GNUNET_PeerIdentity *peer)
959 struct GNUNET_ATS_Session *session;
961 if (NULL != (session = lookup_session (endpoint, peer)))
963 return create_session (endpoint, peer);
968 * Function called once we have successfully given the fragment
969 * message to the SUID helper process and we are thus ready for
972 * @param cls the `struct FragmentMessage *`
973 * @param result result of the operation (#GNUNET_OK on success,
974 * #GNUNET_NO if the helper died, #GNUNET_SYSERR
975 * if the helper was stopped)
978 fragment_transmission_done (void *cls,
981 struct FragmentMessage *fm = cls;
984 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
989 * Transmit a fragment of a message.
991 * @param cls `struct FragmentMessage *` this fragment message belongs to
992 * @param hdr pointer to the start of the fragment message
995 transmit_fragment (void *cls,
996 const struct GNUNET_MessageHeader *hdr)
998 struct FragmentMessage *fm = cls;
999 struct MacEndpoint *endpoint = fm->macendpoint;
1003 if (NULL == endpoint)
1008 msize = ntohs (hdr->size);
1009 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
1012 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header;
1014 radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
1015 get_radiotap_header (endpoint, radio_header, size);
1016 LOG (GNUNET_ERROR_TYPE_DEBUG,
1017 "Sending %u bytes of data to MAC `%s'\n",
1018 (unsigned int) msize,
1019 mac_to_string (&endpoint->wlan_addr.mac));
1021 get_wlan_header (endpoint->plugin,
1022 &radio_header->frame,
1023 &endpoint->wlan_addr.mac,
1024 sizeof (endpoint->wlan_addr.mac));
1025 GNUNET_memcpy (&radio_header[1], hdr, msize);
1026 GNUNET_assert (NULL == fm->sh);
1027 fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper,
1028 &radio_header->header,
1030 &fragment_transmission_done, fm);
1031 fm->size_on_wire += size;
1034 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
1035 _("# message fragments sent"),
1041 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
1043 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
1044 "# bytes currently in buffers",
1046 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
1047 "# bytes transmitted",
1054 * Frees the space of a message in the fragment queue (send queue)
1056 * @param fm message to free
1059 free_fragment_message (struct FragmentMessage *fm)
1061 struct MacEndpoint *endpoint = fm->macendpoint;
1063 GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
1064 _("# messages pending (with fragmentation)"),
1066 GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
1067 endpoint->sending_messages_tail,
1071 GNUNET_HELPER_send_cancel (fm->sh);
1074 if (NULL != fm->msg)
1076 GNUNET_free (fm->msg);
1079 if (NULL != fm->fragcontext)
1081 GNUNET_FRAGMENT_context_destroy (fm->fragcontext,
1082 &endpoint->msg_delay,
1083 &endpoint->ack_delay);
1084 fm->fragcontext = NULL;
1086 if (NULL != fm->timeout_task)
1088 GNUNET_SCHEDULER_cancel (fm->timeout_task);
1089 fm->timeout_task = NULL;
1096 * A FragmentMessage has timed out. Remove it.
1098 * @param cls pointer to the 'struct FragmentMessage'
1101 fragmentmessage_timeout (void *cls)
1103 struct FragmentMessage *fm = cls;
1105 fm->timeout_task = NULL;
1106 if (NULL != fm->cont)
1108 fm->cont (fm->cont_cls,
1115 free_fragment_message (fm);
1120 * Transmit a message to the given destination with fragmentation.
1122 * @param endpoint desired destination
1123 * @param timeout how long can the message wait?
1124 * @param target peer that should receive the message
1125 * @param msg message to transmit
1126 * @param payload_size bytes of payload
1127 * @param cont continuation to call once the message has
1128 * been transmitted (or if the transport is ready
1129 * for the next transmission call; or if the
1130 * peer disconnected...); can be NULL
1131 * @param cont_cls closure for @a cont
1134 send_with_fragmentation (struct MacEndpoint *endpoint,
1135 struct GNUNET_TIME_Relative timeout,
1136 const struct GNUNET_PeerIdentity *target,
1137 const struct GNUNET_MessageHeader *msg,
1138 size_t payload_size,
1139 GNUNET_TRANSPORT_TransmitContinuation cont,
1143 struct FragmentMessage *fm;
1144 struct Plugin *plugin;
1146 plugin = endpoint->plugin;
1147 fm = GNUNET_new (struct FragmentMessage);
1148 fm->macendpoint = endpoint;
1149 fm->target = *target;
1150 fm->size_payload = payload_size;
1151 fm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1153 fm->cont_cls = cont_cls;
1154 /* 1 MBit/s typical data rate, 1430 byte fragments => ~100 ms per message */
1156 GNUNET_SCHEDULER_add_delayed (timeout,
1157 &fragmentmessage_timeout,
1159 if (GNUNET_YES == plugin->have_mac)
1162 GNUNET_FRAGMENT_context_create (plugin->env->stats,
1165 fm->macendpoint->msg_delay,
1166 fm->macendpoint->ack_delay,
1168 &transmit_fragment, fm);
1172 fm->msg = GNUNET_copy_message (msg);
1174 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head,
1175 endpoint->sending_messages_tail,
1181 * Free a MAC endpoint.
1183 * @param endpoint pointer to the MacEndpoint to free
1186 free_macendpoint (struct MacEndpoint *endpoint)
1188 struct Plugin *plugin = endpoint->plugin;
1189 struct FragmentMessage *fm;
1190 struct GNUNET_ATS_Session *session;
1192 GNUNET_STATISTICS_update (plugin->env->stats,
1193 _("# MAC endpoints allocated"),
1196 while (NULL != (session = endpoint->sessions_head))
1197 wlan_plugin_disconnect_session (plugin,
1199 while (NULL != (fm = endpoint->sending_messages_head))
1200 free_fragment_message (fm);
1201 GNUNET_CONTAINER_DLL_remove (plugin->mac_head,
1205 if (NULL != endpoint->defrag)
1207 GNUNET_DEFRAGMENT_context_destroy(endpoint->defrag);
1208 endpoint->defrag = NULL;
1211 plugin->mac_count--;
1212 if (NULL != endpoint->timeout_task)
1214 GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
1215 endpoint->timeout_task = NULL;
1217 GNUNET_free (endpoint);
1222 * A MAC endpoint is timing out. Clean up.
1224 * @param cls pointer to the `struct MacEndpoint *`
1227 macendpoint_timeout (void *cls)
1229 struct MacEndpoint *endpoint = cls;
1230 struct GNUNET_TIME_Relative timeout;
1232 endpoint->timeout_task = NULL;
1233 timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout);
1234 if (0 == timeout.rel_value_us)
1236 free_macendpoint (endpoint);
1239 endpoint->timeout_task =
1240 GNUNET_SCHEDULER_add_delayed (timeout,
1241 &macendpoint_timeout,
1247 * Find (or create) a MacEndpoint with a specific MAC address
1249 * @param plugin pointer to the plugin struct
1250 * @param mac the MAC address of the endpoint
1251 * @return handle to our data structure for this MAC
1253 static struct MacEndpoint *
1254 create_macendpoint (struct Plugin *plugin,
1255 struct WlanAddress *mac)
1257 struct MacEndpoint *pos;
1259 for (pos = plugin->mac_head; NULL != pos; pos = pos->next)
1260 if (0 == memcmp (mac, &pos->wlan_addr, sizeof (pos->wlan_addr)))
1262 pos = GNUNET_new (struct MacEndpoint);
1263 pos->wlan_addr = (*mac);
1264 pos->plugin = plugin;
1266 GNUNET_DEFRAGMENT_context_create (plugin->env->stats,
1268 MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
1270 &wlan_data_message_handler,
1273 pos->msg_delay = GNUNET_TIME_UNIT_MILLISECONDS;
1274 pos->ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
1275 pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
1277 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
1279 GNUNET_CONTAINER_DLL_insert (plugin->mac_head,
1282 plugin->mac_count++;
1283 GNUNET_STATISTICS_update (plugin->env->stats,
1284 _("# MAC endpoints allocated"),
1286 LOG (GNUNET_ERROR_TYPE_DEBUG,
1287 "New MAC endpoint `%s'\n",
1288 wlan_plugin_address_to_string (NULL,
1290 sizeof (struct WlanAddress)));
1296 * Function obtain the network type for a session
1298 * @param cls closure (`struct Plugin*`)
1299 * @param session the session
1300 * @return the network type in HBO or #GNUNET_SYSERR
1302 static enum GNUNET_ATS_Network_Type
1303 wlan_plugin_get_network (void *cls,
1304 struct GNUNET_ATS_Session *session)
1307 return GNUNET_ATS_NET_WLAN;
1309 return GNUNET_ATS_NET_BT;
1315 * Function obtain the network type for an address.
1317 * @param cls closure (`struct Plugin *`)
1318 * @param address the address
1319 * @return the network type
1321 static enum GNUNET_ATS_Network_Type
1322 wlan_plugin_get_network_for_address (void *cls,
1323 const struct GNUNET_HELLO_Address *address)
1326 return GNUNET_ATS_NET_WLAN;
1328 return GNUNET_ATS_NET_BT;
1334 * Creates a new outbound session the transport service will use to
1335 * send data to the peer
1337 * @param cls the `struct Plugin *`
1338 * @param address the address
1339 * @return the session or NULL of max connections exceeded
1341 static struct GNUNET_ATS_Session *
1342 wlan_plugin_get_session (void *cls,
1343 const struct GNUNET_HELLO_Address *address)
1345 struct Plugin *plugin = cls;
1346 struct MacEndpoint *endpoint;
1348 if (NULL == address)
1350 if (sizeof (struct WlanAddress) != address->address_length)
1355 LOG (GNUNET_ERROR_TYPE_DEBUG,
1356 "Service asked to create session for peer `%s' with MAC `%s'\n",
1357 GNUNET_i2s (&address->peer),
1358 wlan_plugin_address_to_string (NULL,
1360 address->address_length));
1361 endpoint = create_macendpoint (plugin,
1362 (struct WlanAddress *) address->address);
1363 return get_session (endpoint, &address->peer);
1368 * Function that can be used to force the plugin to disconnect
1369 * from the given peer and cancel all previous transmissions
1370 * (and their continuation).
1372 * @param cls closure
1373 * @param target peer from which to disconnect
1376 wlan_plugin_disconnect_peer (void *cls,
1377 const struct GNUNET_PeerIdentity *target)
1379 struct Plugin *plugin = cls;
1380 struct GNUNET_ATS_Session *session;
1381 struct MacEndpoint *endpoint;
1383 for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next)
1384 for (session = endpoint->sessions_head; NULL != session; session = session->next)
1385 if (0 == memcmp (target, &session->target,
1386 sizeof (struct GNUNET_PeerIdentity)))
1388 wlan_plugin_disconnect_session (plugin, session);
1389 break; /* inner-loop only (in case peer has another MAC as well!) */
1395 * Function that can be used by the transport service to transmit
1396 * a message using the plugin. Note that in the case of a
1397 * peer disconnecting, the continuation MUST be called
1398 * prior to the disconnect notification itself. This function
1399 * will be called with this peer's HELLO message to initiate
1400 * a fresh connection to another peer.
1402 * @param cls closure
1403 * @param session which session must be used
1404 * @param msgbuf the message to transmit
1405 * @param msgbuf_size number of bytes in @a msgbuf
1406 * @param priority how important is the message (most plugins will
1407 * ignore message priority and just FIFO)
1408 * @param to how long to wait at most for the transmission (does not
1409 * require plugins to discard the message after the timeout,
1410 * just advisory for the desired delay; most plugins will ignore
1412 * @param cont continuation to call once the message has
1413 * been transmitted (or if the transport is ready
1414 * for the next transmission call; or if the
1415 * peer disconnected...); can be NULL
1416 * @param cont_cls closure for @a cont
1417 * @return number of bytes used (on the physical network, with overheads);
1418 * -1 on hard errors (i.e. address invalid); 0 is a legal value
1419 * and does NOT mean that the message was not transmitted (DV)
1422 wlan_plugin_send (void *cls,
1423 struct GNUNET_ATS_Session *session,
1424 const char *msgbuf, size_t msgbuf_size,
1425 unsigned int priority,
1426 struct GNUNET_TIME_Relative to,
1427 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1429 struct Plugin *plugin = cls;
1430 struct WlanHeader *wlanheader;
1431 size_t size = msgbuf_size + sizeof (struct WlanHeader);
1432 char buf[size] GNUNET_ALIGN;
1434 LOG (GNUNET_ERROR_TYPE_DEBUG,
1435 "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n",
1437 GNUNET_i2s (&session->target),
1438 (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size),
1439 (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type));
1440 wlanheader = (struct WlanHeader *) buf;
1441 wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
1442 wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
1443 wlanheader->sender = *plugin->env->my_identity;
1444 wlanheader->target = session->target;
1445 wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size));
1446 GNUNET_memcpy (&wlanheader[1],
1449 GNUNET_STATISTICS_update (plugin->env->stats,
1450 "# bytes currently in buffers",
1453 send_with_fragmentation (session->mac,
1456 &wlanheader->header,
1464 * We have received data from the WLAN via some session. Process depending
1465 * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK).
1467 * @param cls pointer to the plugin
1468 * @param client pointer to the session this message belongs to
1469 * @param hdr start of the message
1472 process_data (void *cls,
1474 const struct GNUNET_MessageHeader *hdr)
1476 struct Plugin *plugin = cls;
1477 struct GNUNET_HELLO_Address *address;
1478 struct MacAndSession *mas = client;
1479 struct FragmentMessage *fm;
1480 struct GNUNET_PeerIdentity tmpsource;
1481 const struct WlanHeader *wlanheader;
1485 msize = ntohs (hdr->size);
1487 GNUNET_STATISTICS_update (plugin->env->stats,
1491 switch (ntohs (hdr->type))
1493 case GNUNET_MESSAGE_TYPE_HELLO:
1496 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr,
1499 GNUNET_break_op (0);
1502 if (NULL == mas->endpoint)
1508 LOG (GNUNET_ERROR_TYPE_DEBUG,
1509 "Processing %u bytes of HELLO from peer `%s' at MAC %s\n",
1510 (unsigned int) msize,
1511 GNUNET_i2s (&tmpsource),
1512 wlan_plugin_address_to_string (NULL,
1513 &mas->endpoint->wlan_addr,
1514 sizeof (mas->endpoint->wlan_addr)));
1516 GNUNET_STATISTICS_update (plugin->env->stats,
1517 _("# HELLO messages received"), 1,
1519 address = GNUNET_HELLO_address_allocate (&tmpsource,
1521 &mas->endpoint->wlan_addr,
1522 sizeof (mas->endpoint->wlan_addr),
1523 GNUNET_HELLO_ADDRESS_INFO_NONE);
1524 mas->session = lookup_session (mas->endpoint,
1526 if (NULL == mas->session)
1528 mas->session = create_session (mas->endpoint,
1530 plugin->env->session_start (plugin->env->cls,
1535 plugin->env->receive (plugin->env->cls,
1539 GNUNET_HELLO_address_free (address);
1541 case GNUNET_MESSAGE_TYPE_FRAGMENT:
1542 if (NULL == mas->endpoint)
1547 LOG (GNUNET_ERROR_TYPE_DEBUG,
1548 "Processing %u bytes of FRAGMENT from MAC %s\n",
1549 (unsigned int) msize,
1550 wlan_plugin_address_to_string (NULL,
1551 &mas->endpoint->wlan_addr,
1552 sizeof (mas->endpoint->wlan_addr)));
1553 GNUNET_STATISTICS_update (plugin->env->stats,
1554 _("# fragments received"),
1557 (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag,
1560 case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
1561 if (NULL == mas->endpoint)
1566 GNUNET_STATISTICS_update (plugin->env->stats,
1567 _("# ACKs received"),
1569 for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next)
1571 ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
1572 if (GNUNET_OK == ret)
1574 LOG (GNUNET_ERROR_TYPE_DEBUG,
1575 "Got last ACK, finished message transmission to `%s' (%p)\n",
1576 wlan_plugin_address_to_string (NULL,
1577 &mas->endpoint->wlan_addr,
1578 sizeof (mas->endpoint->wlan_addr)),
1580 mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
1581 if (NULL != fm->cont)
1583 fm->cont (fm->cont_cls,
1590 free_fragment_message (fm);
1593 if (GNUNET_NO == ret)
1595 LOG (GNUNET_ERROR_TYPE_DEBUG,
1596 "Got an ACK, message transmission to `%s' not yet finished\n",
1597 wlan_plugin_address_to_string (NULL,
1598 &mas->endpoint->wlan_addr,
1599 sizeof (mas->endpoint->wlan_addr)));
1604 LOG (GNUNET_ERROR_TYPE_DEBUG,
1605 "ACK not matched against any active fragmentation with MAC `%s'\n",
1606 wlan_plugin_address_to_string (NULL,
1607 &mas->endpoint->wlan_addr,
1608 sizeof (mas->endpoint->wlan_addr)));
1610 case GNUNET_MESSAGE_TYPE_WLAN_DATA:
1611 if (NULL == mas->endpoint)
1616 if (msize < sizeof (struct WlanHeader))
1621 wlanheader = (const struct WlanHeader *) hdr;
1622 if (0 != memcmp (&wlanheader->target,
1623 plugin->env->my_identity,
1624 sizeof (struct GNUNET_PeerIdentity)))
1626 LOG (GNUNET_ERROR_TYPE_DEBUG,
1627 "Data for `%s', not for me, ignoring\n",
1628 GNUNET_i2s (&wlanheader->target));
1631 if (ntohl (wlanheader->crc) !=
1632 GNUNET_CRYPTO_crc32_n (&wlanheader[1],
1633 msize - sizeof (struct WlanHeader)))
1635 GNUNET_STATISTICS_update (plugin->env->stats,
1636 _("# DATA messages discarded due to CRC32 error"),
1641 mas->session = lookup_session (mas->endpoint,
1642 &wlanheader->sender);
1643 if (NULL == mas->session)
1645 mas->session = create_session (mas->endpoint,
1646 &wlanheader->sender);
1647 address = GNUNET_HELLO_address_allocate (&wlanheader->sender,
1649 &mas->endpoint->wlan_addr,
1650 sizeof (struct WlanAddress),
1651 GNUNET_HELLO_ADDRESS_INFO_NONE);
1652 plugin->env->session_start (plugin->env->cls,
1656 LOG (GNUNET_ERROR_TYPE_DEBUG,
1657 "Notifying transport about peer `%s''s new session %p \n",
1658 GNUNET_i2s (&wlanheader->sender),
1660 GNUNET_HELLO_address_free (address);
1662 LOG (GNUNET_ERROR_TYPE_DEBUG,
1663 "Processing %u bytes of DATA from peer `%s'\n",
1664 (unsigned int) msize,
1665 GNUNET_i2s (&wlanheader->sender));
1666 mas->session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1667 (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer,
1669 (const char *) &wlanheader[1],
1670 msize - sizeof (struct WlanHeader),
1675 if (NULL == mas->endpoint)
1680 if (NULL == mas->session)
1685 LOG (GNUNET_ERROR_TYPE_DEBUG,
1686 "Received packet with %u bytes of type %u from peer %s\n",
1687 (unsigned int) msize,
1688 (unsigned int) ntohs (hdr->type),
1689 GNUNET_i2s (&mas->session->target));
1690 plugin->env->receive (plugin->env->cls,
1691 mas->session->address,
1701 * Task to (periodically) send a HELLO beacon
1703 * @param cls pointer to the plugin struct
1706 send_hello_beacon (void *cls)
1708 struct Plugin *plugin = cls;
1710 uint16_t hello_size;
1711 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
1712 const struct GNUNET_MessageHeader *hello;
1714 hello = plugin->env->get_our_hello ();
1717 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1718 GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1719 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size;
1721 char buf[size] GNUNET_ALIGN;
1723 LOG (GNUNET_ERROR_TYPE_DEBUG,
1724 "Sending %u byte HELLO beacon\n",
1725 (unsigned int) size);
1726 radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf;
1727 get_radiotap_header (NULL, radioHeader, size);
1728 LOG (GNUNET_ERROR_TYPE_DEBUG,
1729 "Broadcasting %u bytes of data to MAC `%s'\n",
1730 (unsigned int) size,
1731 mac_to_string (&bc_all_mac));
1732 get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size);
1733 GNUNET_memcpy (&radioHeader[1], hello, hello_size);
1735 GNUNET_HELPER_send (plugin->suid_helper,
1736 &radioHeader->header,
1737 GNUNET_YES /* can drop */,
1739 GNUNET_STATISTICS_update (plugin->env->stats,
1740 _("# HELLO beacons sent"),
1743 plugin->beacon_task =
1744 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1745 (HELLO_BEACON_SCALING_FACTOR,
1746 plugin->mac_count + 1),
1754 * Function used for to process the data from the suid process
1756 * @param cls the plugin handle
1757 * @param hdr header of the GNUNET_MessageHeader
1760 handle_helper_message (void *cls,
1761 const struct GNUNET_MessageHeader *hdr)
1763 struct Plugin *plugin = cls;
1764 struct GNUNET_HELLO_Address *my_address;
1765 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo;
1766 const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
1767 struct WlanAddress wa;
1768 struct MacAndSession mas;
1770 struct FragmentMessage *fm;
1771 struct MacEndpoint *endpoint;
1773 msize = ntohs (hdr->size);
1774 switch (ntohs (hdr->type))
1776 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
1777 if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
1782 cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
1783 if (GNUNET_YES == plugin->have_mac)
1785 if (0 == memcmp (&plugin->mac_address,
1787 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1788 break; /* no change */
1789 /* remove old address */
1790 memset (&wa, 0, sizeof (struct WlanAddress));
1791 wa.mac = plugin->mac_address;
1792 wa.options = htonl(plugin->options);
1793 my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1796 GNUNET_HELLO_ADDRESS_INFO_NONE);
1797 plugin->env->notify_address (plugin->env->cls,
1800 GNUNET_HELLO_address_free (my_address);
1801 plugin->mac_address = cm->mac;
1805 plugin->mac_address = cm->mac;
1806 plugin->have_mac = GNUNET_YES;
1807 for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next)
1809 for (fm = endpoint->sending_messages_head; NULL != fm; fm = fm->next)
1811 if (NULL != fm->fragcontext)
1813 GNUNET_break (0); /* should not happen */
1817 GNUNET_FRAGMENT_context_create (plugin->env->stats,
1820 fm->macendpoint->msg_delay,
1821 fm->macendpoint->ack_delay,
1823 &transmit_fragment, fm);
1824 GNUNET_free (fm->msg);
1828 GNUNET_break (NULL == plugin->beacon_task);
1829 plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon,
1834 memset (&wa, 0, sizeof (struct WlanAddress));
1835 wa.mac = plugin->mac_address;
1836 wa.options = htonl(plugin->options);
1837 my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1840 GNUNET_HELLO_ADDRESS_INFO_NONE);
1842 LOG (GNUNET_ERROR_TYPE_DEBUG,
1843 "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n",
1844 mac_to_string (&cm->mac),
1845 GNUNET_i2s (plugin->env->my_identity));
1846 plugin->env->notify_address (plugin->env->cls,
1849 GNUNET_HELLO_address_free (my_address);
1851 case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER:
1852 LOG (GNUNET_ERROR_TYPE_DEBUG,
1853 "Got data message from helper with %u bytes\n",
1855 GNUNET_STATISTICS_update (plugin->env->stats,
1856 _("# DATA messages received"), 1,
1858 if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
1860 LOG (GNUNET_ERROR_TYPE_DEBUG,
1861 "Size of packet is too small (%u bytes < %u)\n",
1862 msize, sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage));
1865 rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
1867 /* check if message is actually for us */
1868 if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet,
1869 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1871 /* Not the GNUnet BSSID */
1874 if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac,
1875 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) &&
1876 (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address,
1877 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) )
1879 /* Neither broadcast nor specifically for us */
1882 if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address,
1883 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1885 /* packet is FROM us, thus not FOR us */
1889 GNUNET_STATISTICS_update (plugin->env->stats,
1890 _("# DATA messages processed"),
1892 LOG (GNUNET_ERROR_TYPE_DEBUG,
1893 "Receiving %u bytes of data from MAC `%s'\n",
1894 (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
1895 mac_to_string (&rxinfo->frame.addr2));
1896 LOG (GNUNET_ERROR_TYPE_DEBUG,
1897 "Receiving %u bytes of data to MAC `%s'\n",
1898 (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
1899 mac_to_string (&rxinfo->frame.addr1));
1900 LOG (GNUNET_ERROR_TYPE_DEBUG,
1901 "Receiving %u bytes of data with BSSID MAC `%s'\n",
1902 (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
1903 mac_to_string (&rxinfo->frame.addr3));
1904 wa.mac = rxinfo->frame.addr2;
1905 wa.options = htonl (0);
1906 mas.endpoint = create_macendpoint (plugin, &wa);
1908 (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer,
1910 (const char*) &rxinfo[1],
1911 msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage),
1912 GNUNET_YES, GNUNET_NO);
1916 LOG (GNUNET_ERROR_TYPE_ERROR,
1917 "Unexpected message of type %u (%u bytes)",
1927 * Another peer has suggested an address for this
1928 * peer and transport plugin. Check that this could be a valid
1929 * address. If so, consider adding it to the list
1932 * @param cls closure
1933 * @param addr pointer to the address
1934 * @param addrlen length of @a addr
1935 * @return #GNUNET_OK if this is a plausible address for this peer
1939 wlan_plugin_address_suggested (void *cls,
1943 struct Plugin *plugin = cls;
1944 struct WlanAddress *wa = (struct WlanAddress *) addr;
1946 if (addrlen != sizeof (struct WlanAddress))
1948 GNUNET_break_op (0);
1949 return GNUNET_SYSERR;
1951 if (GNUNET_YES != plugin->have_mac)
1953 LOG (GNUNET_ERROR_TYPE_DEBUG,
1954 "Rejecting MAC `%s': I don't know my MAC!\n",
1955 mac_to_string (addr));
1956 return GNUNET_NO; /* don't know my MAC */
1958 if (0 != memcmp (&wa->mac,
1959 &plugin->mac_address,
1962 LOG (GNUNET_ERROR_TYPE_DEBUG,
1963 "Rejecting MAC `%s': not my MAC!\n",
1964 mac_to_string (addr));
1965 return GNUNET_NO; /* not my MAC */
1972 * Convert the transports address to a nice, human-readable format.
1974 * @param cls closure
1975 * @param type name of the transport that generated the address
1976 * @param addr one of the addresses of the host, NULL for the last address
1977 * the specific address format depends on the transport
1978 * @param addrlen length of the address
1979 * @param numeric should (IP) addresses be displayed in numeric form?
1980 * @param timeout after how long should we give up?
1981 * @param asc function to call on each string
1982 * @param asc_cls closure for @a asc
1985 wlan_plugin_address_pretty_printer (void *cls,
1990 struct GNUNET_TIME_Relative timeout,
1991 GNUNET_TRANSPORT_AddressStringCallback asc,
1996 if (sizeof (struct WlanAddress) == addrlen)
1997 ret = wlan_plugin_address_to_string (NULL,
2004 (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
2005 asc (asc_cls, NULL, GNUNET_OK);
2010 * Exit point from the plugin.
2012 * @param cls pointer to the api struct
2015 LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
2017 struct WlanAddress wa;
2018 struct GNUNET_HELLO_Address *address;
2019 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2020 struct Plugin *plugin = api->cls;
2021 struct MacEndpoint *endpoint;
2022 struct MacEndpoint *endpoint_next;
2029 if (GNUNET_YES == plugin->have_mac)
2031 memset (&wa, 0, sizeof(wa));
2032 wa.options = htonl (plugin->options);
2033 wa.mac = plugin->mac_address;
2034 address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
2036 &wa, sizeof (struct WlanAddress),
2037 GNUNET_HELLO_ADDRESS_INFO_NONE);
2039 plugin->env->notify_address (plugin->env->cls,
2042 plugin->have_mac = GNUNET_NO;
2043 GNUNET_HELLO_address_free (address);
2046 if (NULL != plugin->beacon_task)
2048 GNUNET_SCHEDULER_cancel (plugin->beacon_task);
2049 plugin->beacon_task = NULL;
2051 if (NULL != plugin->suid_helper)
2053 GNUNET_HELPER_stop (plugin->suid_helper,
2055 plugin->suid_helper = NULL;
2057 endpoint_next = plugin->mac_head;
2058 while (NULL != (endpoint = endpoint_next))
2060 endpoint_next = endpoint->next;
2061 free_macendpoint (endpoint);
2063 if (NULL != plugin->fragment_data_tokenizer)
2065 GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer);
2066 plugin->fragment_data_tokenizer = NULL;
2068 if (NULL != plugin->wlan_header_payload_tokenizer)
2070 GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer);
2071 plugin->wlan_header_payload_tokenizer = NULL;
2073 if (NULL != plugin->helper_payload_tokenizer)
2075 GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer);
2076 plugin->helper_payload_tokenizer = NULL;
2078 GNUNET_free_non_null (plugin->wlan_interface);
2079 GNUNET_free (plugin);
2086 * Function called to convert a string address to
2089 * @param cls closure (`struct Plugin *`)
2090 * @param addr string address
2091 * @param addrlen length of the address
2092 * @param buf location to store the buffer
2093 * @param added location to store the number of bytes in the buffer.
2094 * If the function returns #GNUNET_SYSERR, its contents are undefined.
2095 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
2098 wlan_plugin_string_to_address (void *cls,
2104 struct WlanAddress *wa;
2110 if ((NULL == addr) || (0 == addrlen))
2113 return GNUNET_SYSERR;
2115 if ('\0' != addr[addrlen - 1])
2118 return GNUNET_SYSERR;
2120 if (strlen (addr) != addrlen - 1)
2123 return GNUNET_SYSERR;
2126 if (8 != SSCANF (addr,
2127 "%4s.%u.%X:%X:%X:%X:%X:%X",
2129 &a[0], &a[1], &a[2],
2130 &a[3], &a[4], &a[5]))
2133 return GNUNET_SYSERR;
2135 wa = GNUNET_new (struct WlanAddress);
2137 wa->mac.mac[i] = a[i];
2138 wa->options = htonl (0);
2140 *added = sizeof (struct WlanAddress);
2146 * Begin monitoring sessions of a plugin. There can only
2147 * be one active monitor per plugin (i.e. if there are
2148 * multiple monitors, the transport service needs to
2149 * multiplex the generated events over all of them).
2151 * @param cls closure of the plugin
2152 * @param sic callback to invoke, NULL to disable monitor;
2153 * plugin will being by iterating over all active
2154 * sessions immediately and then enter monitor mode
2155 * @param sic_cls closure for @a sic
2158 wlan_plugin_setup_monitor (void *cls,
2159 GNUNET_TRANSPORT_SessionInfoCallback sic,
2162 struct Plugin *plugin = cls;
2163 struct MacEndpoint *mac;
2164 struct GNUNET_ATS_Session *session;
2167 plugin->sic_cls = sic_cls;
2170 for (mac = plugin->mac_head; NULL != mac; mac = mac->next)
2171 for (session = mac->sessions_head; NULL != session; session = session->next)
2173 notify_session_monitor (plugin,
2175 GNUNET_TRANSPORT_SS_INIT);
2176 notify_session_monitor (plugin,
2178 GNUNET_TRANSPORT_SS_UP);
2180 sic (sic_cls, NULL, NULL);
2187 * Function that will be called whenever the transport service wants to
2188 * notify the plugin that a session is still active and in use and
2189 * therefore the session timeout for this session has to be updated
2191 * @param cls closure
2192 * @param peer which peer was the session for
2193 * @param session which session is being updated
2196 wlan_plugin_update_session_timeout (void *cls,
2197 const struct GNUNET_PeerIdentity *peer,
2198 struct GNUNET_ATS_Session *session)
2200 GNUNET_assert (NULL != session->timeout_task);
2201 session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2206 * Function that will be called whenever the transport service wants to
2207 * notify the plugin that the inbound quota changed and that the plugin
2208 * should update it's delay for the next receive value
2210 * @param cls closure
2211 * @param peer which peer was the session for
2212 * @param session which session is being updated
2213 * @param delay new delay to use for receiving
2216 wlan_plugin_update_inbound_delay (void *cls,
2217 const struct GNUNET_PeerIdentity *peer,
2218 struct GNUNET_ATS_Session *session,
2219 struct GNUNET_TIME_Relative delay)
2221 /* does nothing, as inbound delay is not supported by WLAN */
2226 * Entry point for the plugin.
2228 * @param cls closure, the `struct GNUNET_TRANSPORT_PluginEnvironment *`
2229 * @return the `struct GNUNET_TRANSPORT_PluginFunctions *` or NULL on error
2232 LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
2234 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2235 struct GNUNET_TRANSPORT_PluginFunctions *api;
2236 struct Plugin *plugin;
2237 char *wlan_interface;
2238 unsigned long long testmode;
2241 /* check for 'special' mode */
2242 if (NULL == env->receive)
2244 /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
2245 initialze the plugin or the API */
2246 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
2248 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2249 api->address_to_string = &wlan_plugin_address_to_string;
2250 api->string_to_address = &wlan_plugin_string_to_address;
2255 /* check configuration */
2257 GNUNET_CONFIGURATION_have_value (env->cfg,
2261 GNUNET_CONFIGURATION_get_value_number (env->cfg,
2267 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2272 binary = GNUNET_OS_get_libexec_binary_path (HELPER_NAME);
2273 if ( (0 == testmode) &&
2275 GNUNET_OS_check_helper_binary (binary,
2279 LOG (GNUNET_ERROR_TYPE_ERROR,
2280 _("Helper binary `%s' not SUID, cannot run WLAN transport\n"),
2282 GNUNET_free (binary);
2285 GNUNET_free (binary);
2287 GNUNET_CONFIGURATION_get_value_string (env->cfg,
2292 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2298 plugin = GNUNET_new (struct Plugin);
2299 plugin->wlan_interface = wlan_interface;
2301 GNUNET_STATISTICS_set (plugin->env->stats,
2302 _("# sessions allocated"),
2304 GNUNET_STATISTICS_set (plugin->env->stats,
2305 _("# MAC endpoints allocated"),
2307 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, NULL, NULL,
2308 GNUNET_BANDWIDTH_value_init (100 * 1024 *
2311 plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data,
2313 plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data,
2315 plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data,
2318 plugin->options = 0;
2320 /* some compilers do not like switch on 'long long'... */
2321 switch ((unsigned int) testmode)
2323 case 0: /* normal */
2324 plugin->helper_argv[0] = (char *) HELPER_NAME;
2325 plugin->helper_argv[1] = wlan_interface;
2326 plugin->helper_argv[2] = NULL;
2327 plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
2329 plugin->helper_argv,
2330 &handle_helper_message,
2334 case 1: /* testmode, peer 1 */
2335 plugin->helper_argv[0] = (char *) DUMMY_HELPER_NAME;
2336 plugin->helper_argv[1] = (char *) "1";
2337 plugin->helper_argv[2] = NULL;
2338 plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
2340 plugin->helper_argv,
2341 &handle_helper_message,
2345 case 2: /* testmode, peer 2 */
2346 plugin->helper_argv[0] = (char *) DUMMY_HELPER_NAME;
2347 plugin->helper_argv[1] = (char *) "2";
2348 plugin->helper_argv[2] = NULL;
2349 plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
2351 plugin->helper_argv,
2352 &handle_helper_message,
2360 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
2362 api->send = &wlan_plugin_send;
2363 api->get_session = &wlan_plugin_get_session;
2364 api->disconnect_peer = &wlan_plugin_disconnect_peer;
2365 api->disconnect_session = &wlan_plugin_disconnect_session;
2366 api->query_keepalive_factor = &wlan_plugin_query_keepalive_factor;
2367 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2368 api->check_address = &wlan_plugin_address_suggested;
2369 api->address_to_string = &wlan_plugin_address_to_string;
2370 api->string_to_address = &wlan_plugin_string_to_address;
2371 api->get_network = &wlan_plugin_get_network;
2372 api->get_network_for_address = &wlan_plugin_get_network_for_address;
2373 api->update_session_timeout = &wlan_plugin_update_session_timeout;
2374 api->update_inbound_delay = &wlan_plugin_update_inbound_delay;
2375 api->setup_monitor = &wlan_plugin_setup_monitor;
2380 /* end of plugin_transport_wlan.c */