aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2011-01-10 21:41:42 +0000
committerPhilipp Tölke <toelke@in.tum.de>2011-01-10 21:41:42 +0000
commit85aebf0bc477953b80f62bd26cd528a8932501a4 (patch)
treedab931f057662abd2ec5c9fa980d2280a68c755a
parent439d18149cd4b6e548a2b6f6510fbbd625dda6b4 (diff)
downloadgnunet-85aebf0bc477953b80f62bd26cd528a8932501a4.tar.gz
gnunet-85aebf0bc477953b80f62bd26cd528a8932501a4.zip
Mockup for the mesh-api
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/include/gnunet_protocols.h6
-rw-r--r--src/mesh/Makefile.am23
-rw-r--r--src/mesh/mesh_api.c493
5 files changed, 525 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 6f6e47ea4..9d82295d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -798,6 +798,7 @@ src/hello/Makefile
798src/include/Makefile 798src/include/Makefile
799src/include/gnunet_directories.h 799src/include/gnunet_directories.h
800src/hostlist/Makefile 800src/hostlist/Makefile
801src/mesh/Makefile
801src/monkey/Makefile 802src/monkey/Makefile
802src/nat/Makefile 803src/nat/Makefile
803src/peerinfo/Makefile 804src/peerinfo/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 8b43dac73..272483108 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,4 +31,5 @@ SUBDIRS = \
31 topology \ 31 topology \
32 fs \ 32 fs \
33 fragmentation \ 33 fragmentation \
34 vpn 34 vpn \
35 mesh
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index afccc0c45..20fea005a 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -732,6 +732,12 @@ extern "C"
732 732
733 733
734/** 734/**
735 * Type of message used to transport messages throug a MESH-tunnel
736 */
737#define GNUNET_MESSAGE_TYPE_MESH 215
738
739
740/**
735 * Type used to match 'all' message types. 741 * Type used to match 'all' message types.
736 */ 742 */
737#define GNUNET_MESSAGE_TYPE_ALL 65535 743#define GNUNET_MESSAGE_TYPE_ALL 65535
diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am
new file mode 100644
index 000000000..b7b248f39
--- /dev/null
+++ b/src/mesh/Makefile.am
@@ -0,0 +1,23 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12
13lib_LTLIBRARIES = \
14 libgnunetmesh.la
15
16libgnunetmesh_la_SOURCES = \
17 mesh_api.c
18libgnunetmesh_la_LIBADD = \
19 $(top_builddir)/src/util/libgnunetutil.la \
20 $(GN_LIBINTL) $(XLIB)
21libgnunetmesh_la_LDFLAGS = \
22 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
23 -version-info 0:0:0
diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c
new file mode 100644
index 000000000..32996e0db
--- /dev/null
+++ b/src/mesh/mesh_api.c
@@ -0,0 +1,493 @@
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
33struct tunnel_id
34{
35 uint32_t id;
36 struct GNUNET_PeerIdentity initiator;
37 struct GNUNET_PeerIdentity target;
38};
39
40static uint32_t current_id = 0;
41
42struct tunnel_message
43{
44 struct GNUNET_MessageHeader hdr;
45 struct tunnel_id id;
46 /* followed by another GNUNET_MessageHeader */
47};
48
49struct GNUNET_MESH_Tunnel
50{
51 /* The other peer this tunnel leads to; just unicast for the moment! */
52 struct GNUNET_PeerIdentity peer;
53
54 struct tunnel_id id;
55
56 void* notify_cls;
57 GNUNET_CONNECTION_TransmitReadyNotify notify;
58
59 /* The handlers and cls for outbound tunnels. Are NULL for inbound tunnels. */
60 GNUNET_MESH_TunnelDisconnectHandler disconnect_handler;
61 GNUNET_MESH_TunnelConnectHandler connect_handler;
62 void *handler_cls;
63
64 struct GNUNET_MESH_Handle* handle;
65
66 /* The context of the receive-function. */
67 void *ctx;
68};
69
70struct tunnel_list_element
71{
72 struct GNUNET_MESH_Tunnel tunnel;
73 struct tunnel_list_element *next, *prev;
74};
75
76struct tunnel_list
77{
78 struct tunnel_list_element *head, *tail;
79};
80
81struct peer_list_element
82{
83 struct GNUNET_PeerIdentity peer;
84 struct GNUNET_TRANSPORT_ATS_Information atsi;
85 struct peer_list_element *next, *prev;
86};
87
88struct peer_list
89{
90 struct peer_list_element *head, *tail;
91};
92
93struct GNUNET_MESH_Handle
94{
95 struct GNUNET_CORE_Handle *core;
96 struct GNUNET_MESH_MessageHandler *handlers;
97 struct GNUNET_PeerIdentity myself;
98 unsigned int connected_to_core;
99 struct peer_list connected_peers;
100 struct tunnel_list established_tunnels;
101 struct tunnel_list pending_tunnels;
102 void *cls;
103 GNUNET_MESH_TunnelEndHandler *cleaner;
104};
105
106static void
107core_startup (void *cls,
108 struct GNUNET_CORE_Handle *core,
109 const struct GNUNET_PeerIdentity *my_identity,
110 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
111{
112 struct GNUNET_MESH_Handle *handle = cls;
113 memcpy (&handle->myself, my_identity, sizeof (struct GNUNET_PeerIdentity));
114 handle->connected_to_core = GNUNET_YES;
115}
116
117/**
118 * Core calls this if we are connected to a new peer.
119 *
120 * If core tells us that we are connected to ourself, we ignore it. Otherwise, the
121 * peer is added to the connected_peers-list.
122 *
123 */
124static void
125core_connect (void *cls,
126 const struct GNUNET_PeerIdentity *peer,
127 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
128{
129 struct GNUNET_MESH_Handle *handle = cls;
130 /* Check for connect-to-self-message, which we ignore */
131 if (0 ==
132 memcmp (peer, &handle->myself, sizeof (struct GNUNET_PeerIdentity)))
133 return;
134
135
136 /* put the new peer into the list of connected peers */
137 struct peer_list_element *element =
138 GNUNET_malloc (sizeof (struct peer_list_element));
139 memcpy (&element->peer, peer, sizeof (struct GNUNET_PeerIdentity));
140 memcpy (&element->atsi, atsi,
141 sizeof (struct GNUNET_TRANSPORT_ATS_Information));
142
143 GNUNET_CONTAINER_DLL_insert_after (handle->connected_peers.head,
144 handle->connected_peers.tail,
145 handle->connected_peers.tail, element);
146
147 struct tunnel_list_element *tunnel = handle->pending_tunnels.head;
148 while (tunnel != NULL)
149 {
150 if (0 ==
151 memcmp (&tunnel->tunnel.peer, peer,
152 sizeof (struct GNUNET_PeerIdentity)))
153 {
154 struct tunnel_list_element *next = tunnel->next;
155 GNUNET_CONTAINER_DLL_remove (handle->pending_tunnels.head,
156 handle->pending_tunnels.tail, tunnel);
157 GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
158 handle->established_tunnels.tail,
159 handle->established_tunnels.tail,
160 tunnel);
161 tunnel->tunnel.connect_handler (tunnel->tunnel.handler_cls,
162 peer, atsi);
163 tunnel = next;
164 }
165 else
166 tunnel = tunnel->next;
167 }
168}
169
170/**
171 * Core calls this if we disconnect a peer
172 *
173 * Remove this peer from the list of connected peers
174 * Close all tunnels this peer belongs to
175 */
176static void
177core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
178{
179 struct GNUNET_MESH_Handle *handle = cls;
180
181 struct peer_list_element *element = handle->connected_peers.head;
182 while (element != NULL)
183 {
184 if (0 ==
185 memcmp (&element->peer, peer, sizeof (struct GNUNET_PeerIdentity)))
186 break;
187 element = element->next;
188 }
189 if (element != NULL)
190 {
191 GNUNET_CONTAINER_DLL_remove (handle->connected_peers.head,
192 handle->connected_peers.tail, element);
193 GNUNET_free (element);
194 }
195
196 struct tunnel_list_element *telement = handle->established_tunnels.head;
197 while (telement != NULL)
198 {
199 if (0 ==
200 memcmp (&telement->tunnel.peer, peer,
201 sizeof (struct GNUNET_PeerIdentity)))
202 {
203 /* disconnect tunnels */
204 /* outbound tunnels */
205 if (telement->tunnel.connect_handler != NULL)
206 telement->tunnel.disconnect_handler (telement->tunnel.handler_cls,
207 peer);
208 /* inbound tunnels */
209 else
210 handle->cleaner (handle->cls, &telement->tunnel,
211 &telement->tunnel.ctx);
212
213 struct tunnel_list_element *next = telement->next;
214 GNUNET_CONTAINER_DLL_remove (handle->established_tunnels.head,
215 handle->established_tunnels.tail,
216 telement);
217 GNUNET_free (telement);
218 telement = next;
219 }
220 else
221 {
222 telement = telement->next;
223 }
224 }
225}
226
227/**
228 * Receive a message from core.
229 */
230static int
231core_receive (void *cls,
232 const struct GNUNET_PeerIdentity *other,
233 const struct GNUNET_MessageHeader *message,
234 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
235{
236 struct GNUNET_MESH_Handle *handle = cls;
237 struct tunnel_message *tmessage = (struct tunnel_message *) message;
238 struct GNUNET_MessageHeader *rmessage =
239 (struct GNUNET_MessageHeader *) (tmessage + 1);
240
241 struct GNUNET_MESH_MessageHandler *handler;
242
243 for (handler = handle->handlers; handler != NULL; handler++)
244 {
245 if (ntohs (rmessage->type) == handler->type
246 && (handler->expected_size == 0
247 || handler->expected_size == ntohs (rmessage->size)))
248 {
249 break;
250 }
251 }
252
253 /* handler->callback handles this message */
254
255 /* If no handler was found, drop the message but keep the channel open */
256 if (handler == NULL)
257 return GNUNET_OK;
258
259 struct tunnel_list_element *tunnel = handle->established_tunnels.head;
260
261 while (tunnel != NULL)
262 {
263 if (tunnel->tunnel.id.id == tmessage->id.id &&
264 (0 ==
265 memcmp (&tmessage->id.initiator, &tunnel->tunnel.id.initiator,
266 sizeof (struct GNUNET_PeerIdentity)))
267 && (0 ==
268 memcmp (&tmessage->id.target, &tunnel->tunnel.id.target,
269 sizeof (struct GNUNET_PeerIdentity))))
270 break;
271 tunnel = tunnel->next;
272 }
273
274 /* if no tunnel was found: create a new inbound tunnel */
275 if (tunnel == NULL)
276 {
277 tunnel = GNUNET_malloc (sizeof (struct tunnel_list_element));
278 tunnel->tunnel.connect_handler = NULL;
279 tunnel->tunnel.disconnect_handler = NULL;
280 tunnel->tunnel.handler_cls = NULL;
281 tunnel->tunnel.ctx = NULL;
282 tunnel->tunnel.handle = handle;
283 memcpy (&tunnel->tunnel.peer, other,
284 sizeof (struct GNUNET_PeerIdentity));
285 memcpy (&tunnel->tunnel.id, &tmessage->id, sizeof (struct tunnel_id));
286
287 GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
288 handle->established_tunnels.tail,
289 handle->established_tunnels.tail,
290 tunnel);
291 }
292
293 return handler->callback (handle->cls, &tunnel->tunnel,
294 &tunnel->tunnel.ctx, rmessage, atsi);
295}
296
297
298struct GNUNET_MESH_Tunnel *
299GNUNET_MESH_peer_request_connect_all (struct GNUNET_MESH_Handle *handle,
300 struct GNUNET_TIME_Relative timeout,
301 unsigned int num_peers,
302 const struct GNUNET_PeerIdentity *peers,
303 GNUNET_MESH_TunnelConnectHandler
304 connect_handler,
305 GNUNET_MESH_TunnelDisconnectHandler
306 disconnect_handler, void *handler_cls)
307{
308 if (num_peers != 1)
309 return NULL;
310
311 struct tunnel_list_element *tunnel =
312 GNUNET_malloc (sizeof (struct tunnel_list_element));
313
314 tunnel->tunnel.connect_handler = connect_handler;
315 tunnel->tunnel.disconnect_handler = disconnect_handler;
316 tunnel->tunnel.handler_cls = handler_cls;
317 tunnel->tunnel.ctx = NULL;
318 tunnel->tunnel.handle = handle;
319 memcpy (&tunnel->tunnel.id.initiator, &handle->myself,
320 sizeof (struct GNUNET_PeerIdentity));
321 memcpy (&tunnel->tunnel.id.target, peers,
322 sizeof (struct GNUNET_PeerIdentity));
323 tunnel->tunnel.id.id = current_id++;
324
325 struct peer_list_element *element = handle->connected_peers.head;
326 while (element != NULL)
327 {
328 if (0 ==
329 memcmp (&element->peer, peers, sizeof (struct GNUNET_PeerIdentity)))
330 break;
331 element = element->next;
332 }
333
334 if (element != NULL)
335 {
336 /* we are connected to this peer */
337 GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
338 handle->established_tunnels.tail,
339 handle->established_tunnels.tail,
340 tunnel);
341 connect_handler (handler_cls, &element->peer, &element->atsi);
342 }
343 else if (0 ==
344 memcmp (peers, &handle->myself,
345 sizeof (struct GNUNET_PeerIdentity)))
346 {
347 /* we are the peer */
348 GNUNET_CONTAINER_DLL_insert_after (handle->established_tunnels.head,
349 handle->established_tunnels.tail,
350 handle->established_tunnels.tail,
351 tunnel);
352 connect_handler (handler_cls, &handle->myself, NULL);
353 }
354 else
355 {
356 /* we are not connected to this peer */
357 GNUNET_CONTAINER_DLL_insert_after (handle->pending_tunnels.head,
358 handle->pending_tunnels.tail,
359 handle->pending_tunnels.tail,
360 tunnel);
361 }
362
363 return &tunnel->tunnel;
364}
365
366static size_t
367core_notify(void* cls, size_t size, void* buf)
368{
369 struct GNUNET_MESH_Tunnel *tunnel = cls;
370 struct tunnel_message* message = buf;
371 void* cbuf = (void*)(message + 1);
372
373 size_t sent = tunnel->notify(tunnel->notify_cls, size - sizeof(struct tunnel_message), cbuf);
374
375 tunnel->notify = NULL;
376 tunnel->notify_cls = NULL;
377
378 sent += sizeof(struct tunnel_message);
379
380 message->hdr.type = htons(GNUNET_MESSAGE_TYPE_MESH);
381 message->hdr.size = htons(sent);
382 memcpy(&message->id, &tunnel->id, sizeof(struct tunnel_id));
383 return sent;
384}
385
386struct GNUNET_MESH_TransmitHandle *
387GNUNET_MESH_notify_transmit_ready (struct
388 GNUNET_MESH_Tunnel
389 *tunnel,
390 int cork,
391 uint32_t priority,
392 struct
393 GNUNET_TIME_Relative
394 maxdelay,
395 size_t
396 notify_size,
397 GNUNET_CONNECTION_TransmitReadyNotify
398 notify, void *notify_cls)
399{
400 tunnel->notify_cls = notify_cls;
401 tunnel->notify = notify;
402 GNUNET_CORE_notify_transmit_ready(tunnel->handle->core,
403 priority,
404 maxdelay,
405 &tunnel->peer,
406 notify_size + sizeof(struct tunnel_message),
407 core_notify,
408 (void*)tunnel);
409
410 /* aborting is not implemented yet */
411 return (struct GNUNET_MESH_TransmitHandle*)1;
412}
413
414
415struct GNUNET_MESH_Handle *
416GNUNET_MESH_connect (const struct
417 GNUNET_CONFIGURATION_Handle
418 *cfg, void *cls,
419 GNUNET_MESH_TunnelEndHandler
420 cleaner,
421 const struct GNUNET_MESH_MessageHandler *handlers)
422{
423 struct GNUNET_MESH_Handle *ret =
424 GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
425
426 ret->connected_to_core = GNUNET_NO;
427 ret->connected_peers.head = NULL;
428 ret->connected_peers.tail = NULL;
429 ret->cleaner = cleaner;
430 ret->cls = cls;
431
432 const struct GNUNET_MESH_MessageHandler *it;
433 unsigned int len = 1;
434 for (it = handlers; it->callback != NULL; it++)
435 {
436 len++;
437 }
438
439 ret->handlers =
440 GNUNET_malloc (len * sizeof (struct GNUNET_MESH_MessageHandler));
441 memcpy (ret->handlers, handlers,
442 len * sizeof (struct GNUNET_MESH_MessageHandler));
443
444 const static struct GNUNET_CORE_MessageHandler core_handlers[] = {
445 {core_receive, GNUNET_MESSAGE_TYPE_MESH, 0},
446 {NULL, 0, 0}
447 };
448
449 ret->core = GNUNET_CORE_connect (cfg,
450 42,
451 ret,
452 core_startup,
453 core_connect,
454 core_disconnect,
455 NULL,
456 NULL,
457 GNUNET_NO, NULL, GNUNET_NO, core_handlers);
458 return ret;
459}
460
461void
462GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
463{
464 GNUNET_free (handle->handlers);
465 GNUNET_CORE_disconnect (handle->core);
466
467 struct peer_list_element *element = handle->connected_peers.head;
468 while (element != NULL)
469 {
470 struct peer_list_element *next = element->next;
471 GNUNET_free (element);
472 element = next;
473 }
474
475 struct tunnel_list_element *tunnel = handle->pending_tunnels.head;
476 while (tunnel != NULL)
477 {
478 struct tunnel_list_element *next = tunnel->next;
479 GNUNET_free (tunnel);
480 tunnel = next;
481 }
482 tunnel = handle->established_tunnels.head;;
483 while (tunnel != NULL)
484 {
485 struct tunnel_list_element *next = tunnel->next;
486 GNUNET_free (tunnel);
487 tunnel = next;
488 }
489
490 GNUNET_free (handle);
491}
492
493/* end of core_api.c */