send hello to self
[oweals/gnunet.git] / src / mesh / mesh_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/mesh_api.c
23  * @brief mesh service; API for the Mesh. This is used to talk to arbitrary peers
24  *        as of 2011-01Jan-06 this is a mockup.
25  * @author Philipp Tölke
26  */
27 #include <platform.h>
28 #include <gnunet_constants.h>
29 #include <gnunet_mesh_service.h>
30 #include <gnunet_core_service.h>
31 #include <gnunet_container_lib.h>
32
33 struct tunnel_id
34 {
35   uint32_t id GNUNET_PACKED;
36   struct GNUNET_PeerIdentity initiator;
37   struct GNUNET_PeerIdentity target;
38 };
39
40 static uint32_t current_id = 0;
41
42 struct tunnel_message
43 {
44   struct GNUNET_MessageHeader hdr;
45   struct tunnel_id id;
46   /* followed by another GNUNET_MessageHeader */
47 };
48
49 struct notify_cls
50 {
51   void* notify_cls;
52   GNUNET_CONNECTION_TransmitReadyNotify notify;
53   struct GNUNET_MESH_Tunnel *tunnel;
54 };
55
56 struct GNUNET_MESH_Tunnel
57 {
58   /* The other peer this tunnel leads to; just unicast for the moment! */
59   struct GNUNET_PeerIdentity peer;
60
61   struct tunnel_id id;
62
63   /* The handlers and cls for outbound tunnels. Are NULL for inbound tunnels. */
64   GNUNET_MESH_TunnelDisconnectHandler disconnect_handler;
65   GNUNET_MESH_TunnelConnectHandler connect_handler;
66   void *handler_cls;
67
68   struct GNUNET_MESH_Handle* handle;
69
70   /* The message-type requested for this tunnel. Is only needed for pending
71    * by_tupe-tunnels
72    */
73   uint16_t message_type;
74
75   /* The context of the receive-function. */
76   void *ctx;
77 };
78
79 struct tunnel_list_element
80 {
81   struct GNUNET_MESH_Tunnel tunnel;
82   struct tunnel_list_element *next, *prev;
83 };
84
85 struct tunnel_list
86 {
87   struct tunnel_list_element *head, *tail;
88 };
89
90 struct peer_list_element
91 {
92   struct GNUNET_PeerIdentity peer;
93
94   /* how many Message-Types can this peer receive */
95   unsigned int num_types;
96
97   /* array of message-types */
98   GNUNET_MESH_ApplicationType *types;
99
100   struct GNUNET_TRANSPORT_ATS_Information atsi;
101   struct peer_list_element *next, *prev;
102 };
103
104 struct peer_list
105 {
106   struct peer_list_element *head, *tail;
107 };
108
109 struct GNUNET_MESH_Handle
110 {
111   struct GNUNET_CORE_Handle *core;
112   struct GNUNET_MESH_MessageHandler *handlers;
113   struct GNUNET_PeerIdentity myself;
114   unsigned int connected_to_core;
115   struct peer_list connected_peers;
116   struct tunnel_list established_tunnels;
117   struct tunnel_list pending_tunnels;
118   struct tunnel_list pending_by_type_tunnels;
119   void *cls;
120   GNUNET_MESH_TunnelEndHandler *cleaner;
121   size_t hello_message_size;
122   uint16_t *hello_message;
123 };
124
125 static void
126 send_end_connect(void* cls,
127                      const struct GNUNET_SCHEDULER_TaskContext* tc)
128 {
129   struct GNUNET_MESH_Tunnel* tunnel = cls;
130
131   tunnel->connect_handler(tunnel->handler_cls, NULL, NULL);
132 }
133
134 static void
135 send_self_connect(void* cls,
136                         const struct GNUNET_SCHEDULER_TaskContext* tc)
137 {
138   struct GNUNET_MESH_Tunnel* tunnel = cls;
139
140   tunnel->connect_handler(tunnel->handler_cls, &tunnel->handle->myself, NULL);
141   GNUNET_SCHEDULER_add_now(send_end_connect, tunnel);
142 }
143
144 static void
145 core_startup (void *cls,
146               struct GNUNET_CORE_Handle *core,
147               const struct GNUNET_PeerIdentity *my_identity,
148               const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
149 {
150   struct GNUNET_MESH_Handle *handle = cls;
151   memcpy (&handle->myself, my_identity, sizeof (struct GNUNET_PeerIdentity));
152   handle->connected_to_core = GNUNET_YES;
153 }
154
155 static size_t
156 send_hello_message (void *cls, size_t size, void *buf)
157 {
158   struct GNUNET_MESH_Handle *handle = cls;
159   struct GNUNET_MessageHeader *hdr = buf;
160
161   size_t sent = sizeof(struct GNUNET_MessageHeader) + handle->hello_message_size;
162
163   hdr->type = htons(GNUNET_MESSAGE_TYPE_MESH_HELLO);
164   hdr->size = htons(size);
165
166   memcpy(hdr+1, handle->hello_message, handle->hello_message_size);
167   return sent;
168 }
169
170
171 /**
172  * Core calls this if we are connected to a new peer.
173  *
174  * If core tells us that we are connected to ourself, we ignore it. Otherwise, the
175  * peer is added to the connected_peers-list.
176  *
177  */
178 static void
179 core_connect (void *cls,
180               const struct GNUNET_PeerIdentity *peer,
181               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
182 {
183   struct GNUNET_MESH_Handle *handle = cls;
184
185   /* Send a hello to this peer */
186   GNUNET_CORE_notify_transmit_ready(handle->core,
187                                     GNUNET_NO,
188                                     42,
189                                     GNUNET_TIME_UNIT_SECONDS,
190                                     peer,
191                                     sizeof(struct GNUNET_MessageHeader) + handle->hello_message_size,
192                                     &send_hello_message,
193                                     cls);
194
195   /* Check for connect-to-self-message, which we ignore */
196   if (0 ==
197       memcmp (peer, &handle->myself, sizeof (struct GNUNET_PeerIdentity)))
198     return;
199
200
201   /* put the new peer into the list of connected peers */
202   struct peer_list_element *element =
203     GNUNET_malloc (sizeof (struct peer_list_element));
204   memcpy (&element->peer, peer, sizeof (struct GNUNET_PeerIdentity));
205   memcpy (&element->atsi, atsi,
206           sizeof (struct GNUNET_TRANSPORT_ATS_Information));
207
208   GNUNET_CONTAINER_DLL_insert_after (handle->connected_peers.head,
209                                      handle->connected_peers.tail,
210                                      handle->connected_peers.tail, element);
211
212   struct tunnel_list_element *tunnel = handle->pending_tunnels.head;
213   while (tunnel != NULL)
214     {
215       if (0 ==
216           memcmp (&tunnel->tunnel.peer, peer,
217                   sizeof (struct GNUNET_PeerIdentity)))
218         {
219           struct tunnel_list_element *next = tunnel->next;
220           GNUNET_CONTAINER_DLL_remove (handle->pending_tunnels.head,
221                                        handle->pending_tunnels.tail, tunnel);
222           GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
223                                              handle->established_tunnels.tail,
224                                              handle->established_tunnels.tail,
225                                              tunnel);
226           tunnel->tunnel.connect_handler (tunnel->tunnel.handler_cls,
227                                           peer, atsi);
228           GNUNET_SCHEDULER_add_now(send_end_connect, tunnel);
229           tunnel = next;
230         }
231       else
232         tunnel = tunnel->next;
233     }
234 }
235
236 /**
237  * Core calls this if we disconnect a peer
238  *
239  * Remove this peer from the list of connected peers
240  * Close all tunnels this peer belongs to
241  */
242 static void
243 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
244 {
245   struct GNUNET_MESH_Handle *handle = cls;
246
247   struct peer_list_element *element = handle->connected_peers.head;
248   while (element != NULL)
249     {
250       if (0 ==
251           memcmp (&element->peer, peer, sizeof (struct GNUNET_PeerIdentity)))
252         break;
253       element = element->next;
254     }
255   if (element != NULL)
256     {
257       GNUNET_CONTAINER_DLL_remove (handle->connected_peers.head,
258                                    handle->connected_peers.tail, element);
259       GNUNET_free_non_null(element->types);
260       GNUNET_free (element);
261     }
262
263   struct tunnel_list_element *telement = handle->established_tunnels.head;
264   while (telement != NULL)
265     {
266       if (0 ==
267           memcmp (&telement->tunnel.peer, peer,
268                   sizeof (struct GNUNET_PeerIdentity)))
269         {
270           /* disconnect tunnels */
271           /* outbound tunnels */
272           if (telement->tunnel.connect_handler != NULL && NULL != telement->tunnel.disconnect_handler)
273             telement->tunnel.disconnect_handler (telement->tunnel.handler_cls,
274                                                  peer);
275           /* inbound tunnels */
276           else if (NULL != handle->cleaner)
277             handle->cleaner (handle->cls, &telement->tunnel,
278                              &telement->tunnel.ctx);
279
280           struct tunnel_list_element *next = telement->next;
281           GNUNET_CONTAINER_DLL_remove (handle->established_tunnels.head,
282                                        handle->established_tunnels.tail,
283                                        telement);
284           GNUNET_free (telement);
285           telement = next;
286         }
287       else
288         {
289           telement = telement->next;
290         }
291     }
292 }
293
294 /**
295  * Receive a message from core.
296  * This is a hello-message, containing the message-types the other peer can receive
297  */
298 static int
299 receive_hello (void *cls,
300                const struct GNUNET_PeerIdentity *other,
301                const struct GNUNET_MessageHeader *message,
302                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
303 {
304   struct GNUNET_MESH_Handle *handle = cls;
305   uint16_t *num = (uint16_t *) (message + 1);
306   uint16_t *ports = num + 1;
307   unsigned int i;
308
309   struct peer_list_element *element = handle->connected_peers.head;
310   while (element != NULL)
311     {
312       if (0 ==
313           memcmp (&element->peer, other, sizeof (struct GNUNET_PeerIdentity)))
314         break;
315       element = element->next;
316     }
317
318   /* TODO: handle self */
319   /* TODO: add, not replace! */
320   /* TODO: if this changes anything: send new hello */
321   element->num_types = *num;
322   element->types = GNUNET_malloc (*num * sizeof (GNUNET_MESH_ApplicationType));
323
324   for (i = 0; i < *num; i++)
325     element->types[i] = (GNUNET_MESH_ApplicationType)ntohs (ports[i]);
326
327   struct tunnel_list_element *tunnel = handle->pending_by_type_tunnels.head;
328   while (tunnel != NULL)
329     {
330       struct tunnel_list_element *next = tunnel->next;
331       for (i = 0; i < *num; i++)
332         {
333           if (ntohs (ports[i]) == tunnel->tunnel.message_type)
334             {
335               GNUNET_CONTAINER_DLL_remove (handle->pending_tunnels.head,
336                                            handle->pending_tunnels.tail,
337                                            tunnel);
338               GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.
339                                                  head,
340                                                  handle->established_tunnels.
341                                                  tail,
342                                                  handle->established_tunnels.
343                                                  tail, tunnel);
344               tunnel->tunnel.connect_handler (tunnel->tunnel.handler_cls,
345                                               &tunnel->tunnel.peer, atsi);
346               GNUNET_SCHEDULER_add_now (send_end_connect, tunnel);
347               break;
348             }
349         }
350       if (ntohs (ports[i]) == tunnel->tunnel.message_type)
351         tunnel = next;
352       else
353         tunnel = tunnel->next;
354     }
355   return GNUNET_OK;
356 }
357
358 /**
359  * Receive a message from core.
360  */
361 static int
362 core_receive (void *cls,
363               const struct GNUNET_PeerIdentity *other,
364               const struct GNUNET_MessageHeader *message,
365               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
366 {
367   struct GNUNET_MESH_Handle *handle = cls;
368   struct tunnel_message *tmessage = (struct tunnel_message *) message;
369   struct GNUNET_MessageHeader *rmessage =
370     (struct GNUNET_MessageHeader *) (tmessage + 1);
371
372   struct GNUNET_MESH_MessageHandler *handler;
373
374   for (handler = handle->handlers; handler->callback != NULL; handler++)
375     {
376       if ( (ntohs (rmessage->type) == handler->type)
377            && ( (handler->expected_size == 0)
378                 || (handler->expected_size == ntohs (rmessage->size))) )
379         {
380           break;
381         }
382     }
383
384   /* handler->callback handles this message */
385
386   /* If no handler was found, drop the message but keep the channel open */
387   if (handler->callback == NULL)
388     return GNUNET_OK;
389
390   struct tunnel_list_element *tunnel = handle->established_tunnels.head;
391
392   while (tunnel != NULL)
393     {
394       if (tunnel->tunnel.id.id == tmessage->id.id &&
395           (0 ==
396            memcmp (&tmessage->id.initiator, &tunnel->tunnel.id.initiator,
397                    sizeof (struct GNUNET_PeerIdentity)))
398           && (0 ==
399               memcmp (&tmessage->id.target, &tunnel->tunnel.id.target,
400                       sizeof (struct GNUNET_PeerIdentity))))
401         break;
402       tunnel = tunnel->next;
403     }
404
405   /* if no tunnel was found: create a new inbound tunnel */
406   if (tunnel == NULL)
407     {
408       tunnel = GNUNET_malloc (sizeof (struct tunnel_list_element));
409       tunnel->tunnel.connect_handler = NULL;
410       tunnel->tunnel.disconnect_handler = NULL;
411       tunnel->tunnel.handler_cls = NULL;
412       tunnel->tunnel.ctx = NULL;
413       tunnel->tunnel.handle = handle;
414       memcpy (&tunnel->tunnel.peer, other,
415               sizeof (struct GNUNET_PeerIdentity));
416       memcpy (&tunnel->tunnel.id, &tmessage->id, sizeof (struct tunnel_id));
417
418       GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
419                                          handle->established_tunnels.tail,
420                                          handle->established_tunnels.tail,
421                                          tunnel);
422     }
423
424   return handler->callback (handle->cls, &tunnel->tunnel,
425                             &tunnel->tunnel.ctx, other, rmessage, atsi);
426 }
427
428 struct GNUNET_MESH_Tunnel *
429 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Handle *handle,
430                                           struct GNUNET_TIME_Relative timeout,
431                                           GNUNET_MESH_ApplicationType message_type,
432                                           GNUNET_MESH_TunnelConnectHandler
433                                           connect_handler,
434                                           GNUNET_MESH_TunnelDisconnectHandler
435                                           disconnect_handler,
436                                           void *handler_cls)
437 {
438   /* Look in the list of connected peers */
439   struct peer_list_element *element = handle->connected_peers.head;
440   while (element != NULL)
441     {
442       unsigned int i;
443       for (i = 0; i < element->num_types; i++)
444         if (message_type == element->types[i])
445           return GNUNET_MESH_peer_request_connect_all (handle, timeout, 1,
446                                                        &handle->myself,
447                                                        connect_handler,
448                                                        disconnect_handler,
449                                                        handler_cls);
450       element = element->next;
451     }
452
453   /* Put into pending list */
454   struct tunnel_list_element *tunnel =
455     GNUNET_malloc (sizeof (struct tunnel_list_element));
456
457   tunnel->tunnel.connect_handler = connect_handler;
458   tunnel->tunnel.disconnect_handler = disconnect_handler;
459   tunnel->tunnel.handler_cls = handler_cls;
460   tunnel->tunnel.ctx = NULL;
461   tunnel->tunnel.handle = handle;
462   memcpy (&tunnel->tunnel.id.initiator, &handle->myself,
463           sizeof (struct GNUNET_PeerIdentity));
464   tunnel->tunnel.id.id = current_id++;
465   tunnel->tunnel.message_type = message_type;
466
467   GNUNET_CONTAINER_DLL_insert_after (handle->pending_by_type_tunnels.head,
468                                      handle->pending_by_type_tunnels.tail,
469                                      handle->pending_by_type_tunnels.tail,
470                                      tunnel);
471   return &tunnel->tunnel;
472 }
473
474
475
476 struct GNUNET_MESH_Tunnel *
477 GNUNET_MESH_peer_request_connect_all (struct GNUNET_MESH_Handle *handle,
478                                       struct GNUNET_TIME_Relative timeout,
479                                       unsigned int num_peers,
480                                       const struct GNUNET_PeerIdentity *peers,
481                                       GNUNET_MESH_TunnelConnectHandler
482                                       connect_handler,
483                                       GNUNET_MESH_TunnelDisconnectHandler
484                                       disconnect_handler, void *handler_cls)
485 {
486   if (num_peers != 1)
487     return NULL;
488
489   struct tunnel_list_element *tunnel =
490     GNUNET_malloc (sizeof (struct tunnel_list_element));
491
492   tunnel->tunnel.connect_handler = connect_handler;
493   tunnel->tunnel.disconnect_handler = disconnect_handler;
494   tunnel->tunnel.handler_cls = handler_cls;
495   tunnel->tunnel.ctx = NULL;
496   tunnel->tunnel.handle = handle;
497   memcpy (&tunnel->tunnel.id.initiator, &handle->myself,
498           sizeof (struct GNUNET_PeerIdentity));
499   memcpy (&tunnel->tunnel.id.target, peers,
500           sizeof (struct GNUNET_PeerIdentity));
501   tunnel->tunnel.id.id = current_id++;
502   memcpy (&tunnel->tunnel.peer, peers, sizeof(struct GNUNET_PeerIdentity));
503
504   struct peer_list_element *element = handle->connected_peers.head;
505   while (element != NULL)
506     {
507       if (0 ==
508           memcmp (&element->peer, peers, sizeof (struct GNUNET_PeerIdentity)))
509         break;
510       element = element->next;
511     }
512
513   if (element != NULL)
514     {
515       /* we are connected to this peer */
516       GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
517                                          handle->established_tunnels.tail,
518                                          handle->established_tunnels.tail,
519                                          tunnel);
520       connect_handler (handler_cls, &element->peer, &element->atsi);
521     }
522   else if (0 ==
523            memcmp (peers, &handle->myself,
524                    sizeof (struct GNUNET_PeerIdentity)))
525     {
526       /* we are the peer */
527       GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
528                                          handle->established_tunnels.tail,
529                                          handle->established_tunnels.tail,
530                                          tunnel);
531       GNUNET_SCHEDULER_add_now(send_self_connect, tunnel);
532     }
533   else
534     {
535       /* we are not connected to this peer */
536       GNUNET_CONTAINER_DLL_insert_after (handle->pending_tunnels.head,
537                                          handle->pending_tunnels.tail,
538                                          handle->pending_tunnels.tail,
539                                          tunnel);
540       (void) GNUNET_CORE_peer_request_connect (handle->core,
541                                                timeout,
542                                                peers,
543                                                NULL, NULL);                                     
544     }
545
546   return &tunnel->tunnel;
547 }
548
549 const struct GNUNET_PeerIdentity*
550 GNUNET_MESH_get_peer(const struct GNUNET_MESH_Tunnel* tunnel)
551 {
552   return &tunnel->peer;
553 }
554
555 static size_t
556 core_notify(void* cls, size_t size, void* buf)
557 {
558   struct notify_cls *ncls = cls;
559   struct GNUNET_MESH_Tunnel *tunnel = ncls->tunnel;
560   struct tunnel_message* message = buf;
561   void* cbuf = (void*) &message[1];
562   GNUNET_assert(NULL != ncls->notify);
563
564   size_t sent = ncls->notify(ncls->notify_cls, size - sizeof(struct tunnel_message), cbuf);
565
566   GNUNET_free(ncls);
567
568   if (0 == sent) return 0;
569
570   sent += sizeof(struct tunnel_message);
571
572   message->hdr.type = htons(GNUNET_MESSAGE_TYPE_MESH);
573   message->hdr.size = htons(sent);
574   memcpy(&message->id, &tunnel->id, sizeof(struct tunnel_id));
575   return sent;
576 }
577
578
579 /**
580  * Ask the mesh to call "notify" once it is ready to transmit the
581  * given number of bytes to the specified "target".  If we are not yet
582  * connected to the specified peer, a call to this function will cause
583  * us to try to establish a connection.
584  *
585  * @param tunnel tunnel to use for transmission
586  * @param cork is corking allowed for this transmission?
587  * @param priority how important is the message?
588  * @param maxdelay how long can the message wait?
589  * @param target destination for the message, NULL for multicast to all tunnel targets 
590  * @param notify_size how many bytes of buffer space does notify want?
591  * @param notify function to call when buffer space is available;
592  *        will be called with NULL on timeout or if the overall queue
593  *        for this peer is larger than queue_size and this is currently
594  *        the message with the lowest priority
595  * @param notify_cls closure for notify
596  * @return non-NULL if the notify callback was queued,
597  *         NULL if we can not even queue the request (insufficient
598  *         memory); if NULL is returned, "notify" will NOT be called.
599  */
600 struct GNUNET_MESH_TransmitHandle *
601 GNUNET_MESH_notify_transmit_ready (struct
602                                    GNUNET_MESH_Tunnel
603                                    *tunnel,
604                                    int cork,
605                                    uint32_t priority,
606                                    struct
607                                    GNUNET_TIME_Relative
608                                    maxdelay,
609                                    const struct GNUNET_PeerIdentity *target,
610                                    size_t
611                                    notify_size,
612                                    GNUNET_CONNECTION_TransmitReadyNotify
613                                    notify, void *notify_cls)
614 {
615   struct notify_cls *cls = GNUNET_malloc(sizeof(struct notify_cls));
616   cls->notify_cls = notify_cls;
617   GNUNET_assert(NULL != notify);
618   cls->notify = notify;
619   cls->tunnel = tunnel;
620   GNUNET_CORE_notify_transmit_ready(tunnel->handle->core,
621                                     cork,
622                                     priority,
623                                     maxdelay,
624                                     &tunnel->peer,
625                                     notify_size + sizeof(struct tunnel_message),
626                                     &core_notify,
627                                     (void*)cls);
628
629   /* aborting is not implemented yet */
630   return (struct GNUNET_MESH_TransmitHandle*) 1;
631 }
632
633
634 struct GNUNET_MESH_Handle *
635 GNUNET_MESH_connect (const struct
636                      GNUNET_CONFIGURATION_Handle
637                      *cfg, void *cls,
638                      GNUNET_MESH_TunnelEndHandler
639                      cleaner,
640                      const struct GNUNET_MESH_MessageHandler *handlers,
641                      const GNUNET_MESH_ApplicationType *stypes)
642 {
643   struct GNUNET_MESH_Handle *ret =
644     GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
645
646   ret->connected_to_core = GNUNET_NO;
647   ret->connected_peers.head = NULL;
648   ret->connected_peers.tail = NULL;
649   ret->cleaner = cleaner;
650   ret->cls = cls;
651
652   const struct GNUNET_MESH_MessageHandler *it;
653   unsigned int len = 1;
654   for (it = handlers; it->callback != NULL; it++)
655     {
656       len++;
657     }
658
659   ret->handlers =
660     GNUNET_malloc (len * sizeof (struct GNUNET_MESH_MessageHandler));
661   memset(ret->handlers, 0, len * sizeof(struct GNUNET_MESH_MessageHandler));
662   memcpy (ret->handlers, handlers,
663           len * sizeof (struct GNUNET_MESH_MessageHandler));
664
665   /* TODO: build hello */
666
667   const static struct GNUNET_CORE_MessageHandler core_handlers[] = {
668     {&core_receive, GNUNET_MESSAGE_TYPE_MESH, 0},
669     {&receive_hello, GNUNET_MESSAGE_TYPE_MESH_HELLO, 0},
670     {NULL, 0, 0}
671   };
672
673   ret->core = GNUNET_CORE_connect (cfg,
674                                    42,
675                                    ret,
676                                    &core_startup,
677                                    &core_connect,
678                                    &core_disconnect,
679                                    NULL,
680                                    NULL,
681                                    GNUNET_NO, NULL, GNUNET_NO, core_handlers);
682   return ret;
683 }
684
685 void
686 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
687 {
688   GNUNET_free (handle->handlers);
689   GNUNET_CORE_disconnect (handle->core);
690
691   struct peer_list_element *element = handle->connected_peers.head;
692   while (element != NULL)
693     {
694       struct peer_list_element *next = element->next;
695       GNUNET_free (element);
696       element = next;
697     }
698
699   struct tunnel_list_element *tunnel = handle->pending_tunnels.head;
700   while (tunnel != NULL)
701     {
702       struct tunnel_list_element *next = tunnel->next;
703       GNUNET_free (tunnel);
704       tunnel = next;
705     }
706   tunnel = handle->established_tunnels.head;;
707   while (tunnel != NULL)
708     {
709       struct tunnel_list_element *next = tunnel->next;
710       GNUNET_free (tunnel);
711       tunnel = next;
712     }
713
714   GNUNET_free (handle);
715 }
716
717 /* end of mesh_api.c */