aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_wlan.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-05-08 19:55:05 +0000
committerChristian Grothoff <christian@grothoff.org>2012-05-08 19:55:05 +0000
commit535c983e0dcf6dba67e69e15f2f8c882bf305796 (patch)
tree2d07e6de940f26e25d3d67e84233f0af9ae2e072 /src/transport/plugin_transport_wlan.c
parentb437294d389fcde182fb4e11a6782e228271606b (diff)
downloadgnunet-535c983e0dcf6dba67e69e15f2f8c882bf305796.tar.gz
gnunet-535c983e0dcf6dba67e69e15f2f8c882bf305796.zip
-clean up WLAN plugin
Diffstat (limited to 'src/transport/plugin_transport_wlan.c')
-rw-r--r--src/transport/plugin_transport_wlan.c3318
1 files changed, 1035 insertions, 2283 deletions
diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c
index 7711dec06..142095035 100644
--- a/src/transport/plugin_transport_wlan.c
+++ b/src/transport/plugin_transport_wlan.c
@@ -23,10 +23,10 @@
23 * @brief transport plugin for wlan 23 * @brief transport plugin for wlan
24 * @author David Brodski 24 * @author David Brodski
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - HELPER-continuation may be called after fragment times out (-> use after free, see FIXME)
26 */ 29 */
27
28//TODO split rx and tx structures for better handling
29
30#include "platform.h" 30#include "platform.h"
31#include "gnunet_hello_lib.h" 31#include "gnunet_hello_lib.h"
32#include "gnunet_protocols.h" 32#include "gnunet_protocols.h"
@@ -40,59 +40,31 @@
40#include "gnunet_fragmentation_lib.h" 40#include "gnunet_fragmentation_lib.h"
41#include "gnunet_constants.h" 41#include "gnunet_constants.h"
42 42
43
44#define PROTOCOL_PREFIX "wlan" 43#define PROTOCOL_PREFIX "wlan"
45 44
46#define PLUGIN_LOG_NAME "wlan-plugin" 45#define LOG(kind,...) GNUNET_log_from (kind, "transport-wlan",__VA_ARGS__)
47 46
48/** 47/**
49 * Max size of packet 48 * Max size of packet (that we give to the WLAN driver for transmission)
50 */ 49 */
51#define WLAN_MTU 1430 50#define WLAN_MTU 1430
52 51
53/** 52/**
54 * time out of a session
55 */
56#define SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
57
58/**
59 * time out of a mac endpoint 53 * time out of a mac endpoint
60 */ 54 */
61#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2) 55#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
62 56
63/** 57/**
64 * scaling factor for hello beacon 58 * We reduce the frequence of HELLO beacons in relation to
65 */ 59 * the number of MAC addresses currently visible to us.
66#define HELLO_BEACON_SCALING_FACTOR 30 60 * This is the multiplication factor.
67
68/**
69 * scaling factor for restarting the helper
70 */
71#define HELPER_RESTART_SCALING_FACTOR 2
72
73/**
74 * max size of fragment queue
75 */
76#define FRAGMENT_QUEUE_SIZE 10
77/**
78 * max messages in fragment queue per session/client
79 */
80#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
81
82/**
83 * max messages in fragment queue per MAC
84 */
85#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT 1
86
87/**
88 * max messages in in queue
89 */ 61 */
90#define MESSAGES_IN_QUEUE_SIZE 10 62#define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
91 63
92/** 64/**
93 * max messages in in queue per session/client 65 * Maximum number of messages in defragmentation queue per MAC
94 */ 66 */
95#define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 1 67#define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2
96 68
97/** 69/**
98 * Link layer control fields for better compatibility 70 * Link layer control fields for better compatibility
@@ -102,1068 +74,416 @@
102#define WLAN_LLC_SSAP_FIELD 0x1f 74#define WLAN_LLC_SSAP_FIELD 0x1f
103 75
104 76
105 77GNUNET_NETWORK_STRUCT_BEGIN
106/** 78/**
107 * Encapsulation of all of the state of the plugin. 79 * Header for messages which need fragmentation. This is the format of
80 * a message we obtain AFTER defragmentation. We then need to check
81 * the CRC and then tokenize the payload and pass it to the
82 * 'receive' callback.
108 */ 83 */
109struct Plugin 84struct WlanHeader
110{ 85{
111 /**
112 * Our environment.
113 */
114 struct GNUNET_TRANSPORT_PluginEnvironment *env;
115 86
116 /** 87 /**
117 * List of open connections. head 88 * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA.
118 */
119 struct MacEndpoint *mac_head;
120
121 /**
122 * List of open connections. tail
123 */
124 struct MacEndpoint *mac_tail;
125
126 /**
127 * Number of connections
128 */
129 unsigned int mac_count;
130
131 /**
132 * encapsulation of data from the local wlan helper program
133 */
134 struct GNUNET_SERVER_MessageStreamTokenizer *suid_tokenizer;
135
136 /**
137 * encapsulation of packets received from the wlan helper
138 */
139 struct GNUNET_SERVER_MessageStreamTokenizer *data_tokenizer;
140
141 /**
142 * stdout pipe handle for the gnunet-helper-transport-wlan process
143 */
144 struct GNUNET_DISK_PipeHandle *server_stdout;
145
146 /**
147 * stdout file handle for the gnunet-helper-transport-wlan process
148 */ 89 */
149 const struct GNUNET_DISK_FileHandle *server_stdout_handle; 90 struct GNUNET_MessageHeader header;
150 91
151 /** 92 /**
152 * stdin pipe handle for the gnunet-helper-transport-wlan process 93 * CRC32 checksum (only over the payload), in NBO.
153 */ 94 */
154 struct GNUNET_DISK_PipeHandle *server_stdin; 95 uint32_t crc GNUNET_PACKED;
155 96
156 /** 97 /**
157 * stdin file handle for the gnunet-helper-transport-wlan process 98 * Sender of the message.
158 */ 99 */
159 const struct GNUNET_DISK_FileHandle *server_stdin_handle; 100 struct GNUNET_PeerIdentity sender;
160 101
161 /** 102 /**
162 * ID of the gnunet-wlan-server std read task 103 * Target of the message.
163 */ 104 */
164 GNUNET_SCHEDULER_TaskIdentifier server_read_task; 105 struct GNUNET_PeerIdentity target;
165 106
166 /** 107 /* followed by payload, possibly including
167 * ID of the gnunet-wlan-server std read task 108 multiple messages! */
168 */
169 GNUNET_SCHEDULER_TaskIdentifier server_write_task;
170 109
171 /** 110};
172 * ID of the delay task for writing 111GNUNET_NETWORK_STRUCT_END
173 */
174 GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
175 112
176 /**
177 * The process id of the wlan process
178 */
179 struct GNUNET_OS_Process *server_proc;
180 113
114/**
115 * Information kept for each message that is yet to be fragmented and
116 * transmitted.
117 */
118struct PendingMessage
119{
181 /** 120 /**
182 * The interface of the wlan card given to us by the user. 121 * next entry in the DLL
183 */ 122 */
184 char *interface; 123 struct PendingMessage *next;
185 124
186 /** 125 /**
187 * Mode of operation for the helper, 0 = normal, 1 = first loopback, 2 = second loopback 126 * previous entry in the DLL
188 */ 127 */
189 long long unsigned int testmode; 128 struct PendingMessage *prev;
190 129
191 /** 130 /**
192 * The mac_address of the wlan card given to us by the helper. 131 * The pending message
193 */ 132 */
194 struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address; 133 struct WlanHeader *msg;
195 134
196 /** 135 /**
197 * Sessions currently pending for transmission 136 * Continuation function to call once the message
198 * to a peer, if any. 137 * has been sent. Can be NULL if there is no
138 * continuation to call.
199 */ 139 */
200 struct Sessionqueue *pending_Sessions_head; 140 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
201 141
202 /** 142 /**
203 * Sessions currently pending for transmission 143 * Cls for transmit_cont
204 * to a peer (tail), if any.
205 */ 144 */
206 struct Sessionqueue *pending_Sessions_tail; 145 void *transmit_cont_cls;
207 146
208 /** 147 /**
209 * number of pending sessions 148 * Timeout task (for this message).
210 */ 149 */
211 unsigned int pendingsessions; 150 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
212 151
213 /** 152};
214 * Messages in the sending queues
215 */
216 int pending_Fragment_Messages;
217 153
218 /**
219 * messages ready for send, head
220 */
221 struct FragmentMessage_queue *sending_messages_head;
222 154
223 /** 155/**
224 * messages ready for send, tail 156 * Session handle for connections with other peers.
225 */ 157 */
226 struct FragmentMessage_queue *sending_messages_tail; 158struct Session
159{
227 160
228 /** 161 /**
229 * time of the next "hello-beacon" 162 * API requirement (must be first).
230 */ 163 */
231 struct GNUNET_TIME_Absolute beacon_time; 164 struct SessionHeader header;
232 165
233 /** 166 /**
234 * queue to send acks for received fragments (head) 167 * We keep all sessions in a DLL at their respective
168 * 'struct MACEndpoint'.
235 */ 169 */
236 struct AckSendQueue *ack_send_queue_head; 170 struct Session *next;
237 171
238 /** 172 /**
239 * queue to send acks for received fragments (tail) 173 * We keep all sessions in a DLL at their respective
174 * 'struct MACEndpoint'.
240 */ 175 */
241 struct AckSendQueue *ack_send_queue_tail; 176 struct Session *prev;
242 177
243 /** 178 /**
244 * Tracker for bandwidth limit 179 * MAC endpoint with the address of this peer.
245 */ 180 */
246 struct GNUNET_BANDWIDTH_Tracker tracker; 181 struct MacEndpoint *mac;
247 182
248 /** 183 /**
249 * saves the current state of the helper process 184 * Head of messages currently pending for transmission to this peer.
250 */ 185 */
251 int helper_is_running; 186 struct PendingMessage *pending_message_head;
252};
253 187
254/**
255 * Struct to store data if file write did not accept the whole packet
256 */
257struct Finish_send
258{
259 /** 188 /**
260 * pointer to the global plugin struct 189 * Tail of messages currently pending for transmission to this peer.
261 */ 190 */
262 struct Plugin *plugin; 191 struct PendingMessage *pending_message_tail;
263 192
264 /** 193 /**
265 * head of the next part to send to the helper 194 * To whom are we talking to (set to our identity
195 * if we are still waiting for the welcome message)
266 */ 196 */
267 const char *head_of_next_write; 197 struct GNUNET_PeerIdentity target;
268 198
269 /** 199 /**
270 * Start of the message to send, needed for free 200 * When should this session time out?
271 */ 201 */
272 struct GNUNET_MessageHeader *msgstart; 202 struct GNUNET_TIME_Absolute timeout;
273 203
274 /** 204 /**
275 * rest size to send 205 * Timeout task (for the session).
276 */ 206 */
277 ssize_t size; 207 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
278};
279
280/**
281 * Queue of sessions, for the general session queue and the pending session queue
282 */
283//TODO DOXYGEN
284struct Sessionqueue
285{
286 struct Sessionqueue *next;
287 struct Sessionqueue *prev;
288 struct Session *content;
289#if !HAVE_UNALIGNED_64_ACCESS
290 void *dummy; /* for alignment, see #1909 */
291#endif
292};
293
294
295/**
296 * Queue of fragmented messages, for the sending queue of the plugin
297 */
298//TODO DOXYGEN
299struct FragmentMessage_queue
300{
301 struct FragmentMessage_queue *next;
302 struct FragmentMessage_queue *prev;
303 struct FragmentMessage *content;
304};
305
306
307/**
308 * Queue for the fragments received
309 */
310//TODO DOXYGEN
311struct Receive_Fragment_Queue
312{
313 struct Receive_Fragment_Queue *next;
314 struct Receive_Fragment_Queue *prev;
315
316 uint16_t num;
317 // const char *msg;
318 // uint16_t size;
319 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rx_msg;
320};
321
322
323//TODO DOXYGEN
324struct MacEndpoint_id_fragment_triple
325{
326 struct MacEndpoint *endpoint;
327 uint32_t message_id;
328 struct FragmentMessage *fm;
329};
330 208
331//TODO DOXYGEN
332struct Plugin_Session_pair
333{
334 struct Plugin *plugin;
335 struct Session *session;
336}; 209};
337 210
338 211
339GNUNET_NETWORK_STRUCT_BEGIN
340
341/** 212/**
342 * Header for messages which need fragmentation 213 * Struct for messages that are being fragmented in a MAC's transmission queue.
343 */ 214 */
344struct WlanHeader 215struct FragmentMessage
345{ 216{
346 217
347 /** 218 /**
348 * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA. 219 * This is a doubly-linked list.
349 */
350 struct GNUNET_MessageHeader header;
351
352 /**
353 * checksum/error correction
354 */ 220 */
355 uint32_t crc GNUNET_PACKED; 221 struct FragmentMessage *next;
356 222
357 /** 223 /**
358 * To whom are we talking to (set to our identity 224 * This is a doubly-linked list.
359 * if we are still waiting for the welcome message)
360 */ 225 */
361 struct GNUNET_PeerIdentity target; 226 struct FragmentMessage *prev;
362 227
363 /** 228 /**
364 * Where the packet came from 229 * MAC endpoint this message belongs to
365 */ 230 */
366 struct GNUNET_PeerIdentity source; 231 struct MacEndpoint *macendpoint;
367
368// followed by payload
369
370};
371GNUNET_NETWORK_STRUCT_END
372 232
373/**
374 * Information kept for each message that is yet to
375 * be transmitted.
376 */
377struct PendingMessage
378{
379 /** 233 /**
380 * dll next 234 * Fragmentation context
381 */ 235 */
382 struct PendingMessage *next; 236 struct GNUNET_FRAGMENT_Context *fragcontext;
383 237
384 /** 238 /**
385 * dll prev 239 * Transmission handle to helper (to cancel if the frag context
240 * is destroyed early for some reason).
386 */ 241 */
387 struct PendingMessage *prev; 242 struct GNUNET_HELPER_SendHandle *sh;
388 243
389 /** 244 /**
390 * The pending message 245 * Intended recipient.
391 */ 246 */
392 struct WlanHeader *msg; 247 struct GNUNET_PeerIdentity target;
393 248
394 /** 249 /**
395 * Size of the message 250 * Timeout value for the message.
396 */ 251 */
397 size_t message_size; 252 struct GNUNET_TIME_Absolute timeout;
398 253
399 /** 254 /**
400 * Continuation function to call once the message 255 * Timeout task.
401 * has been sent. Can be NULL if there is no
402 * continuation to call.
403 */ 256 */
404 GNUNET_TRANSPORT_TransmitContinuation transmit_cont; 257 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
405 258
406 /** 259 /**
407 * Cls for transmit_cont 260 * Continuation to call when we're done with this message.
408 */ 261 */
409 void *transmit_cont_cls; 262 GNUNET_TRANSPORT_TransmitContinuation cont;
410 263
411 /** 264 /**
412 * Timeout value for the pending message. 265 * Closure for 'cont'
413 */ 266 */
414 struct GNUNET_TIME_Absolute timeout; 267 void *cont_cls;
415 268
416}; 269};
417 270
418 271
419/** 272/**
420 * Queue for acks to send for fragments recived 273 * Struct to represent one network card connection
421 */ 274 */
422struct AckSendQueue 275struct MacEndpoint
423{ 276{
424 277
425 /** 278 /**
426 * next ack in the ack send queue 279 * We keep all MACs in a DLL in the plugin.
427 */ 280 */
428 struct AckSendQueue *next; 281 struct MacEndpoint *next;
429 282
430 /** 283 /**
431 * previous ack in the ack send queue 284 * We keep all MACs in a DLL in the plugin.
432 */ 285 */
433 struct AckSendQueue *prev; 286 struct MacEndpoint *prev;
434 287
435 /** 288 /**
436 * pointer to the session this ack belongs to 289 * Pointer to the global plugin struct.
437 */ 290 */
438 struct MacEndpoint *endpoint; 291 struct Plugin *plugin;
439 292
440 /** 293 /**
441 * ID of message, to distinguish between the messages, picked randomly. 294 * Head of sessions that use this MAC.
442 */ 295 */
443 uint32_t message_id; 296 struct Session *sessions_head;
444 297
445 /** 298 /**
446 * pointer to the radiotap header with the ACK Message. 299 * Tail of sessions that use this MAC.
447 */ 300 */
448 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader; 301 struct Session *sessions_tail;
449};
450
451
452/**
453 * Session handle for connections.
454 */
455struct Session
456{
457 302
458 /** 303 /**
459 * API requirement. 304 * Head of messages we are currently sending to this MAC.
460 */ 305 */
461 struct SessionHeader header; 306 struct FragmentMessage *sending_messages_head;
462 307
463 /** 308 /**
464 * Message currently pending for transmission 309 * Tail of messages we are currently sending to this MAC.
465 * to this peer, if any. head
466 */ 310 */
467 struct PendingMessage *pending_message_head; 311 struct FragmentMessage *sending_messages_tail;
468 312
469 /** 313 /**
470 * Message currently pending for transmission 314 * Defrag context for this MAC
471 * to this peer, if any. tail
472 */ 315 */
473 struct PendingMessage *pending_message_tail; 316 struct GNUNET_DEFRAGMENT_Context *defrag;
474 317
475 /** 318 /**
476 * To whom are we talking to (set to our identity 319 * When should this endpoint time out?
477 * if we are still waiting for the welcome message)
478 */ 320 */
479 struct GNUNET_PeerIdentity target; 321 struct GNUNET_TIME_Absolute timeout;
480 322
481 /** 323 /**
482 * Address of the other peer (either based on our 'connect' 324 * Timeout task.
483 * call or on our 'accept' call).
484 */ 325 */
485 void *connect_addr; 326 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
486 327
487 /** 328 /**
488 * Last activity on this connection. Used to select preferred 329 * count of messages in the fragment out queue for this mac endpoint
489 * connection and timeout
490 */ 330 */
491 struct GNUNET_TIME_Absolute last_activity; 331 unsigned int fragment_messages_out_count;
492 332
493 /** 333 /**
494 * Timeout task. 334 * peer mac address
495 */ 335 */
496 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 336 struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
497 337
498 /** 338 /**
499 * peer connection 339 * Desired transmission power for this MAC
500 */ 340 */
501 struct MacEndpoint *mac; 341 uint16_t tx_power;
502 342
503 /** 343 /**
504 * count of messages in the fragment out queue for this session 344 * Desired transmission rate for this MAC
505 */ 345 */
346 uint8_t rate;
506 347
507 int fragment_messages_out_count; 348 /**
349 * Antenna we should use for this MAC
350 */
351 uint8_t antenna;
508 352
509}; 353};
510 354
355
511/** 356/**
512 * Struct to represent one network card connection 357 * Encapsulation of all of the state of the plugin.
513 */ 358 */
514struct MacEndpoint 359struct Plugin
515{ 360{
516
517 /** 361 /**
518 * dll next 362 * Our environment.
519 */ 363 */
520 struct MacEndpoint *next; 364 struct GNUNET_TRANSPORT_PluginEnvironment *env;
521 365
522 /** 366 /**
523 * dll prev 367 * Handle to helper process for priviledged operations.
524 */ 368 */
525 struct MacEndpoint *prev; 369 struct GNUNET_HELPER_Handle *suid_helper;
526 370
527 /** 371 /**
528 * Pointer to the global plugin struct. 372 * ARGV-vector for the helper (all helpers take only the binary
373 * name, one actual argument, plus the NULL terminator for 'argv').
529 */ 374 */
530 struct Plugin *plugin; 375 char * helper_argv[3];
531 376
532 /** 377 /**
533 * Struct to hold the session reachable over this mac; head 378 * The interface of the wlan card given to us by the user.
534 */ 379 */
535 struct Sessionqueue *sessions_head; 380 char *interface;
536 381
537 /** 382 /**
538 * Struct to hold the session reachable over this mac; tail 383 * Tokenizer for demultiplexing of data packets resulting from defragmentation.
539 */ 384 */
540 struct Sessionqueue *sessions_tail; 385 struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer;
541 386
542 /** 387 /**
543 * Messages currently sending 388 * Tokenizer for demultiplexing of data packets received from the suid helper
544 * to a peer, if any.
545 */ 389 */
546 struct FragmentMessage *sending_messages_head; 390 struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer;
547 391
548 /** 392 /**
549 * Messages currently sending 393 * Tokenizer for demultiplexing of data packets that follow the WLAN Header
550 * to a peer (tail), if any.
551 */ 394 */
552 struct FragmentMessage *sending_messages_tail; 395 struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer;
553 396
554 /** 397 /**
555 * peer mac address 398 * Head of list of open connections.
556 */ 399 */
557 struct GNUNET_TRANSPORT_WLAN_MacAddress addr; 400 struct MacEndpoint *mac_head;
558 401
559 /** 402 /**
560 * Defrag context for this mac endpoint 403 * Tail of list of open connections.
561 */ 404 */
562 struct GNUNET_DEFRAGMENT_Context *defrag; 405 struct MacEndpoint *mac_tail;
563 406
564 /** 407 /**
565 * count of messages in the fragment out queue for this mac endpoint 408 * Number of connections
566 */ 409 */
567 int fragment_messages_out_count; 410 unsigned int mac_count;
568
569 //TODO DOXYGEN
570 uint8_t rate;
571 uint16_t tx_power;
572 uint8_t antenna;
573 411
574 /** 412 /**
575 * Duplicates received 413 * Task that periodically sends a HELLO beacon via the helper.
576 */ 414 */
577 int dups; 415 GNUNET_SCHEDULER_TaskIdentifier beacon_task;
578 416
579 /** 417 /**
580 * Fragments received 418 * Tracker for bandwidth limit
581 */ 419 */
582 int fragc; 420 struct GNUNET_BANDWIDTH_Tracker tracker;
583 421
584 /** 422 /**
585 * Acks received 423 * The mac_address of the wlan card given to us by the helper.
586 */ 424 */
587 int acks; 425 struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
588 426
589 /** 427 /**
590 * Last activity on this endpoint. Used to select preferred 428 * Have we received a control message with our MAC address yet?
591 * connection.
592 */ 429 */
593 struct GNUNET_TIME_Absolute last_activity; 430 int have_mac;
431
594 432
595 /**
596 * Timeout task.
597 */
598 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
599}; 433};
600 434
435
601/** 436/**
602 * Struct for Messages in the fragment queue 437 * Information associated with a message. Can contain
438 * the session or the MAC endpoint associated with the
439 * message (or both).
603 */ 440 */
604struct FragmentMessage 441struct MacAndSession
605{ 442{
606
607 /** 443 /**
608 * Session this message belongs to 444 * NULL if the identity of the other peer is not known.
609 */ 445 */
610 struct Session *session; 446 struct Session *session;
611 447
612 /** 448 /**
613 * This is a doubly-linked list. 449 * MAC address of the other peer, NULL if not known.
614 */
615 struct FragmentMessage *next;
616
617 /**
618 * This is a doubly-linked list.
619 */
620 struct FragmentMessage *prev;
621
622 /**
623 * Fragmentation context
624 */
625 struct GNUNET_FRAGMENT_Context *fragcontext;
626
627 /**
628 * Timeout value for the message.
629 */
630 struct GNUNET_TIME_Absolute timeout;
631
632 /**
633 * Timeout task.
634 */
635 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
636
637 /**
638 * pointer to the radiotap header
639 */ 450 */
640 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader; 451 struct MacEndpoint *endpoint;
641}; 452};
642 453
643 454
644static void
645do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
646
647
648static void
649free_session (struct Plugin *plugin, struct Sessionqueue *queue,
650 int do_free_macendpoint);
651
652
653static struct MacEndpoint *
654create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr);
655
656
657static void
658finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
659
660
661
662/**
663 * Function to find a MacEndpoint with a specific mac addr
664 * @param plugin pointer to the plugin struct
665 * @param addr pointer to the mac address
666 * @param create_new GNUNET_YES if a new end point should be created
667 * @return
668 */
669static struct MacEndpoint *
670get_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
671 int create_new)
672{
673 struct MacEndpoint *queue = plugin->mac_head;
674
675 while (queue != NULL)
676 {
677 //GNUNET_assert (queue->sessions_head != NULL);
678 if (memcmp (addr, &queue->addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
679 return queue; /* session found */
680 queue = queue->next;
681 }
682
683 if (create_new == GNUNET_YES)
684 {
685 return create_macendpoint (plugin, addr);
686 }
687 else
688 {
689 return NULL;
690 }
691}
692
693
694/**
695 * search for a session with the macendpoint and peer id
696 *
697 * @param plugin pointer to the plugin struct
698 * @param endpoint pointer to the mac endpoint of the peer
699 * @param peer pointer to the peerid
700 * @return returns the session
701 */
702static struct Session *
703search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
704 const struct GNUNET_PeerIdentity *peer)
705{
706 GNUNET_assert (endpoint != NULL);
707 struct Sessionqueue *queue = endpoint->sessions_head;
708
709 while (queue != NULL)
710 {
711 GNUNET_assert (queue->content != NULL);
712 if (memcmp
713 (peer, &queue->content->target,
714 sizeof (struct GNUNET_PeerIdentity)) == 0)
715 return queue->content; /* session found */
716 queue = queue->next;
717 }
718 return NULL;
719}
720
721/** 455/**
722 * Function called for a quick conversion of the binary address to 456 * Print MAC addresses nicely.
723 * a numeric address. Note that the caller must not free the
724 * address and that the next call to this function is allowed
725 * to override the address again.
726 * 457 *
727 * @param cls closure 458 * @param mac the mac address
728 * @param addr binary address 459 * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function
729 * @param addrlen length of the address
730 * @return string representing the same address
731 */ 460 */
732static const char * 461static const char *
733wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) 462mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
734{
735 static char ret[40];
736 const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
737
738 if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
739 {
740 GNUNET_break (0);
741 return NULL;
742 }
743 mac = addr;
744 GNUNET_snprintf (ret, sizeof (ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
745 PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2],
746 mac->mac[3], mac->mac[4], mac->mac[5]);
747
748 return ret;
749}
750
751/**
752 * Function for the scheduler if a session times out
753 * @param cls pointer to the Sessionqueue
754 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
755 */
756static void
757session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
758{
759 struct Sessionqueue *queue = cls;
760
761 GNUNET_assert (queue != NULL);
762 GNUNET_assert (queue->content != NULL);
763 queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
764 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
765 {
766 return;
767 }
768 if (GNUNET_TIME_absolute_get_remaining
769 (GNUNET_TIME_absolute_add
770 (queue->content->last_activity, SESSION_TIMEOUT)).rel_value == 0)
771 {
772
773 GNUNET_assert (queue->content->mac != NULL);
774 GNUNET_assert (queue->content->mac->plugin != NULL);
775 GNUNET_STATISTICS_update (queue->content->mac->plugin->env->stats,
776 _("# wlan session timeouts"), 1, GNUNET_NO);
777 free_session (queue->content->mac->plugin, queue, GNUNET_YES);
778 }
779 else
780 {
781 queue->content->timeout_task =
782 GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
783 }
784}
785
786/**
787 * create a new session
788 *
789 * @param plugin pointer to the plugin struct
790 * @param endpoint pointer to the mac endpoint of the peer
791 * @param peer peer identity to use for this session
792 * @return returns the session
793 */
794static struct Session *
795create_session (struct Plugin *plugin, struct MacEndpoint *endpoint,
796 const struct GNUNET_PeerIdentity *peer)
797{
798 GNUNET_assert (endpoint != NULL);
799 GNUNET_assert (plugin != NULL);
800 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan session created"), 1,
801 GNUNET_NO);
802 struct Sessionqueue *queue =
803 GNUNET_malloc (sizeof (struct Sessionqueue) + sizeof (struct Session));
804
805 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
806 endpoint->sessions_tail, queue);
807
808 queue->content = (struct Session *) &queue[1];
809 queue->content->mac = endpoint;
810 queue->content->target = *peer;
811 queue->content->last_activity = GNUNET_TIME_absolute_get ();
812 queue->content->timeout_task =
813 GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
814
815 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
816 "New session %p with endpoint %p: %s\n", queue->content,
817 endpoint, wlan_plugin_address_to_string (NULL,
818 endpoint->addr.mac,
819 6));
820 return queue->content;
821}
822
823/**
824 * Get session from address, create if no session exists
825 *
826 * @param plugin pointer to the plugin struct
827 * @param addr pointer to the mac address of the peer
828 * @param peer pointer to the peerid
829 * @return returns the session
830 */
831static struct Session *
832get_session (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
833 const struct GNUNET_PeerIdentity *peer)
834{
835 struct MacEndpoint *mac;
836
837 mac = get_macendpoint (plugin, addr, GNUNET_YES);
838 struct Session *session = search_session (plugin, mac, peer);
839
840 if (session != NULL)
841 return session;
842 return create_session (plugin, mac, peer);
843}
844
845/**
846 * Queue the session to send data
847 * checks if there is a message pending
848 * checks if this session is not allready in the queue
849 * @param plugin pointer to the plugin
850 * @param session pointer to the session to add
851 */
852static void
853queue_session (struct Plugin *plugin, struct Session *session)
854{
855 struct Sessionqueue *queue = plugin->pending_Sessions_head;
856
857 if (session->pending_message_head != NULL)
858 {
859 while (queue != NULL)
860 {
861 // content is never NULL
862 GNUNET_assert (queue->content != NULL);
863 // is session already in queue?
864 if (session == queue->content)
865 {
866 return;
867 }
868 // try next
869 queue = queue->next;
870 }
871
872 // Session is not in the queue
873
874 queue = GNUNET_malloc (sizeof (struct Sessionqueue));
875 queue->content = session;
876
877 //insert at the tail
878 GNUNET_CONTAINER_DLL_insert_tail (plugin->pending_Sessions_head,
879 plugin->pending_Sessions_tail, queue);
880 plugin->pendingsessions++;
881 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
882 plugin->pendingsessions, GNUNET_NO);
883 }
884
885}
886
887/**
888 * Function to schedule the write task, executed after a delay
889 * @param cls pointer to the plugin struct
890 * @param tc GNUNET_SCHEDULER_TaskContext pointer
891 */
892static void
893delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
894{ 463{
895 struct Plugin *plugin = cls; 464 static char macstr[20];
896
897 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
898
899 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
900 return;
901
902 // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
903 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
904 {
905 plugin->server_write_task =
906 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
907 plugin->server_stdin_handle,
908 &do_transmit, plugin);
909 }
910}
911
912/**
913 * Function to calculate the time of the next periodic "hello-beacon"
914 * @param plugin pointer to the plugin struct
915 */
916static void
917set_next_beacon_time (struct Plugin *const plugin)
918{
919 //under 10 known peers: once a second
920 if (plugin->mac_count < 10)
921 {
922 plugin->beacon_time =
923 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
924 GNUNET_TIME_relative_multiply
925 (GNUNET_TIME_UNIT_SECONDS,
926 HELLO_BEACON_SCALING_FACTOR));
927 }
928 //under 30 known peers: every 10 seconds
929 else if (plugin->mac_count < 30)
930 {
931 plugin->beacon_time =
932 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
933 GNUNET_TIME_relative_multiply
934 (GNUNET_TIME_UNIT_SECONDS,
935 10 * HELLO_BEACON_SCALING_FACTOR));
936 }
937 //over 30 known peers: once a minute
938 else
939 {
940 plugin->beacon_time =
941 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
942 GNUNET_TIME_relative_multiply
943 (GNUNET_TIME_UNIT_MINUTES,
944 HELLO_BEACON_SCALING_FACTOR));
945 }
946}
947
948
949/**
950 * Function to set the timer for the next timeout of the fragment queue
951 * @param plugin the handle to the plugin struct
952 */
953static void
954set_next_send (struct Plugin *plugin)
955{
956 struct GNUNET_TIME_Relative next_send;
957
958 //abort if helper is not running
959 if (plugin->helper_is_running == GNUNET_NO)
960 {
961 return;
962 }
963
964 //cancel old task
965 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
966 {
967 GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
968 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
969 }
970
971 //check if some acks are in the queue
972 if (plugin->ack_send_queue_head != NULL)
973 {
974 next_send = GNUNET_TIME_UNIT_ZERO;
975 }
976
977 //check if there are some fragments in the queue
978 else if (plugin->sending_messages_head != NULL)
979 {
980 next_send = GNUNET_TIME_UNIT_ZERO;
981 }
982 else
983 {
984 next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
985 }
986
987 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
988 "Next packet is send in: %u\n", next_send.rel_value);
989 if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
990 {
991 if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
992 {
993 plugin->server_write_task =
994 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
995 plugin->server_stdin_handle,
996 &do_transmit, plugin);
997 }
998 }
999 else
1000 {
1001 if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
1002 {
1003 plugin->server_write_delay_task =
1004 GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
1005 plugin);
1006 }
1007 }
1008}
1009
1010
1011/**
1012 * Function to get the next queued Session, removes the session from the queue
1013 * @param plugin pointer to the plugin struct
1014 * @return pointer to the session found, returns NULL if there is now session in the queue
1015 */
1016static struct Session *
1017get_next_queue_session (struct Plugin *plugin)
1018{
1019 struct Session *session;
1020 struct Sessionqueue *sessionqueue;
1021 struct Sessionqueue *sessionqueue_old;
1022 struct PendingMessage *pm;
1023
1024 sessionqueue = plugin->pending_Sessions_head;
1025
1026 while (sessionqueue != NULL)
1027 {
1028 session = sessionqueue->content;
1029
1030 GNUNET_assert (session != NULL);
1031 pm = session->pending_message_head;
1032
1033 if (pm == NULL)
1034 {
1035 sessionqueue_old = sessionqueue;
1036 sessionqueue = sessionqueue->next;
1037 plugin->pendingsessions--;
1038 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1039 plugin->pendingsessions, GNUNET_NO);
1040 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1041 plugin->pending_Sessions_tail,
1042 sessionqueue_old);
1043
1044 GNUNET_free (sessionqueue_old);
1045 continue;
1046 }
1047
1048 //check for message timeout
1049 if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
1050 {
1051 //check if session has no message in the fragment queue
1052 if ((session->mac->fragment_messages_out_count <
1053 FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
1054 (session->fragment_messages_out_count <
1055 FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
1056 {
1057 plugin->pendingsessions--;
1058 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1059 plugin->pendingsessions, GNUNET_NO);
1060 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1061 plugin->pending_Sessions_tail,
1062 sessionqueue);
1063 GNUNET_free (sessionqueue);
1064
1065 return session;
1066 }
1067 else
1068 {
1069 sessionqueue = sessionqueue->next;
1070 }
1071 }
1072 else
1073 {
1074 GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1075 session->pending_message_tail, pm);
1076
1077 //call the cont func that it did not work
1078 if (pm->transmit_cont != NULL)
1079 pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
1080 GNUNET_SYSERR);
1081 GNUNET_free (pm->msg);
1082 GNUNET_free (pm);
1083
1084 if (session->pending_message_head == NULL)
1085 {
1086 sessionqueue_old = sessionqueue;
1087 sessionqueue = sessionqueue->next;
1088 plugin->pendingsessions--;
1089 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1090 plugin->pendingsessions, GNUNET_NO);
1091 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1092 plugin->pending_Sessions_tail,
1093 sessionqueue_old);
1094
1095 GNUNET_free (sessionqueue_old);
1096 }
1097 }
1098
1099 }
1100 return NULL;
1101}
1102
1103
1104/**
1105 * frees the space of a message in the fragment queue (send queue)
1106 * @param plugin the plugin struct
1107 * @param fm message to free
1108 */
1109static void
1110free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
1111{
1112 struct Session *session = fm->session;
1113 struct MacEndpoint *endpoint = session->mac;
1114 struct FragmentMessage_queue *fmq;
1115 struct FragmentMessage_queue *fmq_next;
1116 465
1117 fmq = plugin->sending_messages_head; 466 GNUNET_snprintf (macstr, sizeof (macstr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac->mac[0], mac->mac[1],
1118 while (fmq != NULL) 467 mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]);
1119 { 468 return macstr;
1120 fmq_next = fmq->next;
1121 if (fmq->content == fm)
1122 {
1123 GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
1124 plugin->sending_messages_tail, fmq);
1125 GNUNET_free (fmq);
1126 }
1127 fmq = fmq_next;
1128 }
1129 session->mac->fragment_messages_out_count--;
1130 session->fragment_messages_out_count--;
1131 plugin->pending_Fragment_Messages--;
1132 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1133 plugin->pending_Fragment_Messages, GNUNET_NO);
1134 GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
1135 endpoint->sending_messages_tail, fm);
1136 GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
1137 if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1138 {
1139 GNUNET_SCHEDULER_cancel (fm->timeout_task);
1140 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1141 }
1142 GNUNET_free (fm);
1143 queue_session (plugin, session);
1144 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1145 "Free pending fragment messages %p, session %p\n", fm,
1146 session);
1147} 469}
1148 470
1149 471
1150/** 472/**
1151 * function to fill the radiotap header 473 * Fill the radiotap header
1152 * 474 *
1153 * @param plugin pointer to the plugin struct 475 * @param endpoint pointer to the endpoint, can be NULL
1154 * @param endpoint pointer to the endpoint
1155 * @param header pointer to the radiotap header 476 * @param header pointer to the radiotap header
1156 * @param size total message size 477 * @param size total message size
1157 * @return GNUNET_YES at success
1158 */ 478 */
1159static int 479static void
1160getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint, 480get_radiotap_header (struct MacEndpoint *endpoint,
1161 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header, 481 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
1162 uint16_t size) 482 uint16_t size)
1163{ 483{
1164 header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER); 484 header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
1165 header->header.size = ntohs (size); 485 header->header.size = ntohs (size);
1166 if (endpoint != NULL) 486 if (NULL != endpoint)
1167 { 487 {
1168 header->rate = endpoint->rate; 488 header->rate = endpoint->rate;
1169 header->tx_power = endpoint->tx_power; 489 header->tx_power = endpoint->tx_power;
@@ -1175,521 +495,302 @@ getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
1175 header->tx_power = 0; 495 header->tx_power = 0;
1176 header->antenna = 0; 496 header->antenna = 0;
1177 } 497 }
1178
1179 return GNUNET_YES;
1180} 498}
1181 499
1182 500
1183/** 501/**
1184 * function to generate the wlan hardware header for one packet 502 * Generate the WLAN hardware header for one packet
1185 * @param Header address to write the header to 503 *
504 * @param header address to write the header to
1186 * @param to_mac_addr address of the recipient 505 * @param to_mac_addr address of the recipient
1187 * @param plugin pointer to the plugin struct
1188 * @param size size of the whole packet, needed to calculate the time to send the packet 506 * @param size size of the whole packet, needed to calculate the time to send the packet
1189 * FIXME: 'size' is initialized inconsistently throughout the code (sometimes payload, sometimes everything)
1190 * @return GNUNET_YES if there was no error
1191 */ 507 */
1192static int 508static void
1193getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header, 509get_wlan_header (struct Plugin *plugin,
1194 const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, struct Plugin *plugin, 510 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header,
1195 unsigned int size) 511 const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
512 unsigned int size)
1196{ 513{
1197 const int rate = 11000000; 514 const int rate = 11000000;
1198 515
1199 Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); 516 header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
1200 Header->addr1 = *to_mac_addr; 517 header->addr1 = *to_mac_addr;
1201 Header->addr2 = plugin->mac_address; 518 header->addr2 = plugin->mac_address;
1202 Header->addr3 = mac_bssid_gnunet; 519 header->addr3 = mac_bssid_gnunet;
1203 Header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290); 520 header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
1204 Header->sequence_control = 0; // FIXME? 521 header->sequence_control = 0; // FIXME?
1205 Header->llc[0] = WLAN_LLC_DSAP_FIELD; 522 header->llc[0] = WLAN_LLC_DSAP_FIELD;
1206 Header->llc[1] = WLAN_LLC_SSAP_FIELD; 523 header->llc[1] = WLAN_LLC_SSAP_FIELD;
1207 Header->llc[2] = 0; // FIXME? 524 header->llc[2] = 0; // FIXME?
1208 Header->llc[3] = 0; // FIXME? 525 header->llc[3] = 0; // FIXME?
1209 return GNUNET_YES;
1210} 526}
1211 527
1212 528
1213/** 529/**
1214 * function to add a fragment of a message to send 530 * Send an ACK for a fragment we received.
1215 * @param cls FragmentMessage this message belongs to 531 *
1216 * @param hdr pointer to the start of the message 532 * @param cls the 'struct MacEndpoint' the ACK must be sent to
533 * @param msg_id id of the message
534 * @param hdr pointer to the hdr where the ack is stored
1217 */ 535 */
1218static void 536static void
1219add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr) 537send_ack (void *cls, uint32_t msg_id,
538 const struct GNUNET_MessageHeader *hdr)
1220{ 539{
1221 struct FragmentMessage *fm = cls; 540 struct MacEndpoint *endpoint = cls;
1222 struct FragmentMessage_queue *fmqueue; 541 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header;
1223 struct MacEndpoint *endpoint; 542 uint16_t msize = ntohs (hdr->size);
1224 struct Plugin *plugin; 543 size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
1225 uint16_t size; 544 char buf[size];
1226
1227 GNUNET_assert (cls != NULL);
1228 endpoint = fm->session->mac;
1229 plugin = endpoint->plugin;
1230 545
1231 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 546 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1232 "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n", 547 {
1233 fm, fm->session, endpoint, hdr->type); 548 GNUNET_break (0);
1234 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + ntohs (hdr->size); 549 return;
1235 fm->radioHeader = GNUNET_malloc (size); 550 }
1236 getRadiotapHeader (plugin, fm->session->mac, fm->radioHeader, size); 551 LOG (GNUNET_ERROR_TYPE_DEBUG,
1237 getWlanHeader (&fm->radioHeader->frame, &(fm->session->mac->addr), plugin, 552 "Sending ACK to helper\n");
1238 size); 553 radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
1239 memcpy (&fm->radioHeader[1], hdr, ntohs (hdr->size)); 554 get_radiotap_header (endpoint, radio_header, size);
1240 // FIXME: yucky allocation structure! 555 get_wlan_header (endpoint->plugin,
1241 fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue)); 556 &radio_header->frame,
1242 fmqueue->content = fm; 557 &endpoint->addr,
1243 GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head, 558 size);
1244 plugin->sending_messages_tail, fmqueue); 559 memcpy (&radio_header[1], hdr, msize);
1245 set_next_send (plugin); 560 if (NULL !=
561 GNUNET_HELPER_send (endpoint->plugin->suid_helper,
562 &radio_header->header,
563 GNUNET_NO /* dropping ACKs is bad */,
564 NULL, NULL))
565 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN ACKs sent"),
566 1, GNUNET_NO);
1246} 567}
1247 568
1248 569
1249/** 570/**
1250 * We have been notified that gnunet-helper-transport-wlan has written something to stdout. 571 * Handles the data after all fragments are put together
1251 * Handle the output, then reschedule this function to be called again once
1252 * more is available.
1253 * 572 *
1254 * @param cls the plugin handle 573 * @param cls macendpoint this messages belongs to
1255 * @param tc the scheduling context 574 * @param hdr pointer to the data
1256 */ 575 */
1257static void 576static void
1258wlan_plugin_helper_read (void *cls, 577wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
1259 const struct GNUNET_SCHEDULER_TaskContext *tc)
1260{ 578{
1261 struct Plugin *plugin = cls; 579 struct MacEndpoint *endpoint = cls;
1262 580 struct Plugin *plugin = endpoint->plugin;
1263 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK; 581 struct MacAndSession mas;
1264
1265 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1266 return;
1267
1268 char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
1269 ssize_t bytes;
1270 582
1271 bytes = 583 GNUNET_STATISTICS_update (plugin->env->stats,
1272 GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf, 584 _("# WLAN messages defragmented"), 1,
1273 sizeof (mybuf)); 585 GNUNET_NO);
1274 if (bytes <= 0) 586 mas.session = NULL;
1275 { 587 mas.endpoint = endpoint;
1276 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 588 (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer,
1277 _ 589 &mas,
1278 ("Finished reading from gnunet-helper-transport-wlan stdout with code: %d\n"), 590 (const char *) hdr,
1279 bytes); 591 ntohs (hdr->size),
1280 return; 592 GNUNET_YES, GNUNET_NO);
1281 }
1282 GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
1283 GNUNET_NO, GNUNET_NO);
1284
1285 GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1286 plugin->server_read_task =
1287 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1288 plugin->server_stdout_handle,
1289 &wlan_plugin_helper_read, plugin);
1290} 593}
1291 594
595
1292/** 596/**
1293 * Start the gnunet-helper-transport-wlan process. 597 * Free a session
1294 * 598 *
1295 * @param plugin the transport plugin 599 * @param session the session free
1296 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1297 */ 600 */
1298static int 601static void
1299wlan_transport_start_wlan_helper (struct Plugin *plugin) 602free_session (struct Session *session)
1300{ 603{
1301 const char *filenamehw = "gnunet-helper-transport-wlan"; 604 struct MacEndpoint *endpoint = session->mac;
1302 const char *filenameloopback = "gnunet-helper-transport-wlan-dummy"; 605 struct PendingMessage *pm;
1303 char *absolute_filename = NULL; 606
1304 607 endpoint->plugin->env->session_end (endpoint->plugin->env->cls,
1305 if (plugin->helper_is_running == GNUNET_YES) 608 &session->target,
1306 { 609 session);
1307 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 610 while (NULL != (pm = session->pending_message_head))
1308 "wlan_transport_start_wlan_helper not needed, helper already running!"); 611 {
1309 return GNUNET_YES; 612 GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1310 } 613 session->pending_message_tail, pm);
1311 614 if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task)
1312 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
1313 if (plugin->server_stdout == NULL)
1314 return GNUNET_SYSERR;
1315
1316 plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
1317 if (plugin->server_stdin == NULL)
1318 return GNUNET_SYSERR;
1319
1320 if ((plugin->testmode == 1) || (plugin->testmode == 2))
1321 {
1322 if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
1323 {
1324 absolute_filename = GNUNET_strdup (filenameloopback);
1325 }
1326 else
1327 {
1328 char cwd[FILENAME_MAX];
1329
1330 GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
1331
1332 GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
1333 filenameloopback);
1334
1335 if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
1336 {
1337 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1338 "Helper `%s' not found! %i\n", absolute_filename);
1339 GNUNET_break (0);
1340 }
1341 }
1342 }
1343
1344 /* Start the server process */
1345
1346 if (plugin->testmode == 0)
1347 {
1348
1349 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1350 "Starting gnunet-helper-transport-wlan process cmd: %s %s %i\n",
1351 filenamehw, plugin->interface, plugin->testmode);
1352 if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
1353 {
1354 plugin->server_proc =
1355 GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
1356 filenamehw, filenamehw, plugin->interface,
1357 NULL);
1358 }
1359 else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO)
1360 {
1361 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1362 "gnunet-helper-transport-wlan is not suid, please change it or look at the doku\n");
1363 GNUNET_break (0);
1364 }
1365 else
1366 {
1367 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1368 "gnunet-helper-transport-wlan not found, please look if it exists and is the $PATH variable!\n");
1369 GNUNET_break (0);
1370 }
1371
1372 }
1373 else if (plugin->testmode == 1)
1374 {
1375
1376 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1377 "Starting gnunet-helper-transport-wlan-dummy loopback 1 process cmd: %s %s %i\n",
1378 absolute_filename, plugin->interface, plugin->testmode);
1379 plugin->server_proc =
1380 GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
1381 absolute_filename, absolute_filename, "1",
1382 NULL);
1383 if (plugin->server_proc == NULL)
1384 {
1385 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1386 "`%s' not found, please look if it exists and is in the $PATH variable!\n",
1387 absolute_filename);
1388 GNUNET_break (0);
1389 }
1390 }
1391 else if (plugin->testmode == 2)
1392 {
1393 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1394 "Starting gnunet-helper-transport-wlan-dummy loopback 2 process cmd: %s %s %i\n",
1395 absolute_filename, plugin->interface, plugin->testmode);
1396 plugin->server_proc =
1397 GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
1398 absolute_filename, absolute_filename, "2",
1399 NULL);
1400 if (plugin->server_proc == NULL)
1401 { 615 {
1402 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, 616 GNUNET_SCHEDULER_cancel (pm->timeout_task);
1403 "`%s' not found, please look if it exists and is in the $PATH variable!\n", 617 pm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1404 absolute_filename);
1405 GNUNET_break (0);
1406 } 618 }
619 GNUNET_free (pm->msg);
620 GNUNET_free (pm);
1407 } 621 }
1408 if (absolute_filename != NULL) 622 GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head,
1409 GNUNET_free (absolute_filename); 623 endpoint->sessions_tail,
1410 if (plugin->server_proc == NULL) 624 session);
625 if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1411 { 626 {
1412 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 627 GNUNET_SCHEDULER_cancel (session->timeout_task);
1413 "Failed to start gnunet-helper-transport-wlan process\n"); 628 session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1414 return GNUNET_SYSERR;
1415 } 629 }
1416 630 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), -1,
1417 631 GNUNET_NO);
1418 632 GNUNET_free (session);
1419 /* Close the write end of the read pipe */
1420 GNUNET_DISK_pipe_close_end (plugin->server_stdout,
1421 GNUNET_DISK_PIPE_END_WRITE);
1422
1423 /* Close the read end of the write pipe */
1424 GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1425
1426 plugin->server_stdout_handle =
1427 GNUNET_DISK_pipe_handle (plugin->server_stdout,
1428 GNUNET_DISK_PIPE_END_READ);
1429 plugin->server_stdin_handle =
1430 GNUNET_DISK_pipe_handle (plugin->server_stdin,
1431 GNUNET_DISK_PIPE_END_WRITE);
1432
1433 GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1434
1435 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1436 "Adding server_read_task for the gnunet-helper-transport-wlan\n");
1437 plugin->server_read_task =
1438 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1439 plugin->server_stdout_handle,
1440 &wlan_plugin_helper_read, plugin);
1441
1442 plugin->helper_is_running = GNUNET_YES;
1443 return GNUNET_YES;
1444} 633}
1445 634
635
1446/** 636/**
1447 * Stops the gnunet-helper-transport-wlan process. 637 * A session is timing out. Clean up.
1448 * 638 *
1449 * @param plugin the transport plugin 639 * @param cls pointer to the Session
1450 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error 640 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1451 */ 641 */
1452static int 642static void
1453wlan_transport_stop_wlan_helper (struct Plugin *plugin) 643session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1454{ 644{
1455 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 645 struct Session * session = cls;
1456 "Stoping WLAN helper process\n"); 646 struct GNUNET_TIME_Relative timeout;
1457 647
1458 if (plugin->helper_is_running == GNUNET_NO) 648 session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1459 { 649 timeout = GNUNET_TIME_absolute_get_remaining (session->timeout);
1460 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 650 if (0 == timeout.rel_value)
1461 "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
1462 return GNUNET_YES;
1463 }
1464 if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1465 { 651 {
1466 GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task); 652 free_session (session);
1467 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK; 653 return;
1468 }
1469 if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
1470 {
1471 GNUNET_SCHEDULER_cancel (plugin->server_write_task);
1472 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1473 }
1474 if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
1475 {
1476 GNUNET_SCHEDULER_cancel (plugin->server_read_task);
1477 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1478 } 654 }
1479 GNUNET_DISK_pipe_close (plugin->server_stdout); 655 session->timeout_task =
1480 GNUNET_DISK_pipe_close (plugin->server_stdin); 656 GNUNET_SCHEDULER_add_delayed (timeout, &session_timeout, session);
1481 GNUNET_OS_process_kill (plugin->server_proc, SIGKILL);
1482 GNUNET_OS_process_wait (plugin->server_proc);
1483 GNUNET_OS_process_destroy (plugin->server_proc);
1484 plugin->helper_is_running = GNUNET_NO;
1485 return GNUNET_YES;
1486} 657}
1487 658
659
1488/** 660/**
1489 * function for delayed restart of the helper process 661 * Create a new session
1490 * @param cls Finish_send struct if message should be finished 662 *
1491 * @param tc TaskContext 663 * @param endpoint pointer to the mac endpoint of the peer
664 * @param peer peer identity to use for this session
665 * @return returns the session
1492 */ 666 */
1493static void 667static struct Session *
1494delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 668create_session (struct MacEndpoint *endpoint,
669 const struct GNUNET_PeerIdentity *peer)
1495{ 670{
1496 struct Finish_send *finish = cls; 671 struct Session *session;
1497 struct Plugin *plugin;
1498
1499 plugin = finish->plugin;
1500
1501 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1502 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1503 {
1504 GNUNET_free_non_null (finish->msgstart);
1505 GNUNET_free (finish);
1506 return;
1507 }
1508
1509 wlan_transport_start_wlan_helper (plugin);
1510
1511 if (finish->size != 0)
1512 {
1513 plugin->server_write_task =
1514 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1515 plugin->server_stdin_handle,
1516 &finish_sending, finish);
1517 }
1518 else
1519 {
1520 set_next_send (plugin);
1521 GNUNET_free_non_null (finish->msgstart);
1522 GNUNET_free (finish);
1523 }
1524 672
673 for (session = endpoint->sessions_head; NULL != session; session = session->next)
674 if (0 == memcmp (peer, &session->target,
675 sizeof (struct GNUNET_PeerIdentity)))
676 {
677 session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
678 return session;
679 }
680 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), 1,
681 GNUNET_NO);
682 session = GNUNET_malloc (sizeof (struct Session));
683 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
684 endpoint->sessions_tail,
685 session);
686 session->mac = endpoint;
687 session->target = *peer;
688 session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
689 session->timeout_task =
690 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session);
691 LOG (GNUNET_ERROR_TYPE_DEBUG,
692 "Created new session for peer `%s' with endpoint %s\n",
693 GNUNET_i2s (peer),
694 mac_to_string (&endpoint->addr));
695 return session;
1525} 696}
1526 697
698
1527/** 699/**
1528 * Function to restart the helper 700 * Function called once we have successfully given the fragment
1529 * @param plugin pointer to the global plugin struct 701 * message to the SUID helper process and we are thus ready for
1530 * @param finish pointer to the Finish_send struct to finish 702 * the next fragment.
703 *
704 * @param cls the 'struct FragmentMessage'
705 * @param result result of the operation (GNUNET_OK on success, GNUNET_NO if the helper died, GNUNET_SYSERR
706 * if the helper was stopped)
1531 */ 707 */
1532static void 708static void
1533restart_helper (struct Plugin *plugin, struct Finish_send *finish) 709fragment_transmission_done (void *cls,
710 int result)
1534{ 711{
1535 static struct GNUNET_TIME_Relative next_try = { 1000 }; 712 struct FragmentMessage *fm = cls;
1536 GNUNET_assert (finish != NULL);
1537
1538 wlan_transport_stop_wlan_helper (plugin);
1539 plugin->server_write_task =
1540 GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish);
1541 GNUNET_TIME_relative_multiply (next_try, HELPER_RESTART_SCALING_FACTOR);
1542 713
714 fm->sh = NULL;
715 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
1543} 716}
1544 717
718
1545/** 719/**
1546 * function to finish a sending if not all could have been writen befor 720 * Transmit a fragment of a message.
1547 * @param cls pointer to the Finish_send struct 721 *
1548 * @param tc TaskContext 722 * @param cls 'struct FragmentMessage' this fragment message belongs to
723 * @param hdr pointer to the start of the fragment message
1549 */ 724 */
1550static void 725static void
1551finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 726transmit_fragment (void *cls,
727 const struct GNUNET_MessageHeader *hdr)
1552{ 728{
1553 struct Finish_send *finish = cls; 729 struct FragmentMessage *fm = cls;
1554 struct Plugin *plugin; 730 struct MacEndpoint *endpoint = fm->macendpoint;
1555 ssize_t bytes; 731 size_t size;
1556 732 uint16_t msize;
1557 plugin = finish->plugin; 733
1558 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; 734 msize = ntohs (hdr->size);
1559 735 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
1560 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) 736 {
1561 { 737 char buf[size];
1562 GNUNET_free (finish->msgstart); 738 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header;
1563 GNUNET_free (finish); 739
1564 return; 740 radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
1565 } 741 get_radiotap_header (endpoint, radio_header, size);
1566 bytes = 742 get_wlan_header (endpoint->plugin,
1567 GNUNET_DISK_file_write (plugin->server_stdin_handle, 743 &radio_header->frame,
1568 finish->head_of_next_write, finish->size); 744 &endpoint->addr,
1569 745 size);
1570 if (bytes != finish->size) 746 memcpy (&radio_header[1], hdr, msize);
1571 { 747 GNUNET_assert (NULL == fm->sh);
1572 if (bytes != GNUNET_SYSERR) 748 fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper,
1573 { 749 &radio_header->header,
1574 finish->head_of_next_write += bytes; 750 GNUNET_NO,
1575 finish->size -= bytes; 751 &fragment_transmission_done, fm);
1576 plugin->server_write_task = 752 if (NULL != fm->sh)
1577 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, 753 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN message fragments sent"),
1578 plugin->server_stdin_handle, 754 1, GNUNET_NO);
1579 &finish_sending, finish);
1580 }
1581 else 755 else
1582 { 756 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
1583 restart_helper (plugin, finish);
1584 }
1585 }
1586 else
1587 {
1588 GNUNET_free (finish->msgstart);
1589 GNUNET_free (finish);
1590 set_next_send (plugin);
1591 } 757 }
1592} 758}
1593 759
1594 760
1595/** 761/**
1596 * Function to send a HELLO beacon 762 * Frees the space of a message in the fragment queue (send queue)
1597 * 763 *
1598 * @param plugin pointer to the plugin struct 764 * @param fm message to free
1599 */ 765 */
1600static void 766static void
1601send_hello_beacon (struct Plugin *plugin) 767free_fragment_message (struct FragmentMessage *fm)
1602{ 768{
1603 uint16_t size; 769 struct MacEndpoint *endpoint = fm->macendpoint;
1604 ssize_t bytes;
1605 uint16_t hello_size;
1606 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
1607 const struct GNUNET_MessageHeader *hello;
1608 struct Finish_send *finish;
1609
1610 GNUNET_assert (plugin != NULL);
1611 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1612 "Sending hello beacon\n");
1613 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"),
1614 1, GNUNET_NO);
1615 hello = plugin->env->get_our_hello ();
1616 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1617 GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1618 770
1619 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size; 771 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN messages pending (with fragmentation)"),
1620 radioHeader = GNUNET_malloc (size); 772 -1, GNUNET_NO);
1621 getRadiotapHeader (plugin, NULL, radioHeader, size); 773 GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
1622 getWlanHeader (&radioHeader->frame, &bc_all_mac, plugin, size); 774 endpoint->sending_messages_tail, fm);
1623 memcpy (&radioHeader[1], hello, hello_size); 775 if (NULL != fm->sh)
1624 bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, radioHeader, size);
1625 GNUNET_free (radioHeader);
1626 if (bytes == GNUNET_SYSERR)
1627 { 776 {
1628 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, 777 GNUNET_HELPER_send_cancel (fm->sh);
1629 _("Error writing to WLAN helper: %s\n"), 778 fm->sh = NULL;
1630 STRERROR (errno));
1631 finish = GNUNET_malloc (sizeof (struct Finish_send));
1632 finish->plugin = plugin;
1633 finish->head_of_next_write = NULL;
1634 finish->size = 0;
1635 finish->msgstart = NULL;
1636 restart_helper (plugin, finish);
1637 set_next_beacon_time (plugin);
1638 } 779 }
1639 else 780 GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
781 if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1640 { 782 {
1641 GNUNET_assert (bytes == size); 783 GNUNET_SCHEDULER_cancel (fm->timeout_task);
1642 set_next_beacon_time (plugin); 784 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1643 set_next_send (plugin);
1644 } 785 }
786 GNUNET_free (fm);
1645} 787}
1646 788
1647 789
1648/** 790/**
1649 * function to add an ack to send it for a received fragment 791 * A FragmentMessage has timed out. Remove it.
1650 * 792 *
1651 * @param cls MacEndpoint this ack belongs to 793 * @param cls pointer to the 'struct FragmentMessage'
1652 * @param msg_id id of the message
1653 * @param hdr pointer to the hdr where the ack is stored
1654 */
1655static void
1656add_ack_for_send (void *cls, uint32_t msg_id,
1657 const struct GNUNET_MessageHeader *hdr)
1658{
1659 struct MacEndpoint *endpoint = cls;
1660 struct Plugin *plugin = endpoint->plugin;
1661 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radioHeader;
1662 struct AckSendQueue *ack;
1663 struct GNUNET_MessageHeader *msgheader;
1664 uint16_t size;
1665
1666 GNUNET_assert (endpoint != NULL);
1667 size = sizeof (struct AckSendQueue) + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + ntohs (hdr->size);
1668 ack = GNUNET_malloc (size);
1669 ack->message_id = msg_id;
1670 ack->endpoint = endpoint;
1671 radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) &ack[1];
1672 ack->radioHeader = radioHeader;
1673 getRadiotapHeader (plugin, ack->endpoint, radioHeader, size - sizeof (struct AckSendQueue));
1674 size = ntohs (hdr->size);
1675 getWlanHeader (&radioHeader->frame,
1676 &ack->endpoint->addr,
1677 plugin,
1678 size);
1679 msgheader = (struct GNUNET_MessageHeader *) &radioHeader[1];
1680 memcpy (msgheader, hdr, size);
1681 GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
1682 plugin->ack_send_queue_tail, ack);
1683 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1684 "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
1685 msg_id, ack, endpoint);
1686 set_next_send (plugin);
1687}
1688
1689
1690/**
1691 * Function for the scheduler if a FragmentMessage times out
1692 * @param cls pointer to the FragmentMessage
1693 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext 794 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1694 */ 795 */
1695static void 796static void
@@ -1698,257 +799,153 @@ fragmentmessage_timeout (void *cls,
1698{ 799{
1699 struct FragmentMessage *fm = cls; 800 struct FragmentMessage *fm = cls;
1700 801
1701 GNUNET_assert (fm != NULL);
1702 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK; 802 fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1703 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 803 if (NULL != fm->cont)
1704 return; 804 {
1705 free_fragment_message (fm->session->mac->plugin, fm); 805 fm->cont (fm->cont_cls, &fm->target, GNUNET_SYSERR);
806 fm->cont = NULL;
807 }
808 free_fragment_message (fm);
1706} 809}
1707 810
1708 811
1709/** 812/**
1710 * Function to check if there is some space in the fragment queue 813 * Transmit a message to the given destination with fragmentation.
1711 * inserts a message if space is available 814 *
1712 * @param plugin the plugin struct 815 * @param endpoint desired destination
816 * @param timeout how long can the message wait?
817 * @param target peer that should receive the message
818 * @param msg message to transmit
819 * @param cont continuation to call once the message has
820 * been transmitted (or if the transport is ready
821 * for the next transmission call; or if the
822 * peer disconnected...); can be NULL
823 * @param cont_cls closure for cont
1713 */ 824 */
1714static void 825static void
1715check_fragment_queue (struct Plugin *plugin) 826send_with_fragmentation (struct MacEndpoint *endpoint,
827 struct GNUNET_TIME_Relative timeout,
828 const struct GNUNET_PeerIdentity *target,
829 const struct GNUNET_MessageHeader *msg,
830 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
831
1716{ 832{
1717 struct Session *session;
1718 struct FragmentMessage *fm; 833 struct FragmentMessage *fm;
1719 struct GNUNET_PeerIdentity pid; 834 struct Plugin *plugin;
1720
1721 struct PendingMessage *pm;
1722
1723 if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
1724 {
1725 session = get_next_queue_session (plugin);
1726 if (session != NULL)
1727 {
1728 pm = session->pending_message_head;
1729 GNUNET_assert (pm != NULL);
1730 GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1731 session->pending_message_tail, pm);
1732 session->mac->fragment_messages_out_count++;
1733 session->fragment_messages_out_count++;
1734 plugin->pending_Fragment_Messages++;
1735 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1736 plugin->pending_Fragment_Messages, GNUNET_NO);
1737
1738 fm = GNUNET_malloc (sizeof (struct FragmentMessage));
1739 fm->session = session;
1740 fm->timeout.abs_value = pm->timeout.abs_value;
1741 fm->fragcontext =
1742 GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
1743 &plugin->tracker,
1744 GNUNET_TIME_UNIT_SECONDS,
1745 &(pm->msg->header),
1746 &add_message_for_send, fm);
1747 fm->timeout_task =
1748 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
1749 (fm->timeout), fragmentmessage_timeout,
1750 fm);
1751 GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
1752 session->mac->sending_messages_tail,
1753 fm);
1754
1755 if (pm->transmit_cont != NULL)
1756 {
1757 pid = session->target;
1758 pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
1759 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1760 "called pm->transmit_cont for %p\n", session);
1761 }
1762 else
1763 {
1764 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1765 "no pm->transmit_cont for %p\n", session);
1766 }
1767 GNUNET_free (pm);
1768
1769 if (session->pending_message_head != NULL)
1770 {
1771 //requeue session
1772 queue_session (plugin, session);
1773 }
1774
1775 }
1776 }
1777 835
1778 //check if timeout changed 836 plugin = endpoint->plugin;
1779 set_next_send (plugin); 837 fm = GNUNET_malloc (sizeof (struct FragmentMessage));
838 fm->macendpoint = endpoint;
839 fm->target = *target;
840 fm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
841 fm->fragcontext =
842 GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
843 &plugin->tracker,
844 GNUNET_TIME_UNIT_SECONDS,
845 msg,
846 &transmit_fragment, fm);
847 fm->timeout_task =
848 GNUNET_SCHEDULER_add_delayed (timeout,
849 &fragmentmessage_timeout, fm);
850 GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head,
851 endpoint->sending_messages_tail,
852 fm);
1780} 853}
1781 854
1782 855
1783/** 856/**
1784 * Function to send an ack, does not free the ack 857 * Free a MAC endpoint.
1785 * @param plugin pointer to the plugin 858 *
859 * @param endpoint pointer to the MacEndpoint to free
1786 */ 860 */
1787static void 861static void
1788send_ack (struct Plugin *plugin) 862free_macendpoint (struct MacEndpoint *endpoint)
1789{ 863{
1790 ssize_t bytes; 864 struct Plugin *plugin = endpoint->plugin;
1791 struct AckSendQueue *ack; 865 struct FragmentMessage *fm;
1792 struct Finish_send *finish; 866 struct Session *session;
1793 867
1794 GNUNET_assert (plugin != NULL); 868 GNUNET_STATISTICS_update (plugin->env->stats,
1795 ack = plugin->ack_send_queue_head; 869 _("# WLAN MAC endpoints allocated"), -1, GNUNET_NO);
1796 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 870 while (NULL != (session = endpoint->sessions_head))
1797 "Sending ack for message_id %u for mac endpoint %p, size %u\n", 871 free_session (session);
1798 ack->message_id, ack->endpoint, 872 while (NULL != (fm = endpoint->sending_messages_head))
1799 ntohs (ack->radioHeader->header.size)); 873 free_fragment_message (fm);
1800 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1, 874 GNUNET_CONTAINER_DLL_remove (plugin->mac_head,
1801 GNUNET_NO); 875 plugin->mac_tail,
1802 bytes = 876 endpoint);
1803 GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->radioHeader, 877 plugin->mac_count--;
1804 ntohs (ack->radioHeader->header.size)); 878 if (GNUNET_SCHEDULER_NO_TASK != endpoint->timeout_task)
1805 if (bytes == GNUNET_SYSERR)
1806 { 879 {
1807 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, 880 GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
1808 _ 881 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1809 ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
1810 errno, strerror (errno));
1811 finish = GNUNET_malloc (sizeof (struct Finish_send));
1812 finish->plugin = plugin;
1813 finish->head_of_next_write = NULL;
1814 finish->size = 0;
1815 finish->msgstart = NULL;
1816 restart_helper (plugin, finish);
1817 return;
1818 } 882 }
1819 GNUNET_assert (bytes == ntohs (ack->radioHeader->header.size)); 883 GNUNET_free (endpoint);
1820 GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
1821 plugin->ack_send_queue_tail, ack);
1822 GNUNET_free (ack);
1823 set_next_send (plugin);
1824} 884}
1825 885
1826 886
1827/** 887/**
1828 * Function called when wlan helper is ready to get some data 888 * A MAC endpoint is timing out. Clean up.
1829 * 889 *
1830 * @param cls closure 890 * @param cls pointer to the MacEndpoint
1831 * @param tc GNUNET_SCHEDULER_TaskContext 891 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1832 */ 892 */
1833static void 893static void
1834do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 894macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1835{ 895{
1836 struct Plugin *plugin = cls; 896 struct MacEndpoint *endpoint = cls;
1837 struct Session *session; 897 struct GNUNET_TIME_Relative timeout;
1838 struct FragmentMessage *fm;
1839 struct Finish_send *finish;
1840 struct FragmentMessage_queue *fmq;
1841 ssize_t bytes;
1842 898
1843 GNUNET_assert (plugin != NULL); 899 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1844 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK; 900 timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout);
1845 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 901 if (0 == timeout.rel_value)
1846 return;
1847 if (plugin->ack_send_queue_head != NULL)
1848 {
1849 send_ack (plugin);
1850 return;
1851 }
1852 //test if a "hello-beacon" has to be send
1853 if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
1854 {
1855 send_hello_beacon (plugin);
1856 return;
1857 }
1858 if (NULL == plugin->sending_messages_head)
1859 { 902 {
1860 /* nothing to do right now, check when to go again */ 903 free_macendpoint (endpoint);
1861 set_next_send (plugin);
1862 return; 904 return;
1863 } 905 }
1864 GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN fragments sent"), 1, 906 endpoint->timeout_task =
1865 GNUNET_NO); 907 GNUNET_SCHEDULER_add_delayed (timeout, &macendpoint_timeout,
1866 908 endpoint);
1867 fmq = plugin->sending_messages_head;
1868 fm = fmq->content;
1869 GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
1870 plugin->sending_messages_tail, fmq);
1871 GNUNET_free (fmq);
1872
1873 session = fm->session;
1874 GNUNET_assert (session != NULL);
1875 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1876 "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
1877 fm, ntohs (fm->radioHeader->header.size));
1878 bytes =
1879 GNUNET_DISK_file_write (plugin->server_stdin_handle,
1880 fm->radioHeader,
1881 ntohs (fm->radioHeader->header.size));
1882 if (bytes != ntohs (fm->radioHeader->header.size))
1883 {
1884 finish = GNUNET_malloc (sizeof (struct Finish_send));
1885 finish->plugin = plugin;
1886 finish->msgstart = &fm->radioHeader->header;
1887 GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1888 if (bytes == GNUNET_SYSERR)
1889 {
1890 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1891 _("Error writing to WLAN helper: %s\n"),
1892 STRERROR (errno));
1893 finish->head_of_next_write = (char*) fm->radioHeader;
1894 finish->size = ntohs (fm->radioHeader->header.size);
1895 restart_helper (plugin, finish);
1896 }
1897 else
1898 {
1899 finish->head_of_next_write = ((char*) fm->radioHeader) + bytes;
1900 finish->size = ntohs (fm->radioHeader->header.size) - bytes;
1901 plugin->server_write_task =
1902 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1903 plugin->server_stdin_handle,
1904 &finish_sending, finish);
1905 }
1906 }
1907 else
1908 {
1909 GNUNET_free (fm->radioHeader);
1910 fm->radioHeader = NULL;
1911 set_next_send (plugin);
1912 }
1913 GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
1914} 909}
1915 910
1916 911
1917/** 912/**
1918 * Another peer has suggested an address for this 913 * Find (or create) a MacEndpoint with a specific MAC address
1919 * peer and transport plugin. Check that this could be a valid
1920 * address. If so, consider adding it to the list
1921 * of addresses.
1922 * 914 *
1923 * @param cls closure 915 * @param plugin pointer to the plugin struct
1924 * @param addr pointer to the address 916 * @param addr the MAC address of the endpoint
1925 * @param addrlen length of addr 917 * @return handle to our data structure for this MAC
1926 * @return GNUNET_OK if this is a plausible address for this peer
1927 * and transport
1928 */ 918 */
1929static int 919static struct MacEndpoint *
1930wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) 920create_macendpoint (struct Plugin *plugin,
921 const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr)
1931{ 922{
1932 //struct Plugin *plugin = cls; 923 struct MacEndpoint *pos;
1933 924
1934 /* check if the address is plausible; if so, 925 for (pos = plugin->mac_head; NULL != pos; pos = pos->next)
1935 * add it to our list! */ 926 if (0 == memcmp (addr, &pos->addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1936 927 return pos;
1937 GNUNET_assert (cls != NULL); 928 pos = GNUNET_malloc (sizeof (struct MacEndpoint));
1938 //FIXME mitm is not checked 929 pos->addr = *addr;
1939 //Mac Address has 6 bytes 930 pos->plugin = plugin;
1940 if (addrlen == 6) 931 pos->defrag =
1941 { 932 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
1942 /* TODO check for bad addresses like multicast, broadcast, etc */ 933 MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
1943 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 934 pos,
1944 "wlan_plugin_address_suggested got good address, size %u!\n", 935 &wlan_data_message_handler,
1945 addrlen); 936 &send_ack);
1946 return GNUNET_OK; 937 pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
1947 } 938 pos->timeout_task =
1948 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 939 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
1949 "wlan_plugin_address_suggested got bad address, size %u!\n", 940 pos);
1950 addrlen); 941 GNUNET_CONTAINER_DLL_insert (plugin->mac_head, plugin->mac_tail, pos);
1951 return GNUNET_SYSERR; 942 plugin->mac_count++;
943 GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
944 1, GNUNET_NO);
945 LOG (GNUNET_ERROR_TYPE_DEBUG,
946 "New MAC endpoint `%s'\n",
947 mac_to_string (addr));
948 return pos;
1952} 949}
1953 950
1954 951
@@ -1960,33 +957,55 @@ wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
1960 * @param address the address 957 * @param address the address
1961 * @return the session or NULL of max connections exceeded 958 * @return the session or NULL of max connections exceeded
1962 */ 959 */
1963
1964static struct Session * 960static struct Session *
1965wlan_plugin_get_session (void *cls, 961wlan_plugin_get_session (void *cls,
1966 const struct GNUNET_HELLO_Address *address) 962 const struct GNUNET_HELLO_Address *address)
1967{ 963{
1968 struct Plugin *plugin = cls; 964 struct Plugin *plugin = cls;
1969 struct Session * s = NULL; 965 struct MacEndpoint *endpoint;
1970
1971 GNUNET_assert (plugin != NULL);
1972 GNUNET_assert (address != NULL);
1973 966
1974 if (GNUNET_OK == wlan_plugin_address_suggested (plugin, 967 if (NULL == address)
1975 address->address, 968 return NULL;
1976 address->address_length)) 969 if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != address->address_length)
1977 {
1978 s = get_session (plugin, address->address, &address->peer);
1979 }
1980 else
1981 { 970 {
1982 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME, 971 GNUNET_break (0);
1983 _("Wlan Address len %d is wrong\n"), address->address_length); 972 return NULL;
1984 return s;
1985 } 973 }
974 LOG (GNUNET_ERROR_TYPE_DEBUG,
975 "Service asked to create session for peer `%s' with MAC `%s'\n",
976 GNUNET_i2s (&address->peer),
977 mac_to_string (address->address));
978 endpoint = create_macendpoint (plugin, address->address);
979 return create_session (endpoint, &address->peer);
980}
981
982
983/**
984 * Function that can be used to force the plugin to disconnect
985 * from the given peer and cancel all previous transmissions
986 * (and their continuation).
987 *
988 * @param cls closure
989 * @param target peer from which to disconnect
990 */
991static void
992wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
993{
994 struct Plugin *plugin = cls;
995 struct Session *session;
996 struct MacEndpoint *endpoint;
1986 997
1987 return s; 998 for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next)
999 for (session = endpoint->sessions_head; NULL != session; session = session->next)
1000 if (0 == memcmp (target, &session->target,
1001 sizeof (struct GNUNET_PeerIdentity)))
1002 {
1003 free_session (session);
1004 break; /* inner-loop only (in case peer has another MAC as well!) */
1005 }
1988} 1006}
1989 1007
1008
1990/** 1009/**
1991 * Function that can be used by the transport service to transmit 1010 * Function that can be used by the transport service to transmit
1992 * a message using the plugin. Note that in the case of a 1011 * a message using the plugin. Note that in the case of a
@@ -2023,801 +1042,489 @@ wlan_plugin_send (void *cls,
2023 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) 1042 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
2024{ 1043{
2025 struct Plugin *plugin = cls; 1044 struct Plugin *plugin = cls;
2026 struct PendingMessage *newmsg;
2027 struct WlanHeader *wlanheader; 1045 struct WlanHeader *wlanheader;
2028 1046 size_t size = msgbuf_size + sizeof (struct WlanHeader);
2029 GNUNET_assert (plugin != NULL); 1047 char buf[size] GNUNET_ALIGN;
2030 GNUNET_assert (session != NULL); 1048
2031 GNUNET_assert (msgbuf_size > 0); 1049 LOG (GNUNET_ERROR_TYPE_DEBUG,
2032 1050 "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n",
2033 //queue message: 1051 msgbuf_size,
2034 1052 GNUNET_i2s (&session->target),
2035 //queue message in session 1053 (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size),
2036 //test if there is no other message in the "queue" 1054 (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type));
2037 //FIXME: to many send requests 1055 wlanheader = (struct WlanHeader *) buf;
2038 if (session->pending_message_head != NULL)
2039 {
2040 newmsg = session->pending_message_head;
2041 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2042 "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages for this mac connection %u\n",
2043 GNUNET_TIME_absolute_get_remaining (newmsg->
2044 timeout).rel_value,
2045 session->mac->fragment_messages_out_count);
2046 }
2047
2048 newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
2049 newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
2050 wlanheader = newmsg->msg;
2051 //copy msg to buffer, not fragmented / segmented yet, but with message header
2052 wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader)); 1056 wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
2053 wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA); 1057 wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
2054 memcpy (&(wlanheader->target), &session->target, sizeof (struct GNUNET_PeerIdentity)); 1058 wlanheader->sender = *plugin->env->my_identity;
2055 memcpy (&(wlanheader->source), plugin->env->my_identity, 1059 wlanheader->target = session->target;
2056 sizeof (struct GNUNET_PeerIdentity)); 1060 wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size));
2057 wlanheader->crc = 0;
2058 memcpy (&wlanheader[1], msgbuf, msgbuf_size); 1061 memcpy (&wlanheader[1], msgbuf, msgbuf_size);
2059 wlanheader->crc = 1062 send_with_fragmentation (session->mac,
2060 htonl (GNUNET_CRYPTO_crc32_n 1063 to,
2061 ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader))); 1064 &session->target,
2062 1065 &wlanheader->header,
2063 newmsg->transmit_cont = cont; 1066 cont, cont_cls);
2064 newmsg->transmit_cont_cls = cont_cls; 1067 return size;
2065 newmsg->timeout = GNUNET_TIME_relative_to_absolute (to);
2066
2067 newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
2068
2069 newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
2070
2071 GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
2072 session->pending_message_tail, newmsg);
2073
2074 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2075 "New message for %p with size (incl wlan header) %u added\n",
2076 session, newmsg->message_size);
2077 //queue session
2078 queue_session (plugin, session);
2079
2080 check_fragment_queue (plugin);
2081 //FIXME not the correct size
2082 return msgbuf_size;
2083} 1068}
2084 1069
2085 1070
2086/** 1071/**
2087 * function to free a mac endpoint 1072 * We have received data from the WLAN via some session. Process depending
2088 * @param plugin pointer to the plugin struct 1073 * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK).
2089 * @param endpoint pointer to the MacEndpoint to free
2090 */
2091static void
2092free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
2093{
2094 struct Sessionqueue *sessions;
2095 struct Sessionqueue *sessions_next;
2096
2097 GNUNET_assert (endpoint != NULL);
2098
2099 sessions = endpoint->sessions_head;
2100 while (sessions != NULL)
2101 {
2102 sessions_next = sessions->next;
2103 free_session (plugin, sessions, GNUNET_NO);
2104 sessions = sessions_next;
2105 }
2106
2107 GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
2108 if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2109 {
2110 GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
2111 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2112 }
2113 plugin->mac_count--;
2114 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2115 plugin->mac_count, GNUNET_NO);
2116 GNUNET_free (endpoint);
2117
2118}
2119
2120/**
2121 * function to free a session
2122 * @param plugin pointer to the plugin
2123 * @param queue pointer to the sessionqueue element to free
2124 * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
2125 */
2126static void
2127free_session (struct Plugin *plugin, struct Sessionqueue *queue,
2128 int do_free_macendpoint)
2129{
2130 struct Sessionqueue *pendingsession;
2131 struct Sessionqueue *pendingsession_tmp;
2132 struct PendingMessage *pm;
2133 struct MacEndpoint *endpoint;
2134 struct FragmentMessage *fm;
2135 struct FragmentMessage *fmnext;
2136 int check = 0;
2137
2138 GNUNET_assert (plugin != NULL);
2139 GNUNET_assert (queue != NULL);
2140 GNUNET_assert (queue->content != NULL);
2141
2142 //session found
2143 //is this session pending for send
2144 pendingsession = plugin->pending_Sessions_head;
2145 while (pendingsession != NULL)
2146 {
2147 pendingsession_tmp = pendingsession;
2148 pendingsession = pendingsession->next;
2149 GNUNET_assert (pendingsession_tmp->content != NULL);
2150 if (pendingsession_tmp->content == queue->content)
2151 {
2152 plugin->pendingsessions--;
2153 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
2154 plugin->pendingsessions, GNUNET_NO);
2155 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2156 plugin->pending_Sessions_tail,
2157 pendingsession_tmp);
2158 GNUNET_free (pendingsession_tmp);
2159
2160 GNUNET_assert (check == 0);
2161 check = 1;
2162 }
2163 }
2164
2165 endpoint = queue->content->mac;
2166 fm = endpoint->sending_messages_head;
2167 while (fm != NULL)
2168 {
2169 fmnext = fm->next;
2170 if (fm->session == queue->content)
2171 free_fragment_message (plugin, fm);
2172 fm = fmnext;
2173 }
2174
2175 // remove PendingMessage
2176 pm = queue->content->pending_message_head;
2177 while (pm != NULL)
2178 {
2179 GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
2180 queue->content->pending_message_tail, pm);
2181 GNUNET_free (pm->msg);
2182 GNUNET_free (pm);
2183 pm = queue->content->pending_message_head;
2184 }
2185
2186 GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
2187 queue);
2188 //Check that no ohter session on this endpoint for this session exits
2189 GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
2190 NULL);
2191 if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
2192 {
2193 free_macendpoint (plugin, endpoint);
2194 //check if no endpoint with the same address exists
2195 GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
2196 NULL);
2197 }
2198
2199 if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2200 {
2201 GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
2202 queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2203 }
2204 GNUNET_free (queue);
2205
2206 check_fragment_queue (plugin);
2207}
2208
2209/**
2210 * Function that can be used to force the plugin to disconnect
2211 * from the given peer and cancel all previous transmissions
2212 * (and their continuation).
2213 * 1074 *
2214 * @param cls closure 1075 * @param cls pointer to the plugin
2215 * @param target peer from which to disconnect 1076 * @param client pointer to the session this message belongs to
1077 * @param hdr start of the message
2216 */ 1078 */
2217static void 1079static void
2218wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 1080process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2219{ 1081{
2220 struct Plugin *plugin = cls; 1082 struct Plugin *plugin = cls;
2221 struct Sessionqueue *queue; 1083 struct MacAndSession *mas = client;
2222 struct Sessionqueue *queue_next; 1084 struct MacAndSession xmas;
2223 struct MacEndpoint *endpoint = plugin->mac_head; 1085#define NUM_ATS 2
2224 struct MacEndpoint *endpoint_next; 1086 struct GNUNET_ATS_Information ats[NUM_ATS]; /* FIXME: do better here */
1087 struct FragmentMessage *fm;
1088 struct GNUNET_PeerIdentity tmpsource;
1089 const struct WlanHeader *wlanheader;
1090 int ret;
1091 uint16_t msize;
2225 1092
2226 // just look at all the session for the needed one 1093 ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
2227 while (endpoint != NULL) 1094 ats[0].value = htonl (1);
1095 ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1096 ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
1097 msize = ntohs (hdr->size);
1098 switch (ntohs (hdr->type))
2228 { 1099 {
2229 queue = endpoint->sessions_head; 1100 case GNUNET_MESSAGE_TYPE_HELLO:
2230 endpoint_next = endpoint->next; 1101 if (GNUNET_OK !=
2231 while (queue != NULL) 1102 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource))
2232 { 1103 {
2233 // content is never NULL 1104 GNUNET_break_op (0);
2234 GNUNET_assert (queue->content != NULL); 1105 break;
2235 queue_next = queue->next;
2236 if (memcmp
2237 (target, &(queue->content->target),
2238 sizeof (struct GNUNET_PeerIdentity)) == 0)
2239 {
2240 free_session (plugin, queue, GNUNET_YES);
2241 }
2242 // try next
2243 queue = queue_next;
2244 } 1106 }
2245 endpoint = endpoint_next; 1107 LOG (GNUNET_ERROR_TYPE_DEBUG,
2246 } 1108 "Processing %u bytes of HELLO from peer `%s' at MAC %s\n",
2247} 1109 (unsigned int) msize,
2248 1110 GNUNET_i2s (&tmpsource),
2249/** 1111 mac_to_string (&mas->endpoint->addr));
2250 * Convert the transports address to a nice, human-readable
2251 * format.
2252 *
2253 * @param cls closure
2254 * @param type name of the transport that generated the address
2255 * @param addr one of the addresses of the host, NULL for the last address
2256 * the specific address format depends on the transport
2257 * @param addrlen length of the address
2258 * @param numeric should (IP) addresses be displayed in numeric form?
2259 * @param timeout after how long should we give up?
2260 * @param asc function to call on each string
2261 * @param asc_cls closure for asc
2262 */
2263static void
2264wlan_plugin_address_pretty_printer (void *cls, const char *type,
2265 const void *addr, size_t addrlen,
2266 int numeric,
2267 struct GNUNET_TIME_Relative timeout,
2268 GNUNET_TRANSPORT_AddressStringCallback asc,
2269 void *asc_cls)
2270{
2271 char *ret;
2272 const unsigned char *input;
2273
2274 //GNUNET_assert(cls !=NULL);
2275 if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
2276 {
2277 /* invalid address (MAC addresses have 6 bytes) */
2278 //GNUNET_break (0);
2279 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2280 "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
2281 addrlen);
2282 asc (asc_cls, NULL);
2283 return;
2284 }
2285 input = (const unsigned char *) addr;
2286 GNUNET_asprintf (&ret,
2287 "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
2288 type, PROTOCOL_PREFIX, input[0], input[1], input[2],
2289 input[3], input[4], input[5]);
2290 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2291 "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
2292 addrlen, numeric, type, ret);
2293 asc (asc_cls, ret);
2294 //only one mac address per plugin
2295 asc (asc_cls, NULL);
2296}
2297
2298
2299
2300/**
2301 * handels the data after all fragments are put together
2302 * @param cls macendpoint this messages belongs to
2303 * @param hdr pointer to the data
2304 */
2305static void
2306wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
2307{
2308 struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
2309 struct Plugin *plugin = endpoint->plugin;
2310 struct WlanHeader *wlanheader;
2311 struct Session *session;
2312
2313 const struct GNUNET_MessageHeader *temp_hdr;
2314 struct GNUNET_PeerIdentity tmpsource;
2315 int crc;
2316
2317 GNUNET_assert (plugin != NULL);
2318
2319 if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2320 {
2321
2322 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2323 "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2324 ntohs (hdr->size));
2325 1112
2326 if (ntohs (hdr->size) < 1113 GNUNET_STATISTICS_update (plugin->env->stats,
2327 sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader)) 1114 _("# HELLO messages received via WLAN"), 1,
1115 GNUNET_NO);
1116 plugin->env->receive (plugin->env->cls,
1117 &tmpsource,
1118 hdr,
1119 ats, NUM_ATS,
1120 mas->session,
1121 (mas->endpoint == NULL) ? NULL : (const char *) &mas->endpoint->addr,
1122 (mas->endpoint == NULL) ? 0 : sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1123 break;
1124 case GNUNET_MESSAGE_TYPE_FRAGMENT:
1125 if (NULL == mas->endpoint)
2328 { 1126 {
2329 //packet not big enought 1127 GNUNET_break (0);
2330 return; 1128 break;
2331 } 1129 }
2332 1130 LOG (GNUNET_ERROR_TYPE_DEBUG,
1131 "Processing %u bytes of FRAGMENT from MAC %s\n",
1132 (unsigned int) msize,
1133 mac_to_string (&mas->endpoint->addr));
2333 GNUNET_STATISTICS_update (plugin->env->stats, 1134 GNUNET_STATISTICS_update (plugin->env->stats,
2334 _("# wlan whole messages received"), 1, 1135 _("# fragments received via WLAN"), 1, GNUNET_NO);
2335 GNUNET_NO); 1136 (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag,
2336 wlanheader = (struct WlanHeader *) hdr; 1137 hdr);
2337 1138 break;
2338 session = search_session (plugin, endpoint, &wlanheader->source); 1139 case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
2339 1140 if (NULL == mas->endpoint)
2340 temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2341 crc = ntohl (wlanheader->crc);
2342 wlanheader->crc = 0;
2343 if (GNUNET_CRYPTO_crc32_n
2344 ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
2345 { 1141 {
2346 //wrong crc, dispose message 1142 GNUNET_break (0);
2347 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME, 1143 break;
2348 "Wlan message header crc was wrong: %u != %u\n",
2349 GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
2350 ntohs (wlanheader->header.size)),
2351 crc);
2352 return;
2353 } 1144 }
2354 1145 GNUNET_STATISTICS_update (plugin->env->stats, _("# ACKs received via WLAN"),
2355 //if not in session list 1146 1, GNUNET_NO);
2356 if (session == NULL) 1147 for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next)
2357 { 1148 {
2358 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1149 ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
2359 "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n", 1150 if (GNUNET_OK == ret)
2360 ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
2361 sizeof (struct WlanHeader));
2362 //try if it is a hello message
2363 if (ntohs (wlanheader->header.size) >=
2364 ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
2365 { 1151 {
2366 if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO) 1152 LOG (GNUNET_ERROR_TYPE_DEBUG,
2367 { 1153 "Got last ACK, finished message transmission to `%s' (%p)\n",
2368 if (GNUNET_HELLO_get_id 1154 mac_to_string (&mas->endpoint->addr),
2369 ((const struct GNUNET_HELLO_Message *) temp_hdr, 1155 fm);
2370 &tmpsource) == GNUNET_OK) 1156 mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
2371 { 1157 if (NULL != fm->cont)
2372 session = create_session (plugin, endpoint, &tmpsource); 1158 {
2373 } 1159 fm->cont (fm->cont_cls, &fm->target, GNUNET_OK);
2374 else 1160 fm->cont = NULL;
2375 { 1161 }
2376 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME, 1162 free_fragment_message (fm);
2377 "WLAN client not in session list and hello message is not okay\n"); 1163 break;
2378 return;
2379 }
2380
2381 }
2382 else
2383 {
2384 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2385 "WLAN client not in session list and not a hello message\n");
2386 return;
2387 }
2388 } 1164 }
2389 else 1165 if (GNUNET_NO == ret)
2390 { 1166 {
2391 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME, 1167 LOG (GNUNET_ERROR_TYPE_DEBUG,
2392 "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n", 1168 "Got an ACK, message transmission to `%s' not yet finished\n",
2393 ntohs (wlanheader->header.size), 1169 mac_to_string (&mas->endpoint->addr));
2394 ntohs (temp_hdr->size), sizeof (struct WlanHeader)); 1170 break;
2395 return;
2396 } 1171 }
2397 } 1172 }
2398 1173 LOG (GNUNET_ERROR_TYPE_DEBUG,
2399 //"receive" the message 1174 "ACK not matched against any active fragmentation with MAC `%s'\n",
2400 1175 mac_to_string (&mas->endpoint->addr));
2401 if (memcmp 1176 break;
2402 (&wlanheader->source, &session->target, 1177 case GNUNET_MESSAGE_TYPE_WLAN_DATA:
2403 sizeof (struct GNUNET_PeerIdentity)) != 0) 1178 if (NULL == mas->endpoint)
2404 { 1179 {
2405 //wrong peer id 1180 GNUNET_break (0);
2406 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1181 break;
2407 "WLAN peer source id doesn't match packet peer source id: session %p\n",
2408 session);
2409 return;
2410 } 1182 }
2411 1183 if (msize < sizeof (struct WlanHeader))
2412 if (memcmp 1184 {
2413 (&wlanheader->target, plugin->env->my_identity, 1185 GNUNET_break (0);
2414 sizeof (struct GNUNET_PeerIdentity)) != 0) 1186 break;
1187 }
1188 wlanheader = (const struct WlanHeader *) hdr;
1189 if (0 != memcmp (&wlanheader->target,
1190 plugin->env->my_identity,
1191 sizeof (struct GNUNET_PeerIdentity)))
2415 { 1192 {
2416 //wrong peer id 1193 LOG (GNUNET_ERROR_TYPE_DEBUG,
2417 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1194 "WLAN data for `%s', not for me, ignoring\n",
2418 "WLAN peer target id doesn't match our peer id: session %p\n", 1195 GNUNET_i2s (&wlanheader->target));
2419 session); 1196 break;
2420 return;
2421 } 1197 }
2422 1198 if (ntohl (wlanheader->crc) !=
2423 GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session, 1199 GNUNET_CRYPTO_crc32_n (&wlanheader[1], msize - sizeof (struct WlanHeader)))
2424 (const char *) temp_hdr, 1200 {
2425 ntohs (hdr->size) - sizeof (struct WlanHeader), 1201 GNUNET_STATISTICS_update (plugin->env->stats,
2426 GNUNET_YES, GNUNET_NO); 1202 _("# WLAN DATA messages discarded due to CRC32 error"), 1,
2427 1203 GNUNET_NO);
2428 return; 1204 break;
2429 } 1205 }
2430 else 1206 xmas.endpoint = mas->endpoint;
2431 { 1207 xmas.session = create_session (mas->endpoint, &wlanheader->sender);
2432 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME, 1208 LOG (GNUNET_ERROR_TYPE_DEBUG,
2433 "wlan_data_message_handler got wrong message type: %u\n", 1209 "Processing %u bytes of WLAN DATA from peer `%s'\n",
2434 ntohs (hdr->size)); 1210 (unsigned int) msize,
2435 return; 1211 GNUNET_i2s (&wlanheader->sender));
1212 (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer,
1213 &xmas,
1214 (const char *) &wlanheader[1],
1215 msize - sizeof (struct WlanHeader),
1216 GNUNET_YES, GNUNET_NO);
1217 break;
1218 default:
1219 if (NULL == mas->endpoint)
1220 {
1221 GNUNET_break (0);
1222 break;
1223 }
1224 if (NULL == mas->session)
1225 {
1226 GNUNET_break (0);
1227 break;
1228 }
1229 LOG (GNUNET_ERROR_TYPE_DEBUG,
1230 "Received packet with %u bytes of type %u from peer %s\n",
1231 (unsigned int) msize,
1232 (unsigned int) ntohs (hdr->type),
1233 GNUNET_i2s (&mas->session->target));
1234 plugin->env->receive (plugin->env->cls,
1235 &mas->session->target,
1236 hdr,
1237 ats, NUM_ATS,
1238 mas->session,
1239 (mas->endpoint == NULL) ? NULL : (const char *) &mas->endpoint->addr,
1240 (mas->endpoint == NULL) ? 0 : sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1241 break;
2436 } 1242 }
2437} 1243}
1244#undef NUM_ATS
2438 1245
2439/**
2440 * function to process the a message, give it to the higher layer
2441 * @param cls pointer to the plugin
2442 * @param client pointer to the session this message belongs to
2443 * @param hdr start of the message
2444 */
2445//TODO ATS informations
2446static void
2447process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2448{
2449
2450 GNUNET_assert (client != NULL);
2451 GNUNET_assert (cls != NULL);
2452 struct Session *session = (struct Session *) client;
2453 struct Plugin *plugin = (struct Plugin *) cls;
2454 struct GNUNET_ATS_Information ats[2];
2455
2456 ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
2457 ats[0].value = htonl (1);
2458 ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
2459 ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
2460
2461 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2462 "Calling plugin->env->receive for session %p; %s; size: %u\n",
2463 session, wlan_plugin_address_to_string (NULL,
2464 session->mac->
2465 addr.mac, 6),
2466 htons (hdr->size));
2467 plugin->env->receive (plugin->env->cls, &(session->target), hdr,
2468 (const struct GNUNET_ATS_Information *) &ats, 2,
2469 session, (const char *) &session->mac->addr,
2470 sizeof (session->mac->addr));
2471}
2472 1246
2473/** 1247/**
2474 * Function used for to process the data received from the wlan interface 1248 * Function used for to process the data from the suid process
2475 * 1249 *
2476 * @param cls the plugin handle 1250 * @param cls the plugin handle
2477 * @param hdr hdr of the GNUNET_MessageHeader 1251 * @param client client that send the data (not used)
2478 * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS info 1252 * @param hdr header of the GNUNET_MessageHeader
2479 */ 1253 */
2480static void 1254static void
2481wlan_data_helper (void *cls, 1255handle_helper_message (void *cls, void *client,
2482 const struct GNUNET_MessageHeader *hdr, 1256 const struct GNUNET_MessageHeader *hdr)
2483 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo)
2484{ 1257{
2485 struct Plugin *plugin = cls; 1258 struct Plugin *plugin = cls;
2486 struct FragmentMessage *fm; 1259 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo;
2487 struct FragmentMessage *fm2; 1260 const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
2488 struct GNUNET_PeerIdentity tmpsource; 1261 struct MacAndSession mas;
2489 struct MacEndpoint *macendpoint; 1262 uint16_t msize;
2490 struct Session *session;
2491
2492 // NOTE: session_light->addr = rxinfo->frame.addr2;
2493 macendpoint = get_macendpoint (plugin, &rxinfo->frame.addr2, GNUNET_YES);
2494 1263
1264 msize = ntohs (hdr->size);
2495 switch (ntohs (hdr->type)) 1265 switch (ntohs (hdr->type))
2496 { 1266 {
2497 case GNUNET_MESSAGE_TYPE_HELLO: 1267 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2498 //ADVERTISEMENT 1268 if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
2499 //TODO better DOS protection, error handling
2500 //TODO test first then create session
2501 if (GNUNET_HELLO_get_id
2502 ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
2503 { 1269 {
2504 session = search_session (plugin, macendpoint, &tmpsource); 1270 GNUNET_break (0);
2505 if (session == NULL) 1271 break;
2506 {
2507 session = create_session (plugin, macendpoint, &tmpsource);
2508 }
2509 GNUNET_STATISTICS_update (plugin->env->stats,
2510 _("# wlan hello messages received"), 1,
2511 GNUNET_NO);
2512 plugin->env->receive (plugin->env->cls, &session->target,
2513 hdr, NULL, 0, session,
2514 (const char *) &session->mac->addr,
2515 sizeof (session->mac->addr));
2516 } 1272 }
2517 else 1273 cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
1274 if (GNUNET_YES == plugin->have_mac)
2518 { 1275 {
2519 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME, 1276 if (0 == memcmp (&plugin->mac_address,
2520 "WLAN client not in session list and HELLO message is not okay\n"); 1277 &cm->mac,
2521 return; 1278 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1279 break; /* no change */
1280 /* remove old address */
1281 plugin->env->notify_address (plugin->env->cls, GNUNET_NO,
1282 &plugin->mac_address,
1283 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
2522 } 1284 }
1285 plugin->mac_address = cm->mac;
1286 plugin->have_mac = GNUNET_YES;
1287 LOG (GNUNET_ERROR_TYPE_DEBUG,
1288 "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n",
1289 mac_to_string (&cm->mac),
1290 GNUNET_i2s (plugin->env->my_identity));
1291 plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
1292 &plugin->mac_address,
1293 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
2523 break; 1294 break;
2524 case GNUNET_MESSAGE_TYPE_FRAGMENT: 1295 case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER:
2525 macendpoint = get_macendpoint (plugin, &rxinfo->frame.addr2, GNUNET_YES); 1296 LOG (GNUNET_ERROR_TYPE_DEBUG,
1297 "Got data message from helper with %u bytes\n",
1298 msize);
2526 GNUNET_STATISTICS_update (plugin->env->stats, 1299 GNUNET_STATISTICS_update (plugin->env->stats,
2527 _("# wlan fragments received"), 1, GNUNET_NO); 1300 _("# DATA messages received via WLAN"), 1,
2528 int ret = 1301 GNUNET_NO);
2529 GNUNET_DEFRAGMENT_process_fragment (macendpoint->defrag, 1302 if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
2530 hdr);
2531
2532 if (ret == GNUNET_NO)
2533 { 1303 {
2534 macendpoint->dups++; 1304 GNUNET_break (0);
1305 LOG (GNUNET_ERROR_TYPE_DEBUG,
1306 "Size of packet is too small (%u bytes)\n",
1307 msize);
1308 break;
2535 } 1309 }
2536 else if (ret == GNUNET_OK) 1310 rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
1311
1312 /* check if message is actually for us */
1313 if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet,
1314 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
2537 { 1315 {
2538 macendpoint->fragc++; 1316 /* Not the GNUnet BSSID */
1317 break;
2539 } 1318 }
2540 set_next_send (plugin); 1319 if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac,
2541 break; 1320 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) &&
2542 case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK: 1321 (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address,
2543 if (NULL == macendpoint) 1322 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) )
2544 { 1323 {
2545 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1324 /* Neither broadcast nor specifically for us */
2546 "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n", 1325 break;
2547 ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2548 &rxinfo->frame.addr2.mac,
2549 6));
2550 return;
2551 } 1326 }
2552 fm = macendpoint->sending_messages_head; 1327 if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address,
2553 while (fm != NULL) 1328 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
2554 { 1329 {
2555 fm2 = fm->next; 1330 /* packet is FROM us, thus not FOR us */
2556 GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"), 1331 break;
2557 1, GNUNET_NO);
2558 int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
2559
2560 if (ret == GNUNET_OK)
2561 {
2562 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2563 "Got last ack, finished fragment message %p\n", fm);
2564 macendpoint->acks++;
2565 fm->session->last_activity = GNUNET_TIME_absolute_get ();
2566 macendpoint->last_activity = fm->session->last_activity;
2567 free_fragment_message (plugin, fm);
2568 check_fragment_queue (plugin);
2569 return;
2570 }
2571 if (ret == GNUNET_NO)
2572 {
2573 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2574 "Got ack for: %p\n", fm);
2575 macendpoint->acks++;
2576 return;
2577 }
2578 fm = fm2;
2579 } 1332 }
2580 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1333
2581 "WLAN fragment not in fragment list\n"); 1334 GNUNET_STATISTICS_update (plugin->env->stats,
2582 return; 1335 _("# WLAN DATA messages processed"),
1336 1, GNUNET_NO);
1337 LOG (GNUNET_ERROR_TYPE_DEBUG,
1338 "Receiving %u bytes of data from MAC `%s'\n",
1339 (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
1340 mac_to_string (&rxinfo->frame.addr2));
1341 mas.endpoint = create_macendpoint (plugin, &rxinfo->frame.addr2);
1342 mas.session = NULL;
1343 (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer,
1344 &mas,
1345 (const char*) &rxinfo[1],
1346 msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage),
1347 GNUNET_YES, GNUNET_NO);
1348 break;
2583 default: 1349 default:
2584 // TODO Wrong data?
2585 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2586 "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2587 ntohs (hdr->type), ntohs (hdr->size));
2588 GNUNET_break (0); 1350 GNUNET_break (0);
2589 return; 1351 LOG (GNUNET_ERROR_TYPE_DEBUG,
1352 "Unexpected message of type %u (%u bytes)",
1353 ntohs (hdr->type), ntohs (hdr->size));
1354 break;
2590 } 1355 }
2591 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2592 "Helper finished\n");
2593} 1356}
2594 1357
1358
1359
2595/** 1360/**
2596 * Function to print mac addresses nicely. 1361 * Task to (periodically) send a HELLO beacon
2597 * 1362 *
2598 * @param mac the mac address 1363 * @param cls pointer to the plugin struct
2599 * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function 1364 * @param tc scheduler context
2600 */ 1365 */
2601static const char * 1366static void
2602macprinter (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac) 1367send_hello_beacon (void *cls,
1368 const struct GNUNET_SCHEDULER_TaskContext *tc)
2603{ 1369{
2604 static char macstr[20]; 1370 struct Plugin *plugin = cls;
1371 uint16_t size;
1372 uint16_t hello_size;
1373 struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
1374 const struct GNUNET_MessageHeader *hello;
1375
1376 hello = plugin->env->get_our_hello ();
1377 hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1378 GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1379 size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size;
1380 {
1381 char buf[size] GNUNET_ALIGN;
1382
1383 LOG (GNUNET_ERROR_TYPE_DEBUG,
1384 "Sending %u byte HELLO beacon\n",
1385 (unsigned int) size);
1386 radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf;
1387 get_radiotap_header (NULL, radioHeader, size);
1388 get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size);
1389 memcpy (&radioHeader[1], hello, hello_size);
1390 if (NULL !=
1391 GNUNET_HELPER_send (plugin->suid_helper,
1392 &radioHeader->header,
1393 GNUNET_YES /* can drop */,
1394 NULL, NULL))
1395 GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO beacons sent via WLAN"),
1396 1, GNUNET_NO);
1397 }
1398 plugin->beacon_task =
1399 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1400 (HELLO_BEACON_SCALING_FACTOR,
1401 plugin->mac_count + 1),
1402 &send_hello_beacon,
1403 plugin);
2605 1404
2606 GNUNET_snprintf (macstr, sizeof (macstr), "%2X:%2X:%2X:%2X:%2X:%2X", mac->mac[0], mac->mac[1],
2607 mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]);
2608 return macstr;
2609} 1405}
2610 1406
1407
2611/** 1408/**
2612 * Function for the scheduler if a mac endpoint times out 1409 * Another peer has suggested an address for this
2613 * @param cls pointer to the MacEndpoint 1410 * peer and transport plugin. Check that this could be a valid
2614 * @param tc pointer to the GNUNET_SCHEDULER_TaskContext 1411 * address. If so, consider adding it to the list
1412 * of addresses.
1413 *
1414 * @param cls closure
1415 * @param addr pointer to the address
1416 * @param addrlen length of addr
1417 * @return GNUNET_OK if this is a plausible address for this peer
1418 * and transport
2615 */ 1419 */
2616static void 1420static int
2617macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1421wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
2618{ 1422{
2619 struct MacEndpoint *endpoint = cls; 1423 struct Plugin *plugin = cls;
2620 1424
2621 GNUNET_assert (endpoint != NULL); 1425 if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
2622 endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK; 1426 {
2623 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) 1427 GNUNET_break_op (0);
2624 { 1428 return GNUNET_SYSERR;
2625 return;
2626 } 1429 }
2627 if (GNUNET_TIME_absolute_get_remaining 1430 if (GNUNET_YES != plugin->have_mac)
2628 (GNUNET_TIME_absolute_add
2629 (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
2630 { 1431 {
2631 GNUNET_assert (endpoint->plugin != NULL); 1432 LOG (GNUNET_ERROR_TYPE_DEBUG,
2632 GNUNET_STATISTICS_update (endpoint->plugin->env->stats, 1433 "Rejecting MAC `%s': I don't know my MAC!\n",
2633 _("# wlan mac endpoints timeouts"), 1, GNUNET_NO); 1434 mac_to_string (addr));
2634 free_macendpoint (endpoint->plugin, endpoint); 1435 return GNUNET_NO; /* don't know my MAC */
2635 } 1436 }
2636 else 1437 if (0 != memcmp (addr,
1438 &plugin->mac_address,
1439 addrlen))
2637 { 1440 {
2638 endpoint->timeout_task = 1441 LOG (GNUNET_ERROR_TYPE_DEBUG,
2639 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout, 1442 "Rejecting MAC `%s': not my MAC!\n",
2640 endpoint); 1443 mac_to_string (addr));
1444 return GNUNET_NO; /* not my MAC */
2641 } 1445 }
1446 return GNUNET_OK;
2642} 1447}
2643 1448
1449
2644/** 1450/**
2645 * function to create an macendpoint 1451 * Function called for a quick conversion of the binary address to
2646 * @param plugin pointer to the plugin struct 1452 * a numeric address. Note that the caller must not free the
2647 * @param addr pointer to the macaddress 1453 * address and that the next call to this function is allowed
2648 * @return returns a macendpoint 1454 * to override the address again.
1455 *
1456 * @param cls closure
1457 * @param addr binary address
1458 * @param addrlen length of the address
1459 * @return string representing the same address
2649 */ 1460 */
2650static struct MacEndpoint * 1461static const char *
2651create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr) 1462wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
2652{ 1463{
2653 struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint)); 1464 static char ret[40];
2654 1465 const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
2655 GNUNET_assert (plugin != NULL);
2656 GNUNET_STATISTICS_update (plugin->env->stats,
2657 _("# wlan mac endpoints created"), 1, GNUNET_NO);
2658 newend->addr = *addr;
2659 newend->plugin = plugin;
2660 newend->addr = *addr;
2661 newend->fragment_messages_out_count = 0;
2662 newend->defrag =
2663 GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
2664 MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
2665 newend, &wlan_data_message_handler,
2666 &add_ack_for_send);
2667 newend->last_activity = GNUNET_TIME_absolute_get ();
2668 newend->timeout_task =
2669 GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
2670 newend);
2671 1466
2672 plugin->mac_count++; 1467 if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != addrlen)
2673 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"), 1468 {
2674 plugin->mac_count, GNUNET_NO); 1469 GNUNET_break (0);
2675 GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend); 1470 return NULL;
2676 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1471 }
2677 "New Mac Endpoint %p: %s\n", newend, 1472 mac = addr;
2678 wlan_plugin_address_to_string (NULL, newend->addr.mac, 6)); 1473 GNUNET_snprintf (ret, sizeof (ret), "%s MAC address %s",
2679 return newend; 1474 PROTOCOL_PREFIX,
1475 mac_to_string (mac));
1476 return ret;
2680} 1477}
2681 1478
1479
2682/** 1480/**
2683 * Function used for to process the data from the suid process 1481 * Convert the transports address to a nice, human-readable format.
2684 * 1482 *
2685 * @param cls the plugin handle 1483 * @param cls closure
2686 * @param client client that send the data (not used) 1484 * @param type name of the transport that generated the address
2687 * @param hdr header of the GNUNET_MessageHeader 1485 * @param addr one of the addresses of the host, NULL for the last address
1486 * the specific address format depends on the transport
1487 * @param addrlen length of the address
1488 * @param numeric should (IP) addresses be displayed in numeric form?
1489 * @param timeout after how long should we give up?
1490 * @param asc function to call on each string
1491 * @param asc_cls closure for asc
2688 */ 1492 */
2689static void 1493static void
2690wlan_process_helper (void *cls, void *client, 1494wlan_plugin_address_pretty_printer (void *cls, const char *type,
2691 const struct GNUNET_MessageHeader *hdr) 1495 const void *addr, size_t addrlen,
1496 int numeric,
1497 struct GNUNET_TIME_Relative timeout,
1498 GNUNET_TRANSPORT_AddressStringCallback asc,
1499 void *asc_cls)
2692{ 1500{
2693 struct Plugin *plugin = cls; 1501 const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
2694 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo; 1502 char *ret;
2695 const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
2696 const struct GNUNET_MessageHeader *temp_hdr = NULL;
2697 const char *end;
2698 int datasize = 0;
2699 int pos;
2700 1503
2701 GNUNET_assert (plugin != NULL); 1504 if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != addrlen)
2702 switch (ntohs (hdr->type))
2703 { 1505 {
2704 case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER: 1506 /* invalid address */
2705 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1507 LOG (GNUNET_ERROR_TYPE_WARNING,
2706 "Got data message from helper with %u bytes\n", 1508 _("WLAN address with invalid size encountered\n"));
2707 ntohs (hdr->size)); 1509 asc (asc_cls, NULL);
2708 GNUNET_STATISTICS_update (plugin->env->stats,
2709 _("# wlan data messages received"), 1,
2710 GNUNET_NO);
2711 //call wlan_process_helper with the message inside, later with wlan: analyze signal
2712 if (ntohs (hdr->size) < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
2713 {
2714 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2715 "Size of packet is too small; size: %u\n",
2716 ntohs (hdr->size));
2717 GNUNET_break (0);
2718 /* FIXME: restart SUID process */
2719 return;
2720 }
2721
2722 rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
2723 //process only if it is an broadcast or for this computer both with the gnunet bssid
2724 //check for bssid
2725 if (memcmp
2726 (&rxinfo->frame.addr3, &mac_bssid_gnunet,
2727 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
2728 {
2729 //check for broadcast or mac
2730 if ((memcmp
2731 (&rxinfo->frame.addr1, &bc_all_mac,
2732 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0) ||
2733 (memcmp
2734 (&rxinfo->frame.addr1, &plugin->mac_address,
2735 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
2736 {
2737 //if packet is from us return
2738 if ((memcmp
2739 (&rxinfo->frame.addr2, &plugin->mac_address,
2740 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
2741 {
2742 /* not for us */
2743 return;
2744 }
2745 datasize = ntohs (hdr->size) - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage);
2746 GNUNET_STATISTICS_update (plugin->env->stats,
2747 _("# wlan messages for this client received"),
2748 1, GNUNET_NO);
2749 // FIXME: this is a job for SERVER_mst --
2750 // what we are doing here is not good for alignment...
2751 pos = 0;
2752 end = (const char*) &rxinfo[1];
2753 while (pos < datasize - sizeof (struct GNUNET_MessageHeader))
2754 {
2755 temp_hdr = (struct GNUNET_MessageHeader *) &end[pos];
2756 if (ntohs (temp_hdr->size) <= datasize - pos)
2757 {
2758 GNUNET_STATISTICS_update (plugin->env->stats,
2759 _
2760 ("# wlan messages inside WLAN_HELPER_DATA received"),
2761 1, GNUNET_NO);
2762 wlan_data_helper (plugin, temp_hdr, rxinfo);
2763 }
2764 else
2765 {
2766 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2767 "Size of packet is too small; size: %u > size of packet: %u\n",
2768 ntohs (temp_hdr->size), datasize - pos);
2769 }
2770 pos += ntohs (temp_hdr->size);
2771 }
2772 }
2773 else
2774 {
2775 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2776 "Func wlan_process_helper got wrong MAC: %s\n",
2777 macprinter (&rxinfo->frame.addr1));
2778 }
2779 }
2780 else
2781 {
2782 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2783 "Func wlan_process_helper got wrong BSSID: %s\n",
2784 macprinter (&rxinfo->frame.addr2));
2785 }
2786 break;
2787 case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2788 //TODO more control messages
2789 if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
2790 {
2791 GNUNET_break (0);
2792 /* FIXME: restart SUID process */
2793 return;
2794 }
2795 cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
2796 plugin->mac_address = cm->mac;
2797 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2798 "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2799 wlan_plugin_address_to_string (cls, &plugin->mac_address,
2800 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)));
2801 plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
2802 &plugin->mac_address,
2803 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
2804 break;
2805 default:
2806 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2807 "Func wlan_process_helper got unknown message with number %u, size %u\n",
2808 ntohs (hdr->type), ntohs (hdr->size));
2809 GNUNET_break (0);
2810 return; 1510 return;
2811 } 1511 }
1512 mac = addr;
1513 GNUNET_asprintf (&ret,
1514 "%s MAC address %s",
1515 PROTOCOL_PREFIX,
1516 mac_to_string (mac));
1517 asc (asc_cls, ret);
1518 GNUNET_free (ret);
1519 asc (asc_cls, NULL);
2812} 1520}
2813 1521
2814 1522
2815
2816/** 1523/**
2817 * Exit point from the plugin. 1524 * Exit point from the plugin.
1525 *
2818 * @param cls pointer to the api struct 1526 * @param cls pointer to the api struct
2819 */ 1527 */
2820//FIXME cleanup
2821void * 1528void *
2822libgnunet_plugin_transport_wlan_done (void *cls) 1529libgnunet_plugin_transport_wlan_done (void *cls)
2823{ 1530{
@@ -2831,26 +1538,37 @@ libgnunet_plugin_transport_wlan_done (void *cls)
2831 GNUNET_free (api); 1538 GNUNET_free (api);
2832 return NULL; 1539 return NULL;
2833 } 1540 }
2834 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME, 1541 if (GNUNET_SCHEDULER_NO_TASK != plugin->beacon_task)
2835 "libgnunet_plugin_transport_wlan_done started\n"); 1542 {
2836 wlan_transport_stop_wlan_helper (plugin); 1543 GNUNET_SCHEDULER_cancel (plugin->beacon_task);
2837 1544 plugin->beacon_task = GNUNET_SCHEDULER_NO_TASK;
2838 GNUNET_assert (cls != NULL); 1545 }
2839 //free sessions 1546 if (NULL != plugin->suid_helper)
2840 endpoint = plugin->mac_head; 1547 {
2841 while (endpoint != NULL) 1548 GNUNET_HELPER_stop (plugin->suid_helper);
1549 plugin->suid_helper = NULL;
1550 }
1551 endpoint_next = plugin->mac_head;
1552 while (NULL != (endpoint = endpoint_next))
2842 { 1553 {
2843 endpoint_next = endpoint->next; 1554 endpoint_next = endpoint->next;
2844 free_macendpoint (plugin, endpoint); 1555 free_macendpoint (endpoint);
2845 endpoint = endpoint_next; 1556 }
2846 1557 if (NULL != plugin->fragment_data_tokenizer)
1558 {
1559 GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer);
1560 plugin->fragment_data_tokenizer = NULL;
1561 }
1562 if (NULL != plugin->wlan_header_payload_tokenizer)
1563 {
1564 GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer);
1565 plugin->wlan_header_payload_tokenizer = NULL;
1566 }
1567 if (NULL != plugin->helper_payload_tokenizer)
1568 {
1569 GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer);
1570 plugin->helper_payload_tokenizer = NULL;
2847 } 1571 }
2848 if (plugin->suid_tokenizer != NULL)
2849 GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
2850
2851 if (plugin->data_tokenizer != NULL)
2852 GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
2853
2854 GNUNET_free_non_null (plugin->interface); 1572 GNUNET_free_non_null (plugin->interface);
2855 GNUNET_free (plugin); 1573 GNUNET_free (plugin);
2856 GNUNET_free (api); 1574 GNUNET_free (api);
@@ -2870,7 +1588,10 @@ libgnunet_plugin_transport_wlan_init (void *cls)
2870 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; 1588 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2871 struct GNUNET_TRANSPORT_PluginFunctions *api; 1589 struct GNUNET_TRANSPORT_PluginFunctions *api;
2872 struct Plugin *plugin; 1590 struct Plugin *plugin;
1591 char *interface;
1592 unsigned long long testmode;
2873 1593
1594 /* check for 'special' mode */
2874 if (NULL == env->receive) 1595 if (NULL == env->receive)
2875 { 1596 {
2876 /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully 1597 /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
@@ -2883,28 +1604,89 @@ libgnunet_plugin_transport_wlan_init (void *cls)
2883 return api; 1604 return api;
2884 } 1605 }
2885 1606
1607 /* check configuration */
1608 if ( (GNUNET_YES ==
1609 GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE")) &&
1610 ( (GNUNET_SYSERR ==
1611 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
1612 "TESTMODE", &testmode)) ||
1613 (testmode > 2) ) )
1614 {
1615 LOG (GNUNET_ERROR_TYPE_ERROR,
1616 _("Invalid configuration option `%s' in section `%s'\n"),
1617 "TESTMODE",
1618 "transport-wlan");
1619 return NULL;
1620 }
1621 if ( (0 == testmode) &&
1622 (GNUNET_YES != GNUNET_OS_check_helper_binary ("gnunet-helper-transport-wlan")) )
1623 {
1624 LOG (GNUNET_ERROR_TYPE_ERROR,
1625 _("Helper binary `%s' not SUID, cannot run WLAN transport\n"),
1626 "gnunet-helper-transport-wlan");
1627 return NULL;
1628 }
1629 if (GNUNET_YES !=
1630 GNUNET_CONFIGURATION_get_value_string
1631 (env->cfg, "transport-wlan", "INTERFACE",
1632 &interface))
1633 {
1634 LOG (GNUNET_ERROR_TYPE_ERROR,
1635 _("Missing configuration option `%s' in section `%s'\n"),
1636 "INTERFACE",
1637 "transport-wlan");
1638 return NULL;
1639 }
1640
2886 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1641 plugin = GNUNET_malloc (sizeof (struct Plugin));
1642 plugin->interface = interface;
2887 plugin->env = env; 1643 plugin->env = env;
2888 plugin->pendingsessions = 0; 1644 GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN sessions allocated"),
2889 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"), 1645 0, GNUNET_NO);
2890 plugin->pendingsessions, GNUNET_NO); 1646 GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
2891 plugin->mac_count = 0; 1647 0, 0);
2892 GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2893 plugin->mac_count, GNUNET_NO);
2894 plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2895 plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2896 plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2897 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, 1648 GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
2898 GNUNET_BANDWIDTH_value_init (100 * 1024 * 1649 GNUNET_BANDWIDTH_value_init (100 * 1024 *
2899 1024 / 8), 100); 1650 1024 / 8), 100);
2900 1651 plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
2901 plugin->suid_tokenizer = 1652 plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
2902 GNUNET_SERVER_mst_create (&wlan_process_helper, plugin); 1653 plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
2903 1654#if BEACON
2904 plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); 1655 plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon,
2905 1656 plugin);
2906 //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue)); 1657#endif
2907 //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue)); 1658 switch (testmode)
1659 {
1660 case 0: /* normal */
1661 plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan";
1662 plugin->helper_argv[1] = interface;
1663 plugin->helper_argv[2] = NULL;
1664 plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan",
1665 plugin->helper_argv,
1666 &handle_helper_message,
1667 plugin);
1668 break;
1669 case 1: /* testmode, peer 1 */
1670 plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
1671 plugin->helper_argv[1] = (char *) "1";
1672 plugin->helper_argv[2] = NULL;
1673 plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan-dummy",
1674 plugin->helper_argv,
1675 &handle_helper_message,
1676 plugin);
1677 break;
1678 case 2: /* testmode, peer 2 */
1679 plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
1680 plugin->helper_argv[1] = (char *) "2";
1681 plugin->helper_argv[2] = NULL;
1682 plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan-dummy",
1683 plugin->helper_argv,
1684 &handle_helper_message,
1685 plugin);
1686 break;
1687 default:
1688 GNUNET_assert (0);
1689 }
2908 1690
2909 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1691 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2910 api->cls = plugin; 1692 api->cls = plugin;
@@ -2914,38 +1696,8 @@ libgnunet_plugin_transport_wlan_init (void *cls)
2914 api->address_pretty_printer = &wlan_plugin_address_pretty_printer; 1696 api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2915 api->check_address = &wlan_plugin_address_suggested; 1697 api->check_address = &wlan_plugin_address_suggested;
2916 api->address_to_string = &wlan_plugin_address_to_string; 1698 api->address_to_string = &wlan_plugin_address_to_string;
2917
2918 //read config
2919
2920 if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
2921 {
2922 if (GNUNET_SYSERR ==
2923 GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
2924 "TESTMODE", &(plugin->testmode)))
2925 plugin->testmode = 0; //default value
2926 }
2927
2928 if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
2929 {
2930 if (GNUNET_CONFIGURATION_get_value_string
2931 (env->cfg, "transport-wlan", "INTERFACE",
2932 &(plugin->interface)) != GNUNET_YES)
2933 {
2934 libgnunet_plugin_transport_wlan_done (api);
2935 return NULL;
2936 }
2937 }
2938
2939 //start the plugin
2940 wlan_transport_start_wlan_helper (plugin);
2941 set_next_beacon_time (plugin);
2942 set_next_send (plugin);
2943 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2944 "wlan init finished\n");
2945 return api; 1699 return api;
2946} 1700}
2947 1701
2948 1702
2949
2950
2951/* end of plugin_transport_wlan.c */ 1703/* end of plugin_transport_wlan.c */