aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2013-05-07 11:36:16 +0000
committerBart Polot <bart@net.in.tum.de>2013-05-07 11:36:16 +0000
commitb0b173f897b1f2b015667c96f37b8bc383f2c12a (patch)
treeb1e607c702ee0e1f9bdcde1ae5a3cb6c0c6583e4 /src
parentea931ffc94e1f8145c30c98da50cd5ae9dd5147a (diff)
downloadgnunet-b0b173f897b1f2b015667c96f37b8bc383f2c12a.tar.gz
gnunet-b0b173f897b1f2b015667c96f37b8bc383f2c12a.zip
Initial mesh2 api import
Diffstat (limited to 'src')
-rw-r--r--src/mesh/Makefile.am20
-rw-r--r--src/mesh/mesh2_api.c2329
2 files changed, 2347 insertions, 2 deletions
diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am
index 7d9a4daf8..c0733cafd 100644
--- a/src/mesh/Makefile.am
+++ b/src/mesh/Makefile.am
@@ -20,14 +20,19 @@ plugindir = $(libdir)/gnunet
20 20
21AM_CLFAGS = -g 21AM_CLFAGS = -g
22 22
23if HAVE_EXPERIMENTAL
24 EXP_LIB = libgnunetmesh2.la
25 EXP_LIBEXEC = gnunet-service-mesh-new
26endif
27
23libexec_PROGRAMS = \ 28libexec_PROGRAMS = \
24 gnunet-service-mesh gnunet-service-mesh-new 29 gnunet-service-mesh $(EXP_LIBEXEC)
25 30
26bin_PROGRAMS = \ 31bin_PROGRAMS = \
27 gnunet-mesh 32 gnunet-mesh
28 33
29lib_LTLIBRARIES = \ 34lib_LTLIBRARIES = \
30 libgnunetmesh.la 35 libgnunetmesh.la $(EXP_LIB)
31 36
32plugin_LTLIBRARIES = \ 37plugin_LTLIBRARIES = \
33 libgnunet_plugin_block_mesh.la 38 libgnunet_plugin_block_mesh.la
@@ -53,6 +58,17 @@ libgnunetmesh_la_LDFLAGS = \
53 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 58 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
54 -version-info 2:1:1 59 -version-info 2:1:1
55 60
61libgnunetmesh2_la_SOURCES = \
62 mesh2_api.c mesh_common.c
63libgnunetmesh2_la_LIBADD = \
64 $(top_builddir)/src/util/libgnunetutil.la \
65 $(XLIB) \
66 $(LTLIBINTL)
67libgnunetmesh2_la_LDFLAGS = \
68 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
69 -version-info 2:2:1
70
71
56gnunet_service_mesh_SOURCES = \ 72gnunet_service_mesh_SOURCES = \
57 gnunet-service-mesh.c \ 73 gnunet-service-mesh.c \
58 mesh_tunnel_tree.c mesh_tunnel_tree.h \ 74 mesh_tunnel_tree.c mesh_tunnel_tree.h \
diff --git a/src/mesh/mesh2_api.c b/src/mesh/mesh2_api.c
new file mode 100644
index 000000000..c847bc419
--- /dev/null
+++ b/src/mesh/mesh2_api.c
@@ -0,0 +1,2329 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4 GNUnet is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; either version 3, or (at your
7 option) any later version.
8 GNUnet is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with GNUnet; see the file COPYING. If not, write to the
14 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15 Boston, MA 02111-1307, USA.
16*/
17
18/**
19 * @file mesh/mesh2_api.c
20 * @brief mesh2 api: client implementation of new mesh service
21 * @author Bartlomiej Polot
22 *
23 * STRUCTURE:
24 * - DATA STRUCTURES
25 * - DECLARATIONS
26 * - AUXILIARY FUNCTIONS
27 * - RECEIVE HANDLERS
28 * - SEND FUNCTIONS
29 * - API CALL DEFINITIONS
30 *
31 * TODO: add regex to reconnect
32 */
33#include "platform.h"
34#include "gnunet_common.h"
35#include "gnunet_client_lib.h"
36#include "gnunet_util_lib.h"
37#include "gnunet_peer_lib.h"
38#include "gnunet_mesh2_service.h"
39#include "mesh.h"
40#include "mesh_protocol.h"
41
42#define LOG(kind,...) GNUNET_log_from (kind, "mesh2-api",__VA_ARGS__)
43
44#define DEBUG_ACK GNUNET_YES
45
46/******************************************************************************/
47/************************ DATA STRUCTURES ****************************/
48/******************************************************************************/
49
50/**
51 * Transmission queue to the service
52 */
53struct GNUNET_MESH_TransmitHandle
54{
55
56 /**
57 * Double Linked list
58 */
59 struct GNUNET_MESH_TransmitHandle *next;
60
61 /**
62 * Double Linked list
63 */
64 struct GNUNET_MESH_TransmitHandle *prev;
65
66 /**
67 * Tunnel this message is sent on / for (may be NULL for control messages).
68 */
69 struct GNUNET_MESH_Tunnel *tunnel;
70
71 /**
72 * Callback to obtain the message to transmit, or NULL if we
73 * got the message in 'data'. Notice that messages built
74 * by 'notify' need to be encapsulated with information about
75 * the 'target'.
76 */
77 GNUNET_CONNECTION_TransmitReadyNotify notify;
78
79 /**
80 * Closure for 'notify'
81 */
82 void *notify_cls;
83
84 /**
85 * How long is this message valid. Once the timeout has been
86 * reached, the message must no longer be sent. If this
87 * is a message with a 'notify' callback set, the 'notify'
88 * function should be called with 'buf' NULL and size 0.
89 */
90 struct GNUNET_TIME_Absolute timeout;
91
92 /**
93 * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
94 */
95 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
96
97 /**
98 * Target of the message, 0 for multicast. This field
99 * is only valid if 'notify' is non-NULL.
100 */
101 GNUNET_PEER_Id target;
102
103 /**
104 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
105 */
106 size_t size;
107};
108
109
110/**
111 * Opaque handle to the service.
112 */
113struct GNUNET_MESH_Handle
114{
115
116 /**
117 * Handle to the server connection, to send messages later
118 */
119 struct GNUNET_CLIENT_Connection *client;
120
121 /**
122 * Set of handlers used for processing incoming messages in the tunnels
123 */
124 const struct GNUNET_MESH_MessageHandler *message_handlers;
125
126 /**
127 * Double linked list of the tunnels this client is connected to, head.
128 */
129 struct GNUNET_MESH_Tunnel *tunnels_head;
130
131 /**
132 * Double linked list of the tunnels this client is connected to, tail.
133 */
134 struct GNUNET_MESH_Tunnel *tunnels_tail;
135
136 /**
137 * Callback for inbound tunnel creation
138 */
139 GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
140
141 /**
142 * Callback for inbound tunnel disconnection
143 */
144 GNUNET_MESH_TunnelEndHandler *cleaner;
145
146 /**
147 * Handle to cancel pending transmissions in case of disconnection
148 */
149 struct GNUNET_CLIENT_TransmitHandle *th;
150
151 /**
152 * Closure for all the handlers given by the client
153 */
154 void *cls;
155
156 /**
157 * Messages to send to the service, head.
158 */
159 struct GNUNET_MESH_TransmitHandle *th_head;
160
161 /**
162 * Messages to send to the service, tail.
163 */
164 struct GNUNET_MESH_TransmitHandle *th_tail;
165
166 /**
167 * tid of the next tunnel to create (to avoid reusing IDs often)
168 */
169 MESH_TunnelNumber next_tid;
170
171 /**
172 * Number of handlers in the handlers array.
173 */
174 unsigned int n_handlers;
175
176 /**
177 * Number of applications in the applications array.
178 */
179 unsigned int n_applications;
180
181 /**
182 * Have we started the task to receive messages from the service
183 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
184 */
185 int in_receive;
186
187 /**
188 * Configuration given by the client, in case of reconnection
189 */
190 const struct GNUNET_CONFIGURATION_Handle *cfg;
191
192 /**
193 * Time to the next reconnect in case one reconnect fails
194 */
195 struct GNUNET_TIME_Relative reconnect_time;
196
197 /**
198 * Task for trying to reconnect.
199 */
200 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
201
202 /**
203 * Monitor callback
204 */
205 GNUNET_MESH_TunnelsCB tunnels_cb;
206
207 /**
208 * Monitor callback closure.
209 */
210 void *tunnels_cls;
211
212 /**
213 * Tunnel callback.
214 */
215 GNUNET_MESH_TunnelCB tunnel_cb;
216
217 /**
218 * Tunnel callback closure.
219 */
220 void *tunnel_cls;
221
222 /**
223 * All the peer in the tunnel so far.
224 */
225 struct GNUNET_PeerIdentity *peers;
226
227 /**
228 * How many peers we have in this tunnel so far.
229 */
230 unsigned int tunnel_npeers;
231
232#if DEBUG_ACK
233 unsigned int acks_sent;
234 unsigned int acks_recv;
235#endif
236};
237
238
239/**
240 * Description of a peer
241 */
242struct GNUNET_MESH_Peer
243{
244 /**
245 * ID of the peer in short form
246 */
247 GNUNET_PEER_Id id;
248
249 /**
250 * Tunnel this peer belongs to
251 */
252 struct GNUNET_MESH_Tunnel *t;
253
254 /**
255 * Flag indicating whether service has informed about its connection
256 */
257 int connected;
258
259};
260
261
262/**
263 * Opaque handle to a tunnel.
264 */
265struct GNUNET_MESH_Tunnel
266{
267
268 /**
269 * DLL next
270 */
271 struct GNUNET_MESH_Tunnel *next;
272
273 /**
274 * DLL prev
275 */
276 struct GNUNET_MESH_Tunnel *prev;
277
278 /**
279 * Handle to the mesh this tunnel belongs to
280 */
281 struct GNUNET_MESH_Handle *mesh;
282
283 /**
284 * Local ID of the tunnel
285 */
286 MESH_TunnelNumber tid;
287
288 /**
289 * Owner of the tunnel. (1 if the tunnel is a local client).
290 */
291 GNUNET_PEER_Id owner;
292
293 /**
294 * Destination of the tunnel.
295 */
296 GNUNET_PEER_Id destination;
297
298 /**
299 * Next hop for the tunnel.
300 */
301 GNUNET_PEER_Id next_hop;
302
303 /**
304 * Previous hop for the tunnel.
305 */
306 GNUNET_PEER_Id prev_hop;
307
308 /**
309 * Any data the caller wants to put in here
310 */
311 void *ctx;
312
313 /**
314 * Size of packet queued in this tunnel
315 */
316 unsigned int packet_size;
317
318 /**
319 * Number of applications requested this tunnel
320 */
321 unsigned int napps;
322
323 /**
324 * Is the tunnel throttled to the slowest peer?
325 */
326 int speed_min;
327
328 /**
329 * Is the tunnel allowed to buffer?
330 */
331 int buffering;
332
333 /**
334 * Next packet ID to send.
335 */
336 uint32_t next_send_pid;
337
338 /**
339 * Maximum allowed PID to send (ACK recevied).
340 */
341 uint32_t max_send_pid;
342
343 /**
344 * Last pid received from the service.
345 */
346 uint32_t last_recv_pid;
347
348 /**
349 * Which ACK value have we last sent to the service?
350 */
351 uint32_t max_recv_pid;
352};
353
354
355/******************************************************************************/
356/*********************** DECLARATIONS *************************/
357/******************************************************************************/
358
359/**
360 * Function called to send a message to the service.
361 * "buf" will be NULL and "size" zero if the socket was closed for writing in
362 * the meantime.
363 *
364 * @param cls closure, the mesh handle
365 * @param size number of bytes available in buf
366 * @param buf where the callee should write the connect message
367 * @return number of bytes written to buf
368 */
369static size_t
370send_callback (void *cls, size_t size, void *buf);
371
372
373/******************************************************************************/
374/*********************** AUXILIARY FUNCTIONS *************************/
375/******************************************************************************/
376
377/**
378 * Check if transmission is a payload packet.
379 *
380 * @param th Transmission handle.
381 *
382 * @return GNUNET_YES if it is a payload packet,
383 * GNUNET_NO if it is a mesh management packet.
384 */
385static int
386th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
387{
388 return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
389}
390
391
392/**
393 * Check whether there is any message ready in the queue and find the size.
394 *
395 * @param h Mesh handle.
396 *
397 * @return The size of the first ready message in the queue,
398 * 0 if there is none.
399 */
400static size_t
401message_ready_size (struct GNUNET_MESH_Handle *h)
402{
403 struct GNUNET_MESH_TransmitHandle *th;
404 struct GNUNET_MESH_Tunnel *t;
405
406 for (th = h->th_head; NULL != th; th = th->next)
407 {
408 t = th->tunnel;
409 if (GNUNET_NO == th_is_payload (th))
410 {
411 LOG (GNUNET_ERROR_TYPE_DEBUG, " message internal\n");
412 return th->size;
413 }
414 if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
415 {
416 LOG (GNUNET_ERROR_TYPE_DEBUG, " message payload ok (%u <= %u)\n",
417 t->next_send_pid, t->max_send_pid);
418 return th->size;
419 }
420 }
421 return 0;
422}
423
424
425/**
426 * Get the tunnel handler for the tunnel specified by id from the given handle
427 * @param h Mesh handle
428 * @param tid ID of the wanted tunnel
429 * @return handle to the required tunnel or NULL if not found
430 */
431static struct GNUNET_MESH_Tunnel *
432retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
433{
434 struct GNUNET_MESH_Tunnel *t;
435
436 t = h->tunnels_head;
437 while (t != NULL)
438 {
439 if (t->tid == tid)
440 return t;
441 t = t->next;
442 }
443 return NULL;
444}
445
446
447/**
448 * Create a new tunnel and insert it in the tunnel list of the mesh handle
449 * @param h Mesh handle
450 * @param tid desired tid of the tunnel, 0 to assign one automatically
451 * @return handle to the created tunnel
452 */
453static struct GNUNET_MESH_Tunnel *
454create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
455{
456 struct GNUNET_MESH_Tunnel *t;
457
458 t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
459 GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
460 t->mesh = h;
461 if (0 == tid)
462 {
463 t->tid = h->next_tid;
464 while (NULL != retrieve_tunnel (h, h->next_tid))
465 {
466 h->next_tid++;
467 h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
468 h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
469 }
470 }
471 else
472 {
473 t->tid = tid;
474 }
475 t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
476 t->last_recv_pid = (uint32_t) -1;
477 t->buffering = GNUNET_YES;
478 return t;
479}
480
481
482/**
483 * Destroy the specified tunnel.
484 * - Destroys all peers, calling the disconnect callback on each if needed
485 * - Cancels all outgoing traffic for that tunnel, calling respective notifys
486 * - Calls cleaner if tunnel was inbound
487 * - Frees all memory used
488 *
489 * @param t Pointer to the tunnel.
490 * @param call_cleaner Whether to call the cleaner handler.
491 *
492 * @return Handle to the required tunnel or NULL if not found.
493 */
494static void
495destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
496{
497 struct GNUNET_MESH_Handle *h;
498 struct GNUNET_PeerIdentity pi;
499 struct GNUNET_MESH_TransmitHandle *th;
500 struct GNUNET_MESH_TransmitHandle *next;
501 unsigned int i;
502
503 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
504
505 if (NULL == t)
506 {
507 GNUNET_break (0);
508 return;
509 }
510 h = t->mesh;
511
512 /* free all peer's ID */
513 GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
514 GNUNET_PEER_change_rc (t->owner, -1);
515 GNUNET_PEER_change_rc (t->destination, -1);
516 GNUNET_PEER_change_rc (t->next_hop, -1);
517 GNUNET_PEER_change_rc (t->prev_hop, -1);
518
519 /* signal tunnel destruction */
520 if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) )
521 h->cleaner (h->cls, t, t->ctx);
522
523 /* check that clients did not leave messages behind in the queue */
524 for (th = h->th_head; NULL != th; th = next)
525 {
526 next = th->next;
527 if (th->tunnel != t)
528 continue;
529 /* Clients should have aborted their requests already.
530 * Management traffic should be ok, as clients can't cancel that */
531 GNUNET_break (GNUNET_NO == th_is_payload(th));
532 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
533
534 /* clean up request */
535 if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
536 GNUNET_SCHEDULER_cancel (th->timeout_task);
537 GNUNET_free (th);
538 }
539
540 /* if there are no more pending requests with mesh service, cancel active request */
541 /* Note: this should be unnecessary... */
542 if ((0 == message_ready_size (h)) && (NULL != h->th))
543 {
544 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
545 h->th = NULL;
546 }
547
548
549 if (t->npeers > 0)
550 GNUNET_free (t->peers);
551 if (0 != t->owner)
552 GNUNET_PEER_change_rc (t->owner, -1);
553 if (0 != t->napps && t->apps)
554 GNUNET_free (t->apps);
555 GNUNET_free (t);
556 return;
557}
558
559
560/**
561 * Get the peer descriptor for the peer with id from the given tunnel
562 * @param t Tunnel handle
563 * @param id Short form ID of the wanted peer
564 * @return handle to the requested peer or NULL if not found
565 */
566static struct GNUNET_MESH_Peer *
567retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
568{
569 unsigned int i;
570
571 for (i = 0; i < t->npeers; i++)
572 if (t->peers[i]->id == id)
573 return t->peers[i];
574 return NULL;
575}
576
577
578/**
579 * Add a peer into a tunnel
580 * @param t Tunnel handle
581 * @param pi Full ID of the new peer
582 * @return handle to the newly created peer
583 */
584static struct GNUNET_MESH_Peer *
585add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
586 const struct GNUNET_PeerIdentity *pi)
587{
588 struct GNUNET_MESH_Peer *p;
589 GNUNET_PEER_Id id;
590
591 if (0 != t->owner)
592 {
593 GNUNET_break (0);
594 return NULL;
595 }
596 id = GNUNET_PEER_intern (pi);
597
598 p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
599 p->id = id;
600 p->t = t;
601 GNUNET_array_append (t->peers, t->npeers, p);
602 return p;
603}
604
605
606/**
607 * Remove a peer from a tunnel
608 * @param p Peer handle
609 */
610static void
611remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
612{
613 unsigned int i;
614
615 for (i = 0; i < p->t->npeers; i++)
616 {
617 if (p->t->peers[i] == p)
618 break;
619 }
620 if (i == p->t->npeers)
621 {
622 GNUNET_break (0);
623 return;
624 }
625 p->t->peers[i] = p->t->peers[p->t->npeers - 1];
626 GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
627}
628
629
630/**
631 * Notify client that the transmission has timed out
632 *
633 * @param cls closure
634 * @param tc task context
635 */
636static void
637timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
638{
639 struct GNUNET_MESH_TransmitHandle *th = cls;
640 struct GNUNET_MESH_Handle *mesh;
641
642 mesh = th->tunnel->mesh;
643 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
644 th->tunnel->packet_size = 0;
645 if (GNUNET_YES == th_is_payload (th))
646 th->notify (th->notify_cls, 0, NULL);
647 GNUNET_free (th);
648 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
649 {
650 /* nothing ready to transmit, no point in asking for transmission */
651 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
652 mesh->th = NULL;
653 }
654}
655
656
657/**
658 * Add a transmit handle to the transmission queue and set the
659 * timeout if needed.
660 *
661 * @param h mesh handle with the queue head and tail
662 * @param th handle to the packet to be transmitted
663 */
664static void
665add_to_queue (struct GNUNET_MESH_Handle *h,
666 struct GNUNET_MESH_TransmitHandle *th)
667{
668 GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
669 if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
670 return;
671 th->timeout_task =
672 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
673 (th->timeout), &timeout_transmission, th);
674}
675
676
677/**
678 * Auxiliary function to send an already constructed packet to the service.
679 * Takes care of creating a new queue element, copying the message and
680 * calling the tmt_rdy function if necessary.
681 *
682 * @param h mesh handle
683 * @param msg message to transmit
684 * @param tunnel tunnel this send is related to (NULL if N/A)
685 */
686static void
687send_packet (struct GNUNET_MESH_Handle *h,
688 const struct GNUNET_MessageHeader *msg,
689 struct GNUNET_MESH_Tunnel *tunnel);
690
691
692/**
693 * Send an ack on the tunnel to confirm the processing of a message.
694 *
695 * @param h Mesh handle.
696 * @param t Tunnel on which to send the ACK.
697 */
698static void
699send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
700{
701 struct GNUNET_MESH_LocalAck msg;
702 uint32_t delta;
703
704 delta = t->max_recv_pid - t->last_recv_pid;
705 if (delta > ACK_THRESHOLD)
706 {
707 LOG (GNUNET_ERROR_TYPE_DEBUG,
708 "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
709 t->tid, t->max_recv_pid, t->last_recv_pid, delta);
710 return;
711 }
712 if (GNUNET_YES == t->buffering)
713 t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
714 else
715 t->max_recv_pid = t->last_recv_pid + 1;
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Sending ACK on tunnel %X: %u\n",
718 t->tid, t->max_recv_pid);
719 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
720 msg.header.size = htons (sizeof (msg));
721 msg.tunnel_id = htonl (t->tid);
722 msg.max_pid = htonl (t->max_recv_pid);
723
724#if DEBUG_ACK
725 t->mesh->acks_sent++;
726#endif
727
728 send_packet (h, &msg.header, t);
729 return;
730}
731
732
733
734/**
735 * Reconnect callback: tries to reconnect again after a failer previous
736 * reconnecttion
737 * @param cls closure (mesh handle)
738 * @param tc task context
739 */
740static void
741reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
742
743
744/**
745 * Send a connect packet to the service with the applications and types
746 * requested by the user.
747 *
748 * @param h The mesh handle.
749 *
750 */
751static void
752send_connect (struct GNUNET_MESH_Handle *h)
753{
754 size_t size;
755
756 size = sizeof (struct GNUNET_MESH_ClientConnect);
757 size += h->n_handlers * sizeof (uint16_t);
758 {
759 char buf[size] GNUNET_ALIGN;
760 struct GNUNET_MESH_ClientConnect *msg;
761 uint16_t napps;
762 uint16_t *types;
763 uint16_t ntypes;
764
765 /* build connection packet */
766 msg = (struct GNUNET_MESH_ClientConnect *) buf;
767 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
768 msg->header.size = htons (size);
769 types = (uint16_t *) & apps[napps];
770 for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
771 {
772 types[ntypes] = htons (h->message_handlers[ntypes].type);
773 LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
774 h->message_handlers[ntypes].type);
775 }
776 msg->applications = htons (napps);
777 msg->types = htons (ntypes);
778 LOG (GNUNET_ERROR_TYPE_DEBUG,
779 "Sending %lu bytes long message %d types and %d apps\n",
780 ntohs (msg->header.size), ntypes, napps);
781 send_packet (h, &msg->header, NULL);
782 }
783}
784
785
786/**
787 * Reconnect to the service, retransmit all infomation to try to restore the
788 * original state.
789 *
790 * @param h handle to the mesh
791 *
792 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
793 */
794static int
795do_reconnect (struct GNUNET_MESH_Handle *h)
796{
797 struct GNUNET_MESH_Tunnel *t;
798 unsigned int i;
799
800 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
801 LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n");
802 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
803 LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
804 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
805
806 /* disconnect */
807 if (NULL != h->th)
808 {
809 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
810 h->th = NULL;
811 }
812 if (NULL != h->client)
813 {
814 GNUNET_CLIENT_disconnect (h->client);
815 }
816
817 /* connect again */
818 h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
819 if (h->client == NULL)
820 {
821 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
822 &reconnect_cbk, h);
823 h->reconnect_time =
824 GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
825 GNUNET_TIME_relative_multiply
826 (h->reconnect_time, 2));
827 LOG (GNUNET_ERROR_TYPE_DEBUG,
828 "Next retry in %s\n",
829 GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
830 GNUNET_NO));
831 GNUNET_break (0);
832 return GNUNET_NO;
833 }
834 else
835 {
836 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
837 }
838 send_connect (h);
839 /* Rebuild all tunnels */
840 for (t = h->tunnels_head; NULL != t; t = t->next)
841 {
842 struct GNUNET_MESH_TunnelMessage tmsg;
843 struct GNUNET_MESH_PeerControl pmsg;
844
845 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
846 {
847 /* Tunnel was created by service (incoming tunnel) */
848 /* TODO: Notify service of missing tunnel, to request
849 * creator to recreate path (find a path to him via DHT?)
850 */
851 continue;
852 }
853 t->next_send_pid = 0;
854 t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
855 t->last_recv_pid = (uint32_t) -1;
856 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
857 tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
858 tmsg.tunnel_id = htonl (t->tid);
859 send_packet (h, &tmsg.header, t);
860
861 pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
862 pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
863 pmsg.tunnel_id = htonl (t->tid);
864
865 /* Reconnect all peers */
866 /* If the tunnel was "by type", dont connect individual peers */
867 for (i = 0; i < t->npeers && 0 == t->napps; i++)
868 {
869 GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
870 if (NULL != t->disconnect_handler && t->peers[i]->connected)
871 t->disconnect_handler (t->cls, &pmsg.peer);
872 send_packet (t->mesh, &pmsg.header, t);
873 }
874 /* Reconnect all types, if any */
875 for (i = 0; i < t->napps; i++)
876 {
877 struct GNUNET_MESH_ConnectPeerByType msg;
878
879 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
880 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
881 msg.tunnel_id = htonl (t->tid);
882 msg.type = htonl (t->apps[i]);
883 send_packet (t->mesh, &msg.header, t);
884 }
885 if (GNUNET_NO == t->buffering)
886 GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
887 if (GNUNET_YES == t->speed_min)
888 GNUNET_MESH_tunnel_speed_min (t);
889 }
890 return GNUNET_YES;
891}
892
893/**
894 * Reconnect callback: tries to reconnect again after a failer previous
895 * reconnecttion
896 * @param cls closure (mesh handle)
897 * @param tc task context
898 */
899static void
900reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
901{
902 struct GNUNET_MESH_Handle *h = cls;
903
904 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
905 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
906 return;
907 do_reconnect (h);
908}
909
910
911/**
912 * Reconnect to the service, retransmit all infomation to try to restore the
913 * original state.
914 *
915 * @param h handle to the mesh
916 *
917 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
918 */
919static void
920reconnect (struct GNUNET_MESH_Handle *h)
921{
922 LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
923 h->in_receive = GNUNET_NO;
924 if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
925 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
926 &reconnect_cbk, h);
927}
928
929
930/******************************************************************************/
931/*********************** RECEIVE HANDLERS ****************************/
932/******************************************************************************/
933
934/**
935 * Process the new tunnel notification and add it to the tunnels in the handle
936 *
937 * @param h The mesh handle
938 * @param msg A message with the details of the new incoming tunnel
939 */
940static void
941process_tunnel_created (struct GNUNET_MESH_Handle *h,
942 const struct GNUNET_MESH_TunnelNotification *msg)
943{
944 struct GNUNET_MESH_Tunnel *t;
945 MESH_TunnelNumber tid;
946
947 tid = ntohl (msg->tunnel_id);
948 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
949 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
950 {
951 GNUNET_break (0);
952 return;
953 }
954 if (NULL != h->new_tunnel)
955 {
956 struct GNUNET_ATS_Information atsi;
957
958 t = create_tunnel (h, tid);
959 t->owner = GNUNET_PEER_intern (&msg->peer);
960 t->npeers = 1;
961 t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
962 t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
963 t->peers[0]->t = t;
964 t->peers[0]->connected = 1;
965 t->peers[0]->id = t->owner;
966 GNUNET_PEER_change_rc (t->owner, 1);
967 t->mesh = h;
968 t->tid = tid;
969 if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0)
970 t->buffering = GNUNET_NO;
971 else
972 t->buffering = GNUNET_YES;
973 if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
974 t->speed_min = GNUNET_YES;
975 atsi.type = 0;
976 atsi.value = 0;
977 LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t);
978 t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
979 LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
980 }
981 else
982 {
983 struct GNUNET_MESH_TunnelMessage d_msg;
984
985 LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
986
987 d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
988 d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
989 d_msg.tunnel_id = msg->tunnel_id;
990
991 send_packet (h, &d_msg.header, NULL);
992 }
993 return;
994}
995
996
997/**
998 * Process the tunnel destroy notification and free associated resources
999 *
1000 * @param h The mesh handle
1001 * @param msg A message with the details of the tunnel being destroyed
1002 */
1003static void
1004process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1005 const struct GNUNET_MESH_TunnelMessage *msg)
1006{
1007 struct GNUNET_MESH_Tunnel *t;
1008 MESH_TunnelNumber tid;
1009
1010 tid = ntohl (msg->tunnel_id);
1011 t = retrieve_tunnel (h, tid);
1012
1013 if (NULL == t)
1014 {
1015 return;
1016 }
1017 if (0 == t->owner)
1018 {
1019 GNUNET_break (0);
1020 }
1021 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
1022 destroy_tunnel (t, GNUNET_YES);
1023 return;
1024}
1025
1026
1027/**
1028 * Process the new peer event and notify the upper level of it
1029 *
1030 * @param h The mesh handle
1031 * @param msg A message with the details of the peer event
1032 */
1033static void
1034process_peer_event (struct GNUNET_MESH_Handle *h,
1035 const struct GNUNET_MESH_PeerControl *msg)
1036{
1037 struct GNUNET_MESH_Tunnel *t;
1038 struct GNUNET_MESH_Peer *p;
1039 struct GNUNET_ATS_Information atsi;
1040 GNUNET_PEER_Id id;
1041 uint16_t size;
1042
1043 LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
1044 size = ntohs (msg->header.size);
1045 if (size != sizeof (struct GNUNET_MESH_PeerControl))
1046 {
1047 GNUNET_break (0);
1048 return;
1049 }
1050 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1051 if (NULL == t)
1052 {
1053 GNUNET_break (0);
1054 return;
1055 }
1056 id = GNUNET_PEER_search (&msg->peer);
1057 if ((p = retrieve_peer (t, id)) == NULL)
1058 p = add_peer_to_tunnel (t, &msg->peer);
1059 if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
1060 {
1061 LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
1062 if (NULL != t->connect_handler)
1063 {
1064 atsi.type = 0;
1065 atsi.value = 0;
1066 t->connect_handler (t->cls, &msg->peer, &atsi);
1067 }
1068 p->connected = 1;
1069 }
1070 else
1071 {
1072 LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
1073 if (NULL != t->disconnect_handler && p->connected)
1074 {
1075 t->disconnect_handler (t->cls, &msg->peer);
1076 }
1077 remove_peer_from_tunnel (p);
1078 GNUNET_free (p);
1079 }
1080 LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
1081}
1082
1083
1084/**
1085 * Process the incoming data packets
1086 *
1087 * @param h The mesh handle
1088 * @param message A message encapsulating the data
1089 *
1090 * @return GNUNET_YES if everything went fine
1091 * GNUNET_NO if client closed connection (h no longer valid)
1092 */
1093static int
1094process_incoming_data (struct GNUNET_MESH_Handle *h,
1095 const struct GNUNET_MessageHeader *message)
1096{
1097 const struct GNUNET_MessageHeader *payload;
1098 const struct GNUNET_MESH_MessageHandler *handler;
1099 const struct GNUNET_PeerIdentity *peer;
1100 struct GNUNET_MESH_Unicast *ucast;
1101 struct GNUNET_MESH_Multicast *mcast;
1102 struct GNUNET_MESH_ToOrigin *to_orig;
1103 struct GNUNET_MESH_Tunnel *t;
1104 unsigned int i;
1105 uint32_t pid;
1106 uint16_t type;
1107
1108 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
1109 type = ntohs (message->type);
1110 switch (type)
1111 {
1112 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1113 ucast = (struct GNUNET_MESH_Unicast *) message;
1114
1115 t = retrieve_tunnel (h, ntohl (ucast->tid));
1116 payload = (struct GNUNET_MessageHeader *) &ucast[1];
1117 peer = &ucast->oid;
1118 pid = ntohl (ucast->pid);
1119 LOG (GNUNET_ERROR_TYPE_DEBUG, " ucast on tunnel %s [%X]\n",
1120 GNUNET_i2s (peer), ntohl (ucast->tid));
1121 break;
1122 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1123 mcast = (struct GNUNET_MESH_Multicast *) message;
1124 t = retrieve_tunnel (h, ntohl (mcast->tid));
1125 payload = (struct GNUNET_MessageHeader *) &mcast[1];
1126 peer = &mcast->oid;
1127 pid = ntohl (mcast->pid);
1128 LOG (GNUNET_ERROR_TYPE_DEBUG, " mcast on tunnel %s [%X]\n",
1129 GNUNET_i2s (peer), ntohl (mcast->tid));
1130 break;
1131 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1132 to_orig = (struct GNUNET_MESH_ToOrigin *) message;
1133 t = retrieve_tunnel (h, ntohl (to_orig->tid));
1134 payload = (struct GNUNET_MessageHeader *) &to_orig[1];
1135 peer = &to_orig->sender;
1136 pid = ntohl (to_orig->pid);
1137 LOG (GNUNET_ERROR_TYPE_DEBUG, " torig on tunnel %s [%X]\n",
1138 GNUNET_i2s (peer), ntohl (to_orig->tid));
1139 break;
1140 default:
1141 GNUNET_break (0);
1142 return GNUNET_YES;
1143 }
1144 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid);
1145 if (NULL == t)
1146 {
1147 /* Tunnel was ignored/destroyed, probably service didn't get it yet */
1148 LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n");
1149 return GNUNET_YES;
1150 }
1151 if (GNUNET_YES ==
1152 GMC_is_pid_bigger(pid, t->max_recv_pid))
1153 {
1154 GNUNET_break (0);
1155 LOG (GNUNET_ERROR_TYPE_WARNING,
1156 " unauthorized message! (%u, max %u)\n",
1157 pid, t->max_recv_pid);
1158 // FIXME fc what now? accept? reject?
1159 return GNUNET_YES;
1160 }
1161 t->last_recv_pid = pid;
1162 type = ntohs (payload->type);
1163 send_ack (h, t);
1164 for (i = 0; i < h->n_handlers; i++)
1165 {
1166 handler = &h->message_handlers[i];
1167 if (handler->type == type)
1168 {
1169 struct GNUNET_ATS_Information atsi;
1170
1171 atsi.type = 0;
1172 atsi.value = 0;
1173 if (GNUNET_OK !=
1174 handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
1175 {
1176 LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
1177 GNUNET_MESH_disconnect (h);
1178 return GNUNET_NO;
1179 }
1180 else
1181 {
1182 LOG (GNUNET_ERROR_TYPE_DEBUG,
1183 "callback completed successfully\n");
1184 }
1185 }
1186 }
1187 return GNUNET_YES;
1188}
1189
1190
1191/**
1192 * Process a local ACK message, enabling the client to send
1193 * more data to the service.
1194 *
1195 * @param h Mesh handle.
1196 * @param message Message itself.
1197 */
1198static void
1199process_ack (struct GNUNET_MESH_Handle *h,
1200 const struct GNUNET_MessageHeader *message)
1201{
1202 struct GNUNET_MESH_LocalAck *msg;
1203 struct GNUNET_MESH_Tunnel *t;
1204 uint32_t ack;
1205
1206 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
1207 h->acks_recv++;
1208 msg = (struct GNUNET_MESH_LocalAck *) message;
1209
1210 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1211
1212 if (NULL == t)
1213 {
1214 LOG (GNUNET_ERROR_TYPE_WARNING,
1215 "ACK on unknown tunnel %X\n",
1216 ntohl (msg->tunnel_id));
1217 return;
1218 }
1219 ack = ntohl (msg->max_pid);
1220 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack);
1221 if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid))
1222 t->max_send_pid = ack;
1223 else
1224 return;
1225 if (NULL == h->th && 0 < t->packet_size)
1226 {
1227 LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n", t->tid, ack);
1228 h->th =
1229 GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1230 GNUNET_TIME_UNIT_FOREVER_REL,
1231 GNUNET_YES, &send_callback, h);
1232 }
1233}
1234
1235
1236/**
1237 * Process a local reply about info on all tunnels, pass info to the user.
1238 *
1239 * @param h Mesh handle.
1240 * @param message Message itself.
1241 */
1242static void
1243process_get_tunnels (struct GNUNET_MESH_Handle *h,
1244 const struct GNUNET_MessageHeader *message)
1245{
1246 struct GNUNET_MESH_LocalMonitor *msg;
1247 uint32_t npeers;
1248
1249 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1250
1251 if (NULL == h->tunnels_cb)
1252 {
1253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1254 return;
1255 }
1256
1257 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1258 npeers = ntohl (msg->npeers);
1259 if (ntohs (message->size) !=
1260 (sizeof (struct GNUNET_MESH_LocalMonitor) +
1261 npeers * sizeof (struct GNUNET_PeerIdentity)))
1262 {
1263 GNUNET_break_op (0);
1264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1265 "Get tunnels message: size %hu - expected %u (%u peers)\n",
1266 ntohs (message->size),
1267 sizeof (struct GNUNET_MESH_LocalMonitor) +
1268 npeers * sizeof (struct GNUNET_PeerIdentity),
1269 npeers);
1270 return;
1271 }
1272 h->tunnels_cb (h->tunnels_cls,
1273 &msg->owner,
1274 ntohl (msg->tunnel_id),
1275 (struct GNUNET_PeerIdentity *) &msg[1],
1276 npeers);
1277}
1278
1279
1280
1281/**
1282 * Process a local monitor_tunnel reply, pass info to the user.
1283 *
1284 * @param h Mesh handle.
1285 * @param message Message itself.
1286 */
1287static void
1288process_show_tunnel (struct GNUNET_MESH_Handle *h,
1289 const struct GNUNET_MessageHeader *message)
1290{
1291 struct GNUNET_MESH_LocalMonitor *msg;
1292 struct GNUNET_PeerIdentity *new_peers;
1293 uint32_t *new_parents;
1294 size_t esize;
1295 uint32_t npeers;
1296 unsigned int i;
1297
1298 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1299
1300 if (NULL == h->tunnel_cb)
1301 {
1302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1303 return;
1304 }
1305
1306 /* Verify message sanity */
1307 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1308 npeers = ntohl (msg->npeers);
1309 esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1310 esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t));
1311 if (ntohs (message->size) != esize)
1312 {
1313 GNUNET_break_op (0);
1314 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1315 "Show tunnel message: size %hu - expected %u (%u peers)\n",
1316 ntohs (message->size),
1317 esize,
1318 npeers);
1319
1320 h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1321 h->tunnel_cb = NULL;
1322 h->tunnel_cls = NULL;
1323 h->tunnel_npeers = 0;
1324 GNUNET_free_non_null (h->peers);
1325 h->peers = NULL;
1326
1327 return;
1328 }
1329
1330 new_peers = (struct GNUNET_PeerIdentity *) &msg[1];
1331 new_parents = (uint32_t *) &new_peers[npeers];
1332
1333 h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers);
1334 memcpy (&h->peers[h->tunnel_npeers],
1335 new_peers,
1336 npeers * sizeof (struct GNUNET_PeerIdentity));
1337 h->tunnel_npeers += npeers;
1338 for (i = 0; i < npeers; i++)
1339 h->tunnel_cb (h->tunnel_cls,
1340 &new_peers[i],
1341 &h->peers[new_parents[i]]);
1342}
1343
1344
1345/**
1346 * Function to process all messages received from the service
1347 *
1348 * @param cls closure
1349 * @param msg message received, NULL on timeout or fatal error
1350 */
1351static void
1352msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1353{
1354 struct GNUNET_MESH_Handle *h = cls;
1355
1356 if (msg == NULL)
1357 {
1358 LOG (GNUNET_ERROR_TYPE_DEBUG,
1359 "Mesh service disconnected, reconnecting\n", h);
1360 reconnect (h);
1361 return;
1362 }
1363 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1364 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1365 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1366 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1367 switch (ntohs (msg->type))
1368 {
1369 /* Notify of a new incoming tunnel */
1370 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1371 process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1372 break;
1373 /* Notify of a tunnel disconnection */
1374 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1375 process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1376 break;
1377 /* Notify of a new peer or a peer disconnect in the tunnel */
1378 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1379 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1380 process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1381 break;
1382 /* Notify of a new data packet in the tunnel */
1383 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1384 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1385 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1386 if (GNUNET_NO == process_incoming_data (h, msg))
1387 return;
1388 break;
1389 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1390 process_ack (h, msg);
1391 break;
1392 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1393 process_get_tunnels (h, msg);
1394 break;
1395 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1396 process_show_tunnel (h, msg);
1397 break;
1398 default:
1399 /* We shouldn't get any other packages, log and ignore */
1400 LOG (GNUNET_ERROR_TYPE_WARNING,
1401 "unsolicited message form service (type %s)\n",
1402 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1403 }
1404 LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1405 if (GNUNET_YES == h->in_receive)
1406 {
1407 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1408 GNUNET_TIME_UNIT_FOREVER_REL);
1409 }
1410 else
1411 {
1412 LOG (GNUNET_ERROR_TYPE_DEBUG,
1413 "in receive off, not calling CLIENT_receive\n");
1414 }
1415}
1416
1417
1418/******************************************************************************/
1419/************************ SEND FUNCTIONS ****************************/
1420/******************************************************************************/
1421
1422/**
1423 * Function called to send a message to the service.
1424 * "buf" will be NULL and "size" zero if the socket was closed for writing in
1425 * the meantime.
1426 *
1427 * @param cls closure, the mesh handle
1428 * @param size number of bytes available in buf
1429 * @param buf where the callee should write the connect message
1430 * @return number of bytes written to buf
1431 */
1432static size_t
1433send_callback (void *cls, size_t size, void *buf)
1434{
1435 struct GNUNET_MESH_Handle *h = cls;
1436 struct GNUNET_MESH_TransmitHandle *th;
1437 struct GNUNET_MESH_TransmitHandle *next;
1438 struct GNUNET_MESH_Tunnel *t;
1439 char *cbuf = buf;
1440 size_t tsize;
1441 size_t psize;
1442 size_t nsize;
1443
1444 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1445 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
1446 if ((0 == size) || (NULL == buf))
1447 {
1448 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h);
1449 reconnect (h);
1450 h->th = NULL;
1451 return 0;
1452 }
1453 tsize = 0;
1454 next = h->th_head;
1455 nsize = message_ready_size (h);
1456 while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1457 {
1458 t = th->tunnel;
1459 if (GNUNET_YES == th_is_payload (th))
1460 {
1461 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n");
1462 if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
1463 {
1464 /* This tunnel is not ready to transmit yet, try next message */
1465 next = th->next;
1466 continue;
1467 }
1468 t->packet_size = 0;
1469 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1470 {
1471 /* traffic to origin */
1472 struct GNUNET_MESH_ToOrigin to;
1473 struct GNUNET_MessageHeader *mh;
1474
1475 GNUNET_assert (size >= th->size);
1476 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1477 psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1478 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin, type %s\n",
1479 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1480 if (psize > 0)
1481 {
1482 psize += sizeof (to);
1483 GNUNET_assert (size >= psize);
1484 to.header.size = htons (psize);
1485 to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1486 to.tid = htonl (t->tid);
1487 to.pid = htonl (t->next_send_pid);
1488 to.ttl = 0;
1489 memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1490 memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1491 memcpy (cbuf, &to, sizeof (to));
1492 }
1493 }
1494 else if (th->target == 0)
1495 {
1496 /* multicast */
1497 struct GNUNET_MESH_Multicast mc;
1498 struct GNUNET_MessageHeader *mh;
1499
1500 GNUNET_assert (size >= th->size);
1501 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1502 psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1503 LOG (GNUNET_ERROR_TYPE_DEBUG, " multicast, type %s\n",
1504 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1505 if (psize > 0)
1506 {
1507 psize += sizeof (mc);
1508 GNUNET_assert (size >= psize);
1509 mc.header.size = htons (psize);
1510 mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1511 mc.tid = htonl (t->tid);
1512 mc.pid = htonl (t->next_send_pid);
1513 mc.ttl = 0;
1514 memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1515 memcpy (cbuf, &mc, sizeof (mc));
1516 }
1517 }
1518 else
1519 {
1520 /* unicast */
1521 struct GNUNET_MESH_Unicast uc;
1522 struct GNUNET_MessageHeader *mh;
1523
1524 GNUNET_assert (size >= th->size);
1525 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1526 psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1527 LOG (GNUNET_ERROR_TYPE_DEBUG, " unicast, type %s\n",
1528 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1529 if (psize > 0)
1530 {
1531 psize += sizeof (uc);
1532 GNUNET_assert (size >= psize);
1533 uc.header.size = htons (psize);
1534 uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1535 uc.tid = htonl (t->tid);
1536 uc.pid = htonl (t->next_send_pid);
1537 uc.ttl = 0;
1538 memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1539 GNUNET_PEER_resolve (th->target, &uc.destination);
1540 memcpy (cbuf, &uc, sizeof (uc));
1541 }
1542 }
1543 t->next_send_pid++;
1544 }
1545 else
1546 {
1547 struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1548
1549 LOG (GNUNET_ERROR_TYPE_DEBUG, " mesh traffic, type %s\n",
1550 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1551 memcpy (cbuf, &th[1], th->size);
1552 psize = th->size;
1553 }
1554 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1555 GNUNET_SCHEDULER_cancel (th->timeout_task);
1556 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1557 GNUNET_free (th);
1558 next = h->th_head;
1559 nsize = message_ready_size (h);
1560 cbuf += psize;
1561 size -= psize;
1562 tsize += psize;
1563 }
1564 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size: %u\n", tsize);
1565 h->th = NULL;
1566 size = message_ready_size (h);
1567 if (0 != size)
1568 {
1569 LOG (GNUNET_ERROR_TYPE_DEBUG, " next size: %u\n", size);
1570 h->th =
1571 GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1572 GNUNET_TIME_UNIT_FOREVER_REL,
1573 GNUNET_YES, &send_callback, h);
1574 }
1575 else
1576 {
1577 if (NULL != h->th_head)
1578 LOG (GNUNET_ERROR_TYPE_DEBUG, " can't transmit any more\n");
1579 else
1580 LOG (GNUNET_ERROR_TYPE_DEBUG, " nothing left to transmit\n");
1581 }
1582 if (GNUNET_NO == h->in_receive)
1583 {
1584 LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n");
1585 h->in_receive = GNUNET_YES;
1586 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1587 GNUNET_TIME_UNIT_FOREVER_REL);
1588 }
1589 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
1590 return tsize;
1591}
1592
1593
1594/**
1595 * Auxiliary function to send an already constructed packet to the service.
1596 * Takes care of creating a new queue element, copying the message and
1597 * calling the tmt_rdy function if necessary.
1598 *
1599 * @param h mesh handle
1600 * @param msg message to transmit
1601 * @param tunnel tunnel this send is related to (NULL if N/A)
1602 */
1603static void
1604send_packet (struct GNUNET_MESH_Handle *h,
1605 const struct GNUNET_MessageHeader *msg,
1606 struct GNUNET_MESH_Tunnel *tunnel)
1607{
1608 struct GNUNET_MESH_TransmitHandle *th;
1609 size_t msize;
1610
1611 LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1612 GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1613 msize = ntohs (msg->size);
1614 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1615 th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1616 th->size = msize;
1617 th->tunnel = tunnel;
1618 memcpy (&th[1], msg, msize);
1619 add_to_queue (h, th);
1620 LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n");
1621 if (NULL != h->th)
1622 return;
1623 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize);
1624 h->th =
1625 GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1626 GNUNET_TIME_UNIT_FOREVER_REL,
1627 GNUNET_YES, &send_callback, h);
1628}
1629
1630
1631/******************************************************************************/
1632/********************** API CALL DEFINITIONS *************************/
1633/******************************************************************************/
1634
1635/**
1636 * Connect to the mesh service.
1637 *
1638 * @param cfg configuration to use
1639 * @param cls closure for the various callbacks that follow
1640 * (including handlers in the handlers array)
1641 * @param new_tunnel function called when an *inbound* tunnel is created
1642 * @param cleaner function called when an *inbound* tunnel is destroyed by the
1643 * remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1644 * is called on the tunnel
1645 * @param handlers callbacks for messages we care about, NULL-terminated
1646 * note that the mesh is allowed to drop notifications about
1647 * inbound messages if the client does not process them fast
1648 * enough (for this notification type, a bounded queue is used)
1649 * @param stypes list of the applications that this client claims to provide
1650 * @return handle to the mesh service NULL on error
1651 * (in this case, init is never called)
1652 */
1653struct GNUNET_MESH_Handle *
1654GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1655 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1656 GNUNET_MESH_TunnelEndHandler cleaner,
1657 const struct GNUNET_MESH_MessageHandler *handlers,
1658 const GNUNET_MESH_ApplicationType *stypes)
1659{
1660 struct GNUNET_MESH_Handle *h;
1661 size_t size;
1662
1663 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1664 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1665 LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1666 h->cfg = cfg;
1667 h->new_tunnel = new_tunnel;
1668 h->cleaner = cleaner;
1669 h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1670 if (h->client == NULL)
1671 {
1672 GNUNET_break (0);
1673 GNUNET_free (h);
1674 return NULL;
1675 }
1676 h->cls = cls;
1677 h->message_handlers = handlers;
1678 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1679 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1680 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1681
1682 /* count apps */
1683 for (h->n_applications = 0;
1684 stypes && stypes[h->n_applications];
1685 h->n_applications++) ;
1686 if (0 < h->n_applications)
1687 {
1688 size = h->n_applications * sizeof (GNUNET_MESH_ApplicationType *);
1689 h->applications = GNUNET_malloc (size);
1690 memcpy (h->applications, stypes, size);
1691 }
1692 /* count handlers */
1693 for (h->n_handlers = 0;
1694 handlers && handlers[h->n_handlers].type;
1695 h->n_handlers++) ;
1696 send_connect (h);
1697 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1698 return h;
1699}
1700
1701
1702/**
1703 * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1704 * disconnect callbacks will be called on any still connected peers, notifying
1705 * about their disconnection. The registered inbound tunnel cleaner will be
1706 * called should any inbound tunnels still exist.
1707 *
1708 * @param handle connection to mesh to disconnect
1709 */
1710void
1711GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1712{
1713 struct GNUNET_MESH_Tunnel *t;
1714 struct GNUNET_MESH_Tunnel *aux;
1715 struct GNUNET_MESH_TransmitHandle *th;
1716
1717 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1718
1719#if DEBUG_ACK
1720 LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1721 LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1722#endif
1723
1724 t = handle->tunnels_head;
1725 while (NULL != t)
1726 {
1727 aux = t->next;
1728 if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1729 {
1730 GNUNET_break (0);
1731 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1732 }
1733 destroy_tunnel (t, GNUNET_YES);
1734 t = aux;
1735 }
1736 while ( (th = handle->th_head) != NULL)
1737 {
1738 struct GNUNET_MessageHeader *msg;
1739
1740 /* Make sure it is an allowed packet (everything else should have been
1741 * already canceled).
1742 */
1743 GNUNET_break (GNUNET_NO == th_is_payload (th));
1744 msg = (struct GNUNET_MessageHeader *) &th[1];
1745 switch (ntohs(msg->type))
1746 {
1747 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1748 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1749 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1750 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1751 break;
1752 default:
1753 GNUNET_break (0);
1754 LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1755 ntohs(msg->type));
1756 }
1757
1758 GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1759 GNUNET_free (th);
1760 }
1761
1762 if (NULL != handle->th)
1763 {
1764 GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1765 handle->th = NULL;
1766 }
1767 if (NULL != handle->client)
1768 {
1769 GNUNET_CLIENT_disconnect (handle->client);
1770 handle->client = NULL;
1771 }
1772 if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1773 {
1774 GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1775 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1776 }
1777 GNUNET_free_non_null (handle->applications);
1778 GNUNET_free (handle);
1779}
1780
1781
1782/**
1783 * Announce to ther peer the availability of services described by the regex,
1784 * in order to be reachable to other peers via connect_by_string.
1785 *
1786 * Note that the first 8 characters are considered to be part of a prefix,
1787 * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1788 * all matching strings will be stored in the DHT.
1789 *
1790 * @param h Handle to mesh.
1791 * @param regex String with the regular expression describing local services.
1792 * @param compression_characters How many characters can be assigned to one
1793 * edge of the graph. The bigger the variability
1794 * of the data, the smaller this parameter should
1795 * be (down to 1).
1796 * For maximum compression, use strlen (regex)
1797 * or 0 (special value). Use with care!
1798 */
1799void
1800GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1801 const char *regex,
1802 unsigned int compression_characters)
1803{
1804 struct GNUNET_MESH_RegexAnnounce *msg;
1805 size_t payload;
1806 size_t len;
1807 size_t msgsize;
1808 size_t offset;
1809 char buffer[UINT16_MAX];
1810
1811 len = strlen (regex);
1812 payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce);
1813 msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
1814 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1815 msg->compression_characters = htons (compression_characters);
1816 offset = 0;
1817 do
1818 {
1819 msgsize = (len - offset > payload) ? payload : len - offset;
1820 memcpy (&msg[1], &regex[offset], msgsize);
1821 offset += msgsize;
1822 msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce);
1823
1824 msg->header.size = htons (msgsize);
1825 msg->last = htons (offset >= len);
1826
1827 send_packet (h, &msg->header, NULL);
1828 } while (len > offset);
1829}
1830
1831/**
1832 * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1833 * and to broadcast).
1834 *
1835 * @param h mesh handle
1836 * @param tunnel_ctx client's tunnel context to associate with the tunnel
1837 * @param connect_handler function to call when peers are actually connected
1838 * @param disconnect_handler function to call when peers are disconnected
1839 * @param handler_cls closure for connect/disconnect handlers
1840 */
1841struct GNUNET_MESH_Tunnel *
1842GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1843 GNUNET_MESH_PeerConnectHandler connect_handler,
1844 GNUNET_MESH_PeerDisconnectHandler disconnect_handler,
1845 void *handler_cls)
1846{
1847 struct GNUNET_MESH_Tunnel *t;
1848 struct GNUNET_MESH_TunnelMessage msg;
1849
1850 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1851 t = create_tunnel (h, 0);
1852 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t);
1853 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid);
1854 t->connect_handler = connect_handler;
1855 t->disconnect_handler = disconnect_handler;
1856 t->cls = handler_cls;
1857 t->ctx = tunnel_ctx;
1858 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1859 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1860 msg.tunnel_id = htonl (t->tid);
1861 send_packet (h, &msg.header, t);
1862 return t;
1863}
1864
1865
1866/**
1867 * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1868 * be called.
1869 *
1870 * @param tunnel tunnel handle
1871 */
1872void
1873GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1874{
1875 struct GNUNET_MESH_Handle *h;
1876 struct GNUNET_MESH_TunnelMessage msg;
1877 struct GNUNET_MESH_TransmitHandle *th;
1878
1879 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1880 h = tunnel->mesh;
1881
1882 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1883 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1884 msg.tunnel_id = htonl (tunnel->tid);
1885 th = h->th_head;
1886 while (th != NULL)
1887 {
1888 struct GNUNET_MESH_TransmitHandle *aux;
1889 if (th->tunnel == tunnel)
1890 {
1891 aux = th->next;
1892 /* FIXME call the handler? */
1893 if (GNUNET_YES == th_is_payload (th))
1894 th->notify (th->notify_cls, 0, NULL);
1895 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1896 GNUNET_free (th);
1897 th = aux;
1898 }
1899 else
1900 th = th->next;
1901 }
1902
1903 destroy_tunnel (tunnel, GNUNET_NO);
1904 send_packet (h, &msg.header, NULL);
1905}
1906
1907/**
1908 * Request that the tunnel data rate is limited to the speed of the slowest
1909 * receiver.
1910 *
1911 * @param tunnel Tunnel affected.
1912 */
1913void
1914GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1915{
1916 struct GNUNET_MESH_TunnelMessage msg;
1917 struct GNUNET_MESH_Handle *h;
1918
1919 h = tunnel->mesh;
1920 tunnel->speed_min = GNUNET_YES;
1921
1922 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1923 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1924 msg.tunnel_id = htonl (tunnel->tid);
1925
1926 send_packet (h, &msg.header, NULL);
1927}
1928
1929
1930/**
1931 * Request that the tunnel data rate is limited to the speed of the fastest
1932 * receiver. This is the default behavior.
1933 *
1934 * @param tunnel Tunnel affected.
1935 */
1936void
1937GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1938{
1939 struct GNUNET_MESH_TunnelMessage msg;
1940 struct GNUNET_MESH_Handle *h;
1941
1942 h = tunnel->mesh;
1943 tunnel->speed_min = GNUNET_NO;
1944
1945 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1946 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1947 msg.tunnel_id = htonl (tunnel->tid);
1948
1949 send_packet (h, &msg.header, NULL);
1950}
1951
1952/**
1953 * Turn on/off the buffering status of the tunnel.
1954 *
1955 * @param tunnel Tunnel affected.
1956 * @param buffer GNUNET_YES to turn buffering on (default),
1957 * GNUNET_NO otherwise.
1958 */
1959void
1960GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1961{
1962 struct GNUNET_MESH_TunnelMessage msg;
1963 struct GNUNET_MESH_Handle *h;
1964
1965 h = tunnel->mesh;
1966 tunnel->buffering = buffer;
1967 tunnel->max_send_pid = tunnel->next_send_pid;
1968
1969 if (GNUNET_YES == buffer)
1970 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
1971 else
1972 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
1973 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1974 msg.tunnel_id = htonl (tunnel->tid);
1975
1976 send_packet (h, &msg.header, NULL);
1977}
1978
1979
1980/**
1981 * Request that a peer should be added to the tunnel. The existing
1982 * connect handler will be called ONCE with either success or failure.
1983 * This function should NOT be called again with the same peer before the
1984 * connect handler is called.
1985 * FIXME: I think the above documentation is false. I think it should
1986 * read: "The connect handler will be called once the peer was actually
1987 * successfully added to the multicast group. This function should
1988 * not be called twice for the same peer (unless, of course,
1989 * the peer was removed using GNUNET_MESH_peer_Request_connect_del in
1990 * the meantime).
1991 *
1992 * @param tunnel handle to existing tunnel
1993 * @param peer peer to add
1994 */
1995void
1996GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
1997 const struct GNUNET_PeerIdentity *peer)
1998{
1999 struct GNUNET_MESH_PeerControl msg;
2000 GNUNET_PEER_Id peer_id;
2001 unsigned int i;
2002
2003 peer_id = GNUNET_PEER_intern (peer);
2004 for (i = 0; i < tunnel->npeers; i++)
2005 {
2006 if (tunnel->peers[i]->id == peer_id)
2007 {
2008 /* Peer already exists in tunnel */
2009 GNUNET_PEER_change_rc (peer_id, -1);
2010 GNUNET_break (0);
2011 return;
2012 }
2013 }
2014 if (NULL == add_peer_to_tunnel (tunnel, peer))
2015 return;
2016
2017 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2018 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2019 msg.tunnel_id = htonl (tunnel->tid);
2020 msg.peer = *peer;
2021 send_packet (tunnel->mesh, &msg.header, tunnel);
2022}
2023
2024
2025/**
2026 * Request that a peer should be removed from the tunnel. The existing
2027 * disconnect handler will be called ONCE if we were connected.
2028 *
2029 * @param tunnel handle to existing tunnel
2030 * @param peer peer to remove
2031 */
2032void
2033GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
2034 const struct GNUNET_PeerIdentity *peer)
2035{
2036 struct GNUNET_MESH_PeerControl msg;
2037 GNUNET_PEER_Id peer_id;
2038 unsigned int i;
2039
2040 peer_id = GNUNET_PEER_search (peer);
2041 if (0 == peer_id)
2042 {
2043 GNUNET_break (0);
2044 return;
2045 }
2046 for (i = 0; i < tunnel->npeers; i++)
2047 if (tunnel->peers[i]->id == peer_id)
2048 break;
2049 if (i == tunnel->npeers)
2050 {
2051 GNUNET_break (0);
2052 return;
2053 }
2054 if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
2055 tunnel->disconnect_handler (tunnel->cls, peer);
2056 GNUNET_PEER_change_rc (peer_id, -1);
2057 GNUNET_free (tunnel->peers[i]);
2058 tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
2059 GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
2060
2061 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2062 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2063 msg.tunnel_id = htonl (tunnel->tid);
2064 memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2065 send_packet (tunnel->mesh, &msg.header, tunnel);
2066}
2067
2068/**
2069 * Request that the mesh should try to connect to a peer matching the
2070 * description given in the service string.
2071 *
2072 * FIXME: allow multiple? how to deal with reconnect?
2073 *
2074 * @param tunnel handle to existing tunnel
2075 * @param description string describing the destination node requirements
2076 */
2077void
2078GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
2079 const char *description)
2080{
2081 struct GNUNET_MESH_ConnectPeerByString *m;
2082 size_t len;
2083 size_t msgsize;
2084
2085 len = strlen (description);
2086 msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
2087 GNUNET_assert (UINT16_MAX > msgsize);
2088 {
2089 char buffer[msgsize];
2090
2091 m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
2092 m->header.size = htons (msgsize);
2093 m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
2094 m->tunnel_id = htonl (tunnel->tid);
2095 memcpy(&m[1], description, len);
2096
2097 send_packet (tunnel->mesh, &m->header, tunnel);
2098 }
2099}
2100
2101
2102/**
2103 * Request that the given peer isn't added to this tunnel in calls to
2104 * connect_by_* calls, (due to misbehaviour, bad performance, ...).
2105 *
2106 * @param tunnel handle to existing tunnel.
2107 * @param peer peer identity of the peer which should be blacklisted
2108 * for the tunnel.
2109 */
2110void
2111GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
2112 const struct GNUNET_PeerIdentity *peer)
2113{
2114 struct GNUNET_MESH_PeerControl msg;
2115
2116 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2117 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
2118 msg.tunnel_id = htonl (tunnel->tid);
2119 msg.peer = *peer;
2120 send_packet (tunnel->mesh, &msg.header, tunnel);
2121
2122 return;
2123}
2124
2125
2126/**
2127 * Request that the given peer isn't blacklisted anymore from this tunnel,
2128 * and therefore can be added in future calls to connect_by_*.
2129 * The peer must have been previously blacklisted for this tunnel.
2130 *
2131 * @param tunnel handle to existing tunnel.
2132 * @param peer peer identity of the peer which shouldn't be blacklisted
2133 * for the tunnel anymore.
2134 */
2135void
2136GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
2137 const struct GNUNET_PeerIdentity *peer)
2138{
2139 struct GNUNET_MESH_PeerControl msg;
2140
2141 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2142 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
2143 msg.tunnel_id = htonl (tunnel->tid);
2144 msg.peer = *peer;
2145 send_packet (tunnel->mesh, &msg.header, tunnel);
2146
2147 return;
2148}
2149
2150
2151struct GNUNET_MESH_TransmitHandle *
2152GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2153 struct GNUNET_TIME_Relative maxdelay,
2154 size_t notify_size,
2155 GNUNET_CONNECTION_TransmitReadyNotify notify,
2156 void *notify_cls)
2157{
2158 struct GNUNET_MESH_TransmitHandle *th;
2159 size_t overhead;
2160
2161 GNUNET_assert (NULL != tunnel);
2162 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
2163 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid);
2164 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2165 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n");
2166 else
2167 LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n");
2168 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size);
2169 GNUNET_assert (NULL != notify);
2170 GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
2171 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
2172 th->tunnel = tunnel;
2173 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
2174 th->target = GNUNET_PEER_intern (target);
2175 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2176 overhead = sizeof (struct GNUNET_MESH_ToOrigin);
2177 else if (NULL == target)
2178 overhead = sizeof (struct GNUNET_MESH_Multicast);
2179 else
2180 overhead = sizeof (struct GNUNET_MESH_Unicast);
2181 tunnel->packet_size = th->size = notify_size + overhead;
2182 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size);
2183 th->notify = notify;
2184 th->notify_cls = notify_cls;
2185 add_to_queue (tunnel->mesh, th);
2186 if (NULL != tunnel->mesh->th)
2187 return th;
2188 if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid))
2189 return th;
2190 LOG (GNUNET_ERROR_TYPE_DEBUG, " call notify tmt rdy\n");
2191 tunnel->mesh->th =
2192 GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
2193 GNUNET_TIME_UNIT_FOREVER_REL,
2194 GNUNET_YES, &send_callback,
2195 tunnel->mesh);
2196 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
2197 return th;
2198}
2199
2200
2201/**
2202 * Cancel the specified transmission-ready notification.
2203 *
2204 * @param th handle that was returned by "notify_transmit_ready".
2205 */
2206void
2207GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2208{
2209 struct GNUNET_MESH_Handle *mesh;
2210
2211 th->tunnel->packet_size = 0;
2212 mesh = th->tunnel->mesh;
2213 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2214 GNUNET_SCHEDULER_cancel (th->timeout_task);
2215 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
2216 GNUNET_free (th);
2217 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
2218 {
2219 /* queue empty, no point in asking for transmission */
2220 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
2221 mesh->th = NULL;
2222 }
2223}
2224
2225
2226/**
2227 * Request information about the running mesh peer.
2228 * The callback will be called for every tunnel known to the service,
2229 * listing all active peers that blong to the tunnel.
2230 *
2231 * If called again on the same handle, it will overwrite the previous
2232 * callback and cls. To retrieve the cls, monitor_cancel must be
2233 * called first.
2234 *
2235 * WARNING: unstable API, likely to change in the future!
2236 *
2237 * @param h Handle to the mesh peer.
2238 * @param callback Function to call with the requested data.
2239 * @param callback_cls Closure for @c callback.
2240 */
2241void
2242GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
2243 GNUNET_MESH_TunnelsCB callback,
2244 void *callback_cls)
2245{
2246 struct GNUNET_MessageHeader msg;
2247
2248 msg.size = htons (sizeof (msg));
2249 msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
2250 send_packet (h, &msg, NULL);
2251 h->tunnels_cb = callback;
2252 h->tunnels_cls = callback_cls;
2253
2254 return;
2255}
2256
2257
2258/**
2259 * Cancel a monitor request. The monitor callback will not be called.
2260 *
2261 * @param h Mesh handle.
2262 *
2263 * @return Closure given to GNUNET_MESH_monitor, if any.
2264 */
2265void *
2266GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
2267{
2268 void *cls;
2269
2270 cls = h->tunnels_cls;
2271 h->tunnels_cb = NULL;
2272 h->tunnels_cls = NULL;
2273 return cls;
2274}
2275
2276
2277/**
2278 * Request information about a specific tunnel of the running mesh peer.
2279 *
2280 * WARNING: unstable API, likely to change in the future!
2281 *
2282 * @param h Handle to the mesh peer.
2283 * @param initiator ID of the owner of the tunnel.
2284 * @param tunnel_number Tunnel number.
2285 * @param callback Function to call with the requested data.
2286 * @param callback_cls Closure for @c callback.
2287 */
2288void
2289GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2290 struct GNUNET_PeerIdentity *initiator,
2291 unsigned int tunnel_number,
2292 GNUNET_MESH_TunnelCB callback,
2293 void *callback_cls)
2294{
2295 struct GNUNET_MESH_LocalMonitor msg;
2296
2297 msg.header.size = htons (sizeof (msg));
2298 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
2299 msg.npeers = htonl (0);
2300 msg.owner = *initiator;
2301 msg.tunnel_id = htonl (tunnel_number);
2302 msg.reserved = 0;
2303 send_packet (h, &msg.header, NULL);
2304 h->tunnel_cb = callback;
2305 h->tunnel_cls = callback_cls;
2306
2307 return;
2308}
2309
2310
2311/**
2312 * Transition API for tunnel ctx management
2313 */
2314void
2315GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
2316{
2317 tunnel->ctx = data;
2318}
2319
2320/**
2321 * Transition API for tunnel ctx management
2322 */
2323void *
2324GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
2325{
2326 return tunnel->ctx;
2327}
2328
2329