aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-02-17 14:12:15 +0100
committerChristian Grothoff <christian@grothoff.org>2017-02-17 14:12:15 +0100
commit69d9269f2c5887e73950ee3a7fc0fd5e050a8a86 (patch)
tree003e366551d619b3df9ac61df60270bb926c8db2 /src/cadet
parent9727e5e53721dace7abbcc5bcd28c838af4291cc (diff)
downloadgnunet-69d9269f2c5887e73950ee3a7fc0fd5e050a8a86.tar.gz
gnunet-69d9269f2c5887e73950ee3a7fc0fd5e050a8a86.zip
hacking up 'new' CADET API without legacy logic
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/Makefile.am15
-rw-r--r--src/cadet/cadet_api_new.c1805
2 files changed, 1819 insertions, 1 deletions
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am
index 82fb7351b..9b593b486 100644
--- a/src/cadet/Makefile.am
+++ b/src/cadet/Makefile.am
@@ -30,7 +30,9 @@ bin_PROGRAMS = \
30 gnunet-cadet 30 gnunet-cadet
31 31
32lib_LTLIBRARIES = \ 32lib_LTLIBRARIES = \
33 libgnunetcadet.la $(EXP_LIB) 33 libgnunetcadetnew.la \
34 libgnunetcadet.la \
35 $(EXP_LIB)
34 36
35libgnunetcadet_la_SOURCES = \ 37libgnunetcadet_la_SOURCES = \
36 cadet_api.c cadet_common.c 38 cadet_api.c cadet_common.c
@@ -42,6 +44,17 @@ libgnunetcadet_la_LDFLAGS = \
42 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 44 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
43 -version-info 5:0:0 45 -version-info 5:0:0
44 46
47
48libgnunetcadetnew_la_SOURCES = \
49 cadet_api_new.c
50libgnunetcadetnew_la_LIBADD = \
51 $(top_builddir)/src/util/libgnunetutil.la \
52 $(XLIB) \
53 $(LTLIBINTL)
54libgnunetcadetnew_la_LDFLAGS = \
55 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
56 -version-info 6:0:0
57
45gnunet_cadet_SOURCES = \ 58gnunet_cadet_SOURCES = \
46 gnunet-cadet.c 59 gnunet-cadet.c
47gnunet_cadet_LDADD = \ 60gnunet_cadet_LDADD = \
diff --git a/src/cadet/cadet_api_new.c b/src/cadet/cadet_api_new.c
new file mode 100644
index 000000000..8f482aa28
--- /dev/null
+++ b/src/cadet/cadet_api_new.c
@@ -0,0 +1,1805 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file cadet/cadet_api.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33#define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__)
34
35/**
36 * Ugly legacy hack.
37 */
38union CadetInfoCB
39{
40
41 /**
42 * Channel callback.
43 */
44 GNUNET_CADET_ChannelCB channel_cb;
45
46 /**
47 * Monitor callback
48 */
49 GNUNET_CADET_PeersCB peers_cb;
50
51 /**
52 * Monitor callback
53 */
54 GNUNET_CADET_PeerCB peer_cb;
55
56 /**
57 * Monitor callback
58 */
59 GNUNET_CADET_TunnelsCB tunnels_cb;
60
61 /**
62 * Tunnel callback.
63 */
64 GNUNET_CADET_TunnelCB tunnel_cb;
65};
66
67
68/**
69 * Opaque handle to the service.
70 */
71struct GNUNET_CADET_Handle
72{
73 /**
74 * Message queue.
75 */
76 struct GNUNET_MQ_Handle *mq;
77
78 /**
79 * Ports open.
80 */
81 struct GNUNET_CONTAINER_MultiHashMap *ports;
82
83 /**
84 * Channels open.
85 */
86 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
87
88 /**
89 * child of the next channel to create (to avoid reusing IDs often)
90 */
91 struct GNUNET_CADET_ClientChannelNumber next_ccn;
92
93 /**
94 * Configuration given by the client, in case of reconnection
95 */
96 const struct GNUNET_CONFIGURATION_Handle *cfg;
97
98 /**
99 * Task for trying to reconnect.
100 */
101 struct GNUNET_SCHEDULER_Task *reconnect_task;
102
103 /**
104 * Callback for an info task (only one active at a time).
105 */
106 union CadetInfoCB info_cb;
107
108 /**
109 * Info callback closure for @c info_cb.
110 */
111 void *info_cls;
112
113 /**
114 * Time to the next reconnect in case one reconnect fails
115 */
116 struct GNUNET_TIME_Relative reconnect_time;
117
118};
119
120
121/**
122 * Opaque handle to a channel.
123 */
124struct GNUNET_CADET_Channel
125{
126
127 /**
128 * Other end of the channel.
129 */
130 struct GNUNET_PeerIdentity peer;
131
132 /**
133 * Handle to the cadet this channel belongs to
134 */
135 struct GNUNET_CADET_Handle *cadet;
136
137 /**
138 * Channel's port, if incoming.
139 */
140 struct GNUNET_CADET_Port *incoming_port;
141
142 /**
143 * Any data the caller wants to put in here, used for the
144 * various callbacks (@e disconnects, @e window_changes, handlers).
145 */
146 void *ctx;
147
148 /**
149 * Message Queue for the channel.
150 */
151 struct GNUNET_MQ_Handle *mq;
152
153 /**
154 * Task to allow mq to send more traffic.
155 */
156 struct GNUNET_SCHEDULER_Task *mq_cont;
157
158 /**
159 * Pending envelope in case we don't have an ACK from the service.
160 */
161 struct GNUNET_MQ_Envelope *pending_env;
162
163 /**
164 * Window change handler.
165 */
166 GNUNET_CADET_WindowSizeEventHandler window_changes;
167
168 /**
169 * Disconnect handler.
170 */
171 GNUNET_CADET_DisconnectEventHandler disconnects;
172
173 /**
174 * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
175 */
176 struct GNUNET_CADET_ClientChannelNumber ccn;
177
178 /**
179 * Channel options: reliability, etc.
180 */
181 enum GNUNET_CADET_ChannelOption options;
182
183 /**
184 * Are we allowed to send to the service?
185 */
186 unsigned int allow_send;
187
188};
189
190
191/**
192 * Opaque handle to a port.
193 */
194struct GNUNET_CADET_Port
195{
196 /**
197 * Handle to the CADET session this port belongs to.
198 */
199 struct GNUNET_CADET_Handle *cadet;
200
201 /**
202 * Callback handler for incoming channels on this port.
203 */
204 GNUNET_CADET_InboundChannelNotificationHandler *handler;
205
206 /**
207 * Closure for @a handler.
208 */
209 void *cls;
210
211 /**
212 * Port "number"
213 */
214 struct GNUNET_HashCode id;
215
216 /**
217 * Handler for incoming channels on this port
218 */
219 GNUNET_CADET_ConnectEventHandler connects;
220
221 /**
222 * Closure for @ref connects
223 */
224 void *connects_cls;
225
226 /**
227 * Window size change handler.
228 */
229 GNUNET_CADET_WindowSizeEventHandler window_changes;
230
231 /**
232 * Handler called when an incoming channel is destroyed..
233 */
234 GNUNET_CADET_DisconnectEventHandler disconnects;
235
236 /**
237 * Payload handlers for incoming channels.
238 */
239 struct GNUNET_MQ_MessageHandler *handlers;
240};
241
242
243/**
244 * Find the Port struct for a hash.
245 *
246 * @param h CADET handle.
247 * @param hash HashCode for the port number.
248 * @return The port handle if known, NULL otherwise.
249 */
250static struct GNUNET_CADET_Port *
251find_port (const struct GNUNET_CADET_Handle *h,
252 const struct GNUNET_HashCode *hash)
253{
254 return GNUNET_CONTAINER_multihashmap_get (h->ports,
255 hash);
256}
257
258
259/**
260 * Get the channel handler for the channel specified by id from the given handle
261 *
262 * @param h Cadet handle
263 * @param ccn ID of the wanted channel
264 * @return handle to the required channel or NULL if not found
265 */
266static struct GNUNET_CADET_Channel *
267find_channel (struct GNUNET_CADET_Handle *h,
268 struct GNUNET_CADET_ClientChannelNumber ccn)
269{
270 return GNUNET_CONTAINER_multihashmap32_get (h->channels,
271 ntohl (ccn.channel_of_client));
272}
273
274
275/**
276 * Create a new channel and insert it in the channel list of the cadet handle
277 *
278 * @param h Cadet handle
279 * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically.
280 * @return Handle to the created channel.
281 */
282static struct GNUNET_CADET_Channel *
283create_channel (struct GNUNET_CADET_Handle *h,
284 const struct GNUNET_CADET_ClientChannelNumber *ccnp)
285{
286 struct GNUNET_CADET_Channel *ch;
287 struct GNUNET_CADET_ClientChannelNumber ccn;
288
289 ch = GNUNET_new (struct GNUNET_CADET_Channel);
290 ch->cadet = h;
291 if (NULL == ccnp)
292 {
293 while (NULL !=
294 find_channel (h,
295 h->next_ccn))
296 h->next_ccn.channel_of_client
297 = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | (1 + ntohl (h->next_ccn.channel_of_client)));
298 ccn = h->next_ccn;
299 }
300 else
301 {
302 ccn = *ccnp;
303 }
304 ch->ccn = ccn;
305 GNUNET_assert (GNUNET_OK ==
306 GNUNET_CONTAINER_multihashmap32_put (h->channels,
307 ntohl (ch->ccn.channel_of_client),
308 ch,
309 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
310 return ch;
311}
312
313
314/**
315 * Destroy the specified channel.
316 * - Destroys all peers, calling the disconnect callback on each if needed
317 * - Cancels all outgoing traffic for that channel, calling respective notifys
318 * - Calls cleaner if channel was inbound
319 * - Frees all memory used
320 *
321 * @param ch Pointer to the channel.
322 * @param call_cleaner Whether to call the cleaner handler.
323 */
324static void
325destroy_channel (struct GNUNET_CADET_Channel *ch)
326{
327 struct GNUNET_CADET_Handle *h = ch->cadet;
328
329 LOG (GNUNET_ERROR_TYPE_DEBUG,
330 " destroy_channel %X of %p\n",
331 ch->ccn,
332 h);
333 GNUNET_assert (GNUNET_YES ==
334 GNUNET_CONTAINER_multihashmap32_remove (h->channels,
335 ntohl (ch->ccn.channel_of_client),
336 ch));
337 if (NULL != ch->mq_cont)
338 {
339 GNUNET_SCHEDULER_cancel (ch->mq_cont);
340 ch->mq_cont = NULL;
341 }
342 /* signal channel destruction */
343 if (NULL != ch->disconnects)
344 ch->disconnects (ch->ctx,
345 ch);
346 GNUNET_free (ch);
347}
348
349
350/**
351 * Reconnect to the service, retransmit all infomation to try to restore the
352 * original state.
353 *
354 * @param h handle to the cadet
355 */
356static void
357reconnect (struct GNUNET_CADET_Handle *h);
358
359
360/**
361 * Reconnect callback: tries to reconnect again after a failer previous
362 * reconnecttion
363 *
364 * @param cls closure (cadet handle)
365 */
366static void
367reconnect_cbk (void *cls)
368{
369 struct GNUNET_CADET_Handle *h = cls;
370
371 h->reconnect_task = NULL;
372 reconnect (h);
373}
374
375
376/**
377 * Reconnect to the service, retransmit all infomation to try to restore the
378 * original state.
379 *
380 * @param h handle to the cadet
381 *
382 * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...)
383 */
384static void
385schedule_reconnect (struct GNUNET_CADET_Handle *h)
386{
387 if (NULL == h->reconnect_task)
388 {
389 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
390 &reconnect_cbk, h);
391 h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
392 }
393}
394
395
396/**
397 * Notify the application about a change in the window size (if needed).
398 *
399 * @param ch Channel to notify about.
400 */
401static void
402notify_window_size (struct GNUNET_CADET_Channel *ch)
403{
404 if (NULL != ch->window_changes)
405 ch->window_changes (ch->ctx, ch,
406 ch->allow_send);
407}
408
409
410/**
411 * Allow the MQ implementation to send the next message.
412 *
413 * @param cls Closure (channel whose mq to activate).
414 */
415static void
416cadet_mq_send_continue (void *cls)
417{
418 struct GNUNET_CADET_Channel *ch = cls;
419
420 ch->mq_cont = NULL;
421 GNUNET_MQ_impl_send_continue (ch->mq);
422}
423
424/**
425 * Implement sending functionality of a message queue for
426 * us sending messages to a peer.
427 *
428 * Encapsulates the payload message in a #GNUNET_CADET_LocalData message
429 * in order to label the message with the channel ID and send the
430 * encapsulated message to the service.
431 *
432 * @param mq the message queue
433 * @param msg the message to send
434 * @param impl_state state of the implementation
435 */
436static void
437cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
438 const struct GNUNET_MessageHeader *msg,
439 void *impl_state)
440{
441 struct GNUNET_CADET_Channel *ch = impl_state;
442 struct GNUNET_CADET_Handle *h = ch->cadet;
443 uint16_t msize;
444 struct GNUNET_MQ_Envelope *env;
445 struct GNUNET_CADET_LocalData *cadet_msg;
446
447
448 if (NULL == h->mq)
449 {
450 /* We're currently reconnecting, pretend this worked */
451 GNUNET_MQ_impl_send_continue (mq);
452 return;
453 }
454
455 /* check message size for sanity */
456 msize = ntohs (msg->size);
457 if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE)
458 {
459 GNUNET_break (0);
460 GNUNET_MQ_impl_send_continue (mq);
461 return;
462 }
463
464 env = GNUNET_MQ_msg_nested_mh (cadet_msg,
465 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
466 msg);
467 cadet_msg->ccn = ch->ccn;
468
469 if (0 < ch->allow_send)
470 {
471 /* Service has allowed this message, just send it and continue accepting */
472 GNUNET_MQ_send (h->mq, env);
473 ch->allow_send--;
474 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch);
475 // notify_window_size (ch); /* FIXME add "verbose" setting? */
476 }
477 else
478 {
479 /* Service has NOT allowed this message, queue it and wait for an ACK */
480 GNUNET_assert (NULL == ch->pending_env);
481 ch->pending_env = env;
482 }
483}
484
485
486/**
487 * Handle destruction of a message queue. Implementations must not
488 * free @a mq, but should take care of @a impl_state.
489 *
490 * @param mq the message queue to destroy
491 * @param impl_state state of the implementation
492 */
493static void
494cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
495 void *impl_state)
496{
497 struct GNUNET_CADET_Channel *ch = impl_state;
498
499 GNUNET_assert (mq == ch->mq);
500 ch->mq = NULL;
501}
502
503
504/**
505 * We had an error processing a message we forwarded from a peer to
506 * the CADET service. We should just complain about it but otherwise
507 * continue processing.
508 *
509 * @param cls closure with our `struct GNUNET_CADET_Channel`
510 * @param error error code
511 */
512static void
513cadet_mq_error_handler (void *cls,
514 enum GNUNET_MQ_Error error)
515{
516 struct GNUNET_CADET_Channel *ch = cls;
517
518 GNUNET_break_op (0);
519 if (GNUNET_MQ_ERROR_NO_MATCH)
520 {
521 /* Got a message we did not understand, still try to continue! */
522 GNUNET_CADET_receive_done (ch);
523 }
524}
525
526
527/**
528 * Implementation function that cancels the currently sent message.
529 * Should basically undo whatever #mq_send_impl() did.
530 *
531 * @param mq message queue
532 * @param impl_state state specific to the implementation
533 */
534static void
535cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
536 void *impl_state)
537{
538 struct GNUNET_CADET_Channel *ch = impl_state;
539
540 LOG (GNUNET_ERROR_TYPE_WARNING,
541 "Cannot cancel mq message on channel %X of %p\n",
542 ch->ccn.channel_of_client,
543 ch->cadet);
544 GNUNET_break (0);
545}
546
547
548/**
549 * Process the new channel notification and add it to the channels in the handle
550 *
551 * @param h The cadet handle
552 * @param msg A message with the details of the new incoming channel
553 */
554static void
555handle_channel_created (void *cls,
556 const struct GNUNET_CADET_LocalChannelCreateMessage *msg)
557{
558 struct GNUNET_CADET_Handle *h = cls;
559 struct GNUNET_CADET_Channel *ch;
560 struct GNUNET_CADET_Port *port;
561 const struct GNUNET_HashCode *port_number;
562 struct GNUNET_CADET_ClientChannelNumber ccn;
563
564 ccn = msg->ccn;
565 port_number = &msg->port;
566 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
567 {
568 GNUNET_break (0);
569 return;
570 }
571 port = find_port (h, port_number);
572 if (NULL == port)
573 {
574 /* We could have closed the port but the service didn't know about it yet
575 * This is not an error.
576 */
577 struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg;
578 struct GNUNET_MQ_Envelope *env;
579
580 GNUNET_break (0);
581 LOG (GNUNET_ERROR_TYPE_DEBUG,
582 "No handler for incoming channel %X (on port %s, recently closed?)\n",
583 ntohl (ccn.channel_of_client),
584 GNUNET_h2s (port_number));
585 env = GNUNET_MQ_msg (d_msg,
586 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
587 d_msg->ccn = msg->ccn;
588 GNUNET_MQ_send (h->mq,
589 env);
590 return;
591 }
592
593 ch = create_channel (h,
594 &ccn);
595 ch->peer = msg->peer;
596 ch->cadet = h;
597 ch->incoming_port = port;
598 ch->options = ntohl (msg->opt);
599 LOG (GNUNET_ERROR_TYPE_DEBUG,
600 "Creating incoming channel %X [%s] %p\n",
601 ntohl (ccn.channel_of_client),
602 GNUNET_h2s (port_number),
603 ch);
604
605 GNUNET_assert (NULL != port->connects);
606 ch->window_changes = port->window_changes;
607 ch->disconnects = port->disconnects;
608 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
609 &cadet_mq_destroy_impl,
610 &cadet_mq_cancel_impl,
611 ch,
612 port->handlers,
613 &cadet_mq_error_handler,
614 ch);
615 ch->ctx = port->connects (port->cls,
616 ch,
617 &msg->peer);
618 GNUNET_MQ_set_handlers_closure (ch->mq,
619 ch->ctx);
620}
621
622
623/**
624 * Process the channel destroy notification and free associated resources
625 *
626 * @param h The cadet handle
627 * @param msg A message with the details of the channel being destroyed
628 */
629static void
630handle_channel_destroy (void *cls,
631 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
632{
633 struct GNUNET_CADET_Handle *h = cls;
634 struct GNUNET_CADET_Channel *ch;
635
636 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "Received channel destroy for channel %X from CADET service\n",
638 ntohl (msg->ccn.channel_of_client));
639 ch = find_channel (h,
640 msg->ccn);
641 if (NULL == ch)
642 {
643 GNUNET_break (0);
644 return;
645 }
646 destroy_channel (ch);
647}
648
649
650/**
651 * Check that message received from CADET service is well-formed.
652 *
653 * @param cls the `struct GNUNET_CADET_Handle`
654 * @param message the message we got
655 * @return #GNUNET_OK if the message is well-formed,
656 * #GNUNET_SYSERR otherwise
657 */
658static int
659check_local_data (void *cls,
660 const struct GNUNET_CADET_LocalData *message)
661{
662 struct GNUNET_CADET_Handle *h = cls;
663 struct GNUNET_CADET_Channel *ch;
664 uint16_t size;
665
666 size = ntohs (message->header.size);
667 if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size)
668 {
669 GNUNET_break_op (0);
670 return GNUNET_SYSERR;
671 }
672
673 ch = find_channel (h,
674 message->ccn);
675 if (NULL == ch)
676 {
677 GNUNET_break_op (0);
678 return GNUNET_SYSERR;
679 }
680
681 return GNUNET_OK;
682}
683
684
685/**
686 * Process the incoming data packets, call appropriate handlers.
687 *
688 * @param h The cadet handle
689 * @param message A message encapsulating the data
690 */
691static void
692handle_local_data (void *cls,
693 const struct GNUNET_CADET_LocalData *message)
694{
695 struct GNUNET_CADET_Handle *h = cls;
696 const struct GNUNET_MessageHeader *payload;
697 struct GNUNET_CADET_Channel *ch;
698 uint16_t type;
699 int fwd;
700
701 ch = find_channel (h,
702 message->ccn);
703 if (NULL == ch)
704 {
705 GNUNET_break_op (0);
706 reconnect (h);
707 return;
708 }
709
710 payload = (struct GNUNET_MessageHeader *) &message[1];
711 type = ntohs (payload->type);
712 fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
713 LOG (GNUNET_ERROR_TYPE_DEBUG,
714 "Got a %s data on channel %s [%X] of type %s (%u)\n",
715 GC_f2s (fwd),
716 GNUNET_i2s (&ch->peer),
717 ntohl (message->ccn.channel_of_client),
718 GC_m2s (type),
719 type);
720 GNUNET_MQ_inject_message (ch->mq,
721 payload);
722}
723
724
725/**
726 * Process a local ACK message, enabling the client to send
727 * more data to the service.
728 *
729 * @param h Cadet handle.
730 * @param message Message itself.
731 */
732static void
733handle_local_ack (void *cls,
734 const struct GNUNET_CADET_LocalAck *message)
735{
736 struct GNUNET_CADET_Handle *h = cls;
737 struct GNUNET_CADET_Channel *ch;
738
739 ch = find_channel (h,
740 message->ccn);
741 if (NULL == ch)
742 {
743 LOG (GNUNET_ERROR_TYPE_DEBUG,
744 "ACK on unknown channel %X\n",
745 ntohl (message->ccn.channel_of_client));
746 return;
747 }
748 ch->allow_send++;
749 if (NULL == ch->pending_env)
750 {
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Got an ACK on mq channel %X, allow send now %u!\n",
753 ntohl (ch->ccn.channel_of_client),
754 ch->allow_send);
755 notify_window_size (ch);
756 }
757 else
758 {
759 LOG (GNUNET_ERROR_TYPE_DEBUG,
760 "Got an ACK on mq channel %X, sending pending message!\n",
761 ntohl (ch->ccn.channel_of_client));
762 GNUNET_MQ_send (h->mq,
763 ch->pending_env);
764 ch->allow_send--;
765 ch->pending_env = NULL;
766 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue,
767 ch);
768 }
769}
770
771
772/**
773 * Generic error handler, called with the appropriate error code and
774 * the same closure specified at the creation of the message queue.
775 * Not every message queue implementation supports an error handler.
776 *
777 * @param cls closure, a `struct GNUNET_CORE_Handle *`
778 * @param error error code
779 */
780static void
781handle_mq_error (void *cls,
782 enum GNUNET_MQ_Error error)
783{
784 struct GNUNET_CADET_Handle *h = cls;
785
786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error);
787 GNUNET_MQ_destroy (h->mq);
788 h->mq = NULL;
789 reconnect (h);
790}
791
792
793/**
794 * Check that message received from CADET service is well-formed.
795 *
796 * @param cls the `struct GNUNET_CADET_Handle`
797 * @param message the message we got
798 * @return #GNUNET_OK if the message is well-formed,
799 * #GNUNET_SYSERR otherwise
800 */
801static int
802check_get_peers (void *cls,
803 const struct GNUNET_CADET_LocalInfoPeer *message)
804{
805 struct GNUNET_CADET_Handle *h = cls;
806 uint16_t size;
807
808 if (NULL == h->info_cb.peers_cb)
809 {
810 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
811 " no handler for peesr monitor message!\n");
812 return GNUNET_SYSERR;
813 }
814
815 size = ntohs (message->header.size);
816 if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size)
817 {
818 h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0);
819 h->info_cb.peers_cb = NULL;
820 h->info_cls = NULL;
821 return GNUNET_SYSERR;
822 }
823
824 return GNUNET_OK;
825}
826
827
828/**
829 * Process a local reply about info on all tunnels, pass info to the user.
830 *
831 * @param cls Closure (Cadet handle).
832 * @param msg Message itself.
833 */
834static void
835handle_get_peers (void *cls,
836 const struct GNUNET_CADET_LocalInfoPeer *msg)
837{
838 struct GNUNET_CADET_Handle *h = cls;
839 h->info_cb.peers_cb (h->info_cls, &msg->destination,
840 (int) ntohs (msg->tunnel),
841 (unsigned int ) ntohs (msg->paths),
842 0);
843}
844
845
846/**
847 * Check that message received from CADET service is well-formed.
848 *
849 * @param cls the `struct GNUNET_CADET_Handle`
850 * @param message the message we got
851 * @return #GNUNET_OK if the message is well-formed,
852 * #GNUNET_SYSERR otherwise
853 */
854static int
855check_get_peer (void *cls,
856 const struct GNUNET_CADET_LocalInfoPeer *message)
857{
858 struct GNUNET_CADET_Handle *h = cls;
859 const size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer);
860 struct GNUNET_PeerIdentity *paths_array;
861 size_t esize;
862 unsigned int epaths;
863 unsigned int paths;
864 unsigned int peers;
865
866 if (NULL == h->info_cb.peer_cb)
867 {
868 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
869 " no handler for peer monitor message!\n");
870 goto clean_cls;
871 }
872
873 /* Verify message sanity */
874 esize = ntohs (message->header.size);
875 if (esize < msize)
876 {
877 GNUNET_break_op (0);
878 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
879 goto clean_cls;
880 }
881 if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity)))
882 {
883 GNUNET_break_op (0);
884 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
885 goto clean_cls;
886
887 }
888 peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity);
889 epaths = (unsigned int) ntohs (message->paths);
890 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
891 paths = 0;
892 for (int i = 0; i < peers; i++)
893 {
894 if (0 == memcmp (&paths_array[i], &message->destination,
895 sizeof (struct GNUNET_PeerIdentity)))
896 {
897 paths++;
898 }
899 }
900 if (paths != epaths)
901 {
902 GNUNET_break_op (0);
903 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths);
904 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
905 goto clean_cls;
906 }
907
908 return GNUNET_OK;
909
910clean_cls:
911 h->info_cb.peer_cb = NULL;
912 h->info_cls = NULL;
913 return GNUNET_SYSERR;
914}
915
916
917/**
918 * Process a local peer info reply, pass info to the user.
919 *
920 * @param cls Closure (Cadet handle).
921 * @param message Message itself.
922 */
923static void
924handle_get_peer (void *cls,
925 const struct GNUNET_CADET_LocalInfoPeer *message)
926{
927 struct GNUNET_CADET_Handle *h = cls;
928 struct GNUNET_PeerIdentity *paths_array;
929 unsigned int paths;
930 unsigned int path_length;
931 int neighbor;
932 unsigned int peers;
933
934 paths = (unsigned int) ntohs (message->paths);
935 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
936 peers = (ntohs (message->header.size) - sizeof (*message))
937 / sizeof (struct GNUNET_PeerIdentity);
938 path_length = 0;
939 neighbor = GNUNET_NO;
940
941 for (int i = 0; i < peers; i++)
942 {
943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&paths_array[i]));
944 path_length++;
945 if (0 == memcmp (&paths_array[i], &message->destination,
946 sizeof (struct GNUNET_PeerIdentity)))
947 {
948 if (1 == path_length)
949 neighbor = GNUNET_YES;
950 path_length = 0;
951 }
952 }
953
954 /* Call Callback with tunnel info. */
955 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
956 h->info_cb.peer_cb (h->info_cls,
957 &message->destination,
958 (int) ntohs (message->tunnel),
959 neighbor,
960 paths,
961 paths_array);
962}
963
964
965/**
966 * Check that message received from CADET service is well-formed.
967 *
968 * @param cls the `struct GNUNET_CADET_Handle`
969 * @param msg the message we got
970 * @return #GNUNET_OK if the message is well-formed,
971 * #GNUNET_SYSERR otherwise
972 */
973static int
974check_get_tunnels (void *cls,
975 const struct GNUNET_CADET_LocalInfoTunnel *msg)
976{
977 struct GNUNET_CADET_Handle *h = cls;
978 uint16_t size;
979
980 if (NULL == h->info_cb.tunnels_cb)
981 {
982 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
983 " no handler for tunnels monitor message!\n");
984 return GNUNET_SYSERR;
985 }
986
987 size = ntohs (msg->header.size);
988 if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size)
989 {
990 h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0);
991 h->info_cb.tunnels_cb = NULL;
992 h->info_cls = NULL;
993 return GNUNET_SYSERR;
994 }
995 return GNUNET_OK;
996}
997
998
999/**
1000 * Process a local reply about info on all tunnels, pass info to the user.
1001 *
1002 * @param cls Closure (Cadet handle).
1003 * @param message Message itself.
1004 */
1005static void
1006handle_get_tunnels (void *cls,
1007 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1008{
1009 struct GNUNET_CADET_Handle *h = cls;
1010
1011 h->info_cb.tunnels_cb (h->info_cls,
1012 &msg->destination,
1013 ntohl (msg->channels),
1014 ntohl (msg->connections),
1015 ntohs (msg->estate),
1016 ntohs (msg->cstate));
1017
1018}
1019
1020
1021/**
1022 * Check that message received from CADET service is well-formed.
1023 *
1024 * @param cls the `struct GNUNET_CADET_Handle`
1025 * @param msg the message we got
1026 * @return #GNUNET_OK if the message is well-formed,
1027 * #GNUNET_SYSERR otherwise
1028 */
1029static int
1030check_get_tunnel (void *cls,
1031 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1032{
1033 struct GNUNET_CADET_Handle *h = cls;
1034 unsigned int ch_n;
1035 unsigned int c_n;
1036 size_t esize;
1037 size_t msize;
1038
1039 if (NULL == h->info_cb.tunnel_cb)
1040 {
1041 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1042 " no handler for tunnel monitor message!\n");
1043 goto clean_cls;
1044 }
1045
1046 /* Verify message sanity */
1047 msize = ntohs (msg->header.size);
1048 esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
1049 if (esize > msize)
1050 {
1051 GNUNET_break_op (0);
1052 h->info_cb.tunnel_cb (h->info_cls,
1053 NULL, 0, 0, NULL, NULL, 0, 0);
1054 goto clean_cls;
1055 }
1056 ch_n = ntohl (msg->channels);
1057 c_n = ntohl (msg->connections);
1058 esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1059 esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1060 if (msize != esize)
1061 {
1062 GNUNET_break_op (0);
1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 "m:%u, e: %u (%u ch, %u conn)\n",
1065 (unsigned int) msize,
1066 (unsigned int) esize,
1067 ch_n,
1068 c_n);
1069 h->info_cb.tunnel_cb (h->info_cls,
1070 NULL, 0, 0, NULL, NULL, 0, 0);
1071 goto clean_cls;
1072 }
1073
1074 return GNUNET_OK;
1075
1076clean_cls:
1077 h->info_cb.tunnel_cb = NULL;
1078 h->info_cls = NULL;
1079 return GNUNET_SYSERR;
1080}
1081
1082
1083/**
1084 * Process a local tunnel info reply, pass info to the user.
1085 *
1086 * @param cls Closure (Cadet handle).
1087 * @param msg Message itself.
1088 */
1089static void
1090handle_get_tunnel (void *cls,
1091 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1092{
1093 struct GNUNET_CADET_Handle *h = cls;
1094 unsigned int ch_n;
1095 unsigned int c_n;
1096 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
1097 const struct GNUNET_CADET_ChannelTunnelNumber *chns;
1098
1099 ch_n = ntohl (msg->channels);
1100 c_n = ntohl (msg->connections);
1101
1102 /* Call Callback with tunnel info. */
1103 conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1104 chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
1105 h->info_cb.tunnel_cb (h->info_cls,
1106 &msg->destination,
1107 ch_n,
1108 c_n,
1109 chns,
1110 conns,
1111 ntohs (msg->estate),
1112 ntohs (msg->cstate));
1113}
1114
1115
1116/**
1117 * Function called during #reconnect() to destroy
1118 * all channels that are still open.
1119 *
1120 * @param cls the `struct GNUNET_CADET_Handle`
1121 * @param cid chanenl ID
1122 * @param value a `struct GNUNET_CADET_Channel` to destroy
1123 * @return #GNUNET_OK (continue to iterate)
1124 */
1125static int
1126destroy_channel_on_reconnect_cb (void *cls,
1127 uint32_t cid,
1128 void *value)
1129{
1130 /* struct GNUNET_CADET_Handle *handle = cls; */
1131 struct GNUNET_CADET_Channel *ch = value;
1132
1133 destroy_channel (ch);
1134 return GNUNET_OK;
1135}
1136
1137
1138/**
1139 * Reconnect to the service, retransmit all infomation to try to restore the
1140 * original state.
1141 *
1142 * @param h handle to the cadet
1143 */
1144static void
1145reconnect (struct GNUNET_CADET_Handle *h)
1146{
1147 struct GNUNET_MQ_MessageHandler handlers[] = {
1148 GNUNET_MQ_hd_fixed_size (channel_created,
1149 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1150 struct GNUNET_CADET_LocalChannelCreateMessage,
1151 h),
1152 GNUNET_MQ_hd_fixed_size (channel_destroy,
1153 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1154 struct GNUNET_CADET_LocalChannelDestroyMessage,
1155 h),
1156 GNUNET_MQ_hd_var_size (local_data,
1157 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1158 struct GNUNET_CADET_LocalData,
1159 h),
1160 GNUNET_MQ_hd_fixed_size (local_ack,
1161 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1162 struct GNUNET_CADET_LocalAck,
1163 h),
1164 GNUNET_MQ_hd_var_size (get_peers,
1165 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1166 struct GNUNET_CADET_LocalInfoPeer,
1167 h),
1168 GNUNET_MQ_hd_var_size (get_peer,
1169 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1170 struct GNUNET_CADET_LocalInfoPeer,
1171 h),
1172 GNUNET_MQ_hd_var_size (get_tunnels,
1173 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1174 struct GNUNET_CADET_LocalInfoTunnel,
1175 h),
1176 GNUNET_MQ_hd_var_size (get_tunnel,
1177 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1178 struct GNUNET_CADET_LocalInfoTunnel,
1179 h),
1180 GNUNET_MQ_handler_end ()
1181 };
1182
1183 GNUNET_CONTAINER_multihashmap32_iterate (h->channels,
1184 &destroy_channel_on_reconnect_cb,
1185 h);
1186 if (NULL != h->mq)
1187 {
1188 GNUNET_MQ_destroy (h->mq);
1189 h->mq = NULL;
1190 }
1191 h->mq = GNUNET_CLIENT_connect (h->cfg,
1192 "cadet",
1193 handlers,
1194 &handle_mq_error,
1195 h);
1196 if (NULL == h->mq)
1197 {
1198 schedule_reconnect (h);
1199 return;
1200 }
1201 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1202}
1203
1204
1205/**
1206 * Function called during #GNUNET_CADET_disconnect() to destroy
1207 * all channels that are still open.
1208 *
1209 * @param cls the `struct GNUNET_CADET_Handle`
1210 * @param cid chanenl ID
1211 * @param value a `struct GNUNET_CADET_Channel` to destroy
1212 * @return #GNUNET_OK (continue to iterate)
1213 */
1214static int
1215destroy_channel_cb (void *cls,
1216 uint32_t cid,
1217 void *value)
1218{
1219 /* struct GNUNET_CADET_Handle *handle = cls; */
1220 struct GNUNET_CADET_Channel *ch = value;
1221
1222 if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1223 {
1224 GNUNET_break (0);
1225 LOG (GNUNET_ERROR_TYPE_DEBUG,
1226 "channel %X not destroyed\n",
1227 ntohl (ch->ccn.channel_of_client));
1228 }
1229 destroy_channel (ch);
1230 return GNUNET_OK;
1231}
1232
1233
1234/**
1235 * Function called during #GNUNET_CADET_disconnect() to destroy
1236 * all ports that are still open.
1237 *
1238 * @param cls the `struct GNUNET_CADET_Handle`
1239 * @param id port ID
1240 * @param value a `struct GNUNET_CADET_Channel` to destroy
1241 * @return #GNUNET_OK (continue to iterate)
1242 */
1243static int
1244destroy_port_cb (void *cls,
1245 const struct GNUNET_HashCode *id,
1246 void *value)
1247{
1248 /* struct GNUNET_CADET_Handle *handle = cls; */
1249 struct GNUNET_CADET_Port *port = value;
1250
1251 GNUNET_break (0);
1252 GNUNET_CADET_close_port (port);
1253 return GNUNET_OK;
1254}
1255
1256
1257/**
1258 * Disconnect from the cadet service. All channels will be destroyed. All channel
1259 * disconnect callbacks will be called on any still connected peers, notifying
1260 * about their disconnection. The registered inbound channel cleaner will be
1261 * called should any inbound channels still exist.
1262 *
1263 * @param handle connection to cadet to disconnect
1264 */
1265void
1266GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
1267{
1268 GNUNET_CONTAINER_multihashmap_iterate (handle->ports,
1269 &destroy_port_cb,
1270 handle);
1271 GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
1272 handle->ports = NULL;
1273 GNUNET_CONTAINER_multihashmap32_iterate (handle->channels,
1274 &destroy_channel_cb,
1275 handle);
1276 GNUNET_CONTAINER_multihashmap32_destroy (handle->channels);
1277 handle->channels = NULL;
1278 if (NULL != handle->mq)
1279 {
1280 GNUNET_MQ_destroy (handle->mq);
1281 handle->mq = NULL;
1282 }
1283 if (NULL != handle->reconnect_task)
1284 {
1285 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
1286 handle->reconnect_task = NULL;
1287 }
1288 GNUNET_free (handle);
1289}
1290
1291
1292/**
1293 * Close a port opened with @a GNUNET_CADET_open_port().
1294 * The @a new_channel callback will no longer be called.
1295 *
1296 * @param p Port handle.
1297 */
1298void
1299GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
1300{
1301 struct GNUNET_CADET_PortMessage *msg;
1302 struct GNUNET_MQ_Envelope *env;
1303
1304 env = GNUNET_MQ_msg (msg,
1305 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
1306 msg->port = p->id;
1307 GNUNET_MQ_send (p->cadet->mq,
1308 env);
1309 GNUNET_assert (GNUNET_YES ==
1310 GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports,
1311 &p->id,
1312 p));
1313 GNUNET_free (p);
1314}
1315
1316
1317/**
1318 * Destroy an existing channel.
1319 *
1320 * The existing end callback for the channel will be called immediately.
1321 * Any pending outgoing messages will be sent but no incoming messages will be
1322 * accepted and no data callbacks will be called.
1323 *
1324 * @param channel Channel handle, becomes invalid after this call.
1325 */
1326void
1327GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
1328{
1329 struct GNUNET_CADET_Handle *h = channel->cadet;
1330 struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
1331 struct GNUNET_MQ_Envelope *env;
1332
1333 env = GNUNET_MQ_msg (msg,
1334 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1335 msg->ccn = channel->ccn;
1336 GNUNET_MQ_send (h->mq,
1337 env);
1338 destroy_channel (channel);
1339}
1340
1341
1342/**
1343 * Get information about a channel.
1344 *
1345 * @param channel Channel handle.
1346 * @param option Query (GNUNET_CADET_OPTION_*).
1347 * @param ... dependant on option, currently not used
1348 *
1349 * @return Union with an answer to the query.
1350 */
1351const union GNUNET_CADET_ChannelInfo *
1352GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
1353 enum GNUNET_CADET_ChannelOption option,
1354 ...)
1355{
1356 static int bool_flag;
1357
1358 switch (option)
1359 {
1360 case GNUNET_CADET_OPTION_NOBUFFER:
1361 case GNUNET_CADET_OPTION_RELIABLE:
1362 case GNUNET_CADET_OPTION_OUT_OF_ORDER:
1363 if (0 != (option & channel->options))
1364 bool_flag = GNUNET_YES;
1365 else
1366 bool_flag = GNUNET_NO;
1367 return (const union GNUNET_CADET_ChannelInfo *) &bool_flag;
1368 break;
1369 case GNUNET_CADET_OPTION_PEER:
1370 return (const union GNUNET_CADET_ChannelInfo *) &channel->peer;
1371 break;
1372 default:
1373 GNUNET_break (0);
1374 return NULL;
1375 }
1376}
1377
1378
1379/**
1380 * Send an ack on the channel to confirm the processing of a message.
1381 *
1382 * @param ch Channel on which to send the ACK.
1383 */
1384void
1385GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
1386{
1387 struct GNUNET_CADET_LocalAck *msg;
1388 struct GNUNET_MQ_Envelope *env;
1389
1390 env = GNUNET_MQ_msg (msg,
1391 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1392 LOG (GNUNET_ERROR_TYPE_DEBUG,
1393 "Sending ACK on channel %X\n",
1394 ntohl (channel->ccn.channel_of_client));
1395 msg->ccn = channel->ccn;
1396 GNUNET_MQ_send (channel->cadet->mq,
1397 env);
1398}
1399
1400
1401/**
1402 * Send message of @a type to CADET service of @a h
1403 *
1404 * @param h handle to CADET service
1405 * @param type message type of trivial information request to send
1406 */
1407static void
1408send_info_request (struct GNUNET_CADET_Handle *h,
1409 uint16_t type)
1410{
1411 struct GNUNET_MessageHeader *msg;
1412 struct GNUNET_MQ_Envelope *env;
1413
1414 env = GNUNET_MQ_msg (msg,
1415 type);
1416 GNUNET_MQ_send (h->mq,
1417 env);
1418}
1419
1420
1421/**
1422 * Request a debug dump on the service's STDERR.
1423 *
1424 * WARNING: unstable API, likely to change in the future!
1425 *
1426 * @param h cadet handle
1427 */
1428void
1429GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h)
1430{
1431 send_info_request (h,
1432 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP);
1433}
1434
1435
1436/**
1437 * Request information about peers known to the running cadet service.
1438 * The callback will be called for every peer known to the service.
1439 * Only one info request (of any kind) can be active at once.
1440 *
1441 * WARNING: unstable API, likely to change in the future!
1442 *
1443 * @param h Handle to the cadet peer.
1444 * @param callback Function to call with the requested data.
1445 * @param callback_cls Closure for @c callback.
1446 * @return #GNUNET_OK / #GNUNET_SYSERR
1447 */
1448int
1449GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h,
1450 GNUNET_CADET_PeersCB callback,
1451 void *callback_cls)
1452{
1453 if (NULL != h->info_cb.peers_cb)
1454 {
1455 GNUNET_break (0);
1456 return GNUNET_SYSERR;
1457 }
1458 send_info_request (h,
1459 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
1460 h->info_cb.peers_cb = callback;
1461 h->info_cls = callback_cls;
1462 return GNUNET_OK;
1463}
1464
1465
1466/**
1467 * Cancel a peer info request. The callback will not be called (anymore).
1468 *
1469 * WARNING: unstable API, likely to change in the future!
1470 *
1471 * @param h Cadet handle.
1472 * @return Closure given to GNUNET_CADET_get_peers().
1473 */
1474void *
1475GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h)
1476{
1477 void *cls = h->info_cls;
1478
1479 h->info_cb.peers_cb = NULL;
1480 h->info_cls = NULL;
1481 return cls;
1482}
1483
1484
1485/**
1486 * Request information about a peer known to the running cadet peer.
1487 * The callback will be called for the tunnel once.
1488 * Only one info request (of any kind) can be active at once.
1489 *
1490 * WARNING: unstable API, likely to change in the future!
1491 *
1492 * @param h Handle to the cadet peer.
1493 * @param id Peer whose tunnel to examine.
1494 * @param callback Function to call with the requested data.
1495 * @param callback_cls Closure for @c callback.
1496 * @return #GNUNET_OK / #GNUNET_SYSERR
1497 */
1498int
1499GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h,
1500 const struct GNUNET_PeerIdentity *id,
1501 GNUNET_CADET_PeerCB callback,
1502 void *callback_cls)
1503{
1504 struct GNUNET_CADET_LocalInfo *msg;
1505 struct GNUNET_MQ_Envelope *env;
1506
1507 if (NULL != h->info_cb.peer_cb)
1508 {
1509 GNUNET_break (0);
1510 return GNUNET_SYSERR;
1511 }
1512 env = GNUNET_MQ_msg (msg,
1513 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
1514 msg->peer = *id;
1515 GNUNET_MQ_send (h->mq,
1516 env);
1517 h->info_cb.peer_cb = callback;
1518 h->info_cls = callback_cls;
1519 return GNUNET_OK;
1520}
1521
1522
1523/**
1524 * Request information about tunnels of the running cadet peer.
1525 * The callback will be called for every tunnel of the service.
1526 * Only one info request (of any kind) can be active at once.
1527 *
1528 * WARNING: unstable API, likely to change in the future!
1529 *
1530 * @param h Handle to the cadet peer.
1531 * @param callback Function to call with the requested data.
1532 * @param callback_cls Closure for @c callback.
1533 * @return #GNUNET_OK / #GNUNET_SYSERR
1534 */
1535int
1536GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h,
1537 GNUNET_CADET_TunnelsCB callback,
1538 void *callback_cls)
1539{
1540 if (NULL != h->info_cb.tunnels_cb)
1541 {
1542 GNUNET_break (0);
1543 return GNUNET_SYSERR;
1544 }
1545 send_info_request (h,
1546 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
1547 h->info_cb.tunnels_cb = callback;
1548 h->info_cls = callback_cls;
1549 return GNUNET_OK;
1550}
1551
1552
1553/**
1554 * Cancel a monitor request. The monitor callback will not be called.
1555 *
1556 * @param h Cadet handle.
1557 * @return Closure given to GNUNET_CADET_get_tunnels().
1558 */
1559void *
1560GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h)
1561{
1562 void *cls = h->info_cls;
1563
1564 h->info_cb.tunnels_cb = NULL;
1565 h->info_cls = NULL;
1566 return cls;
1567}
1568
1569
1570/**
1571 * Request information about a tunnel of the running cadet peer.
1572 * The callback will be called for the tunnel once.
1573 * Only one info request (of any kind) can be active at once.
1574 *
1575 * WARNING: unstable API, likely to change in the future!
1576 *
1577 * @param h Handle to the cadet peer.
1578 * @param id Peer whose tunnel to examine.
1579 * @param callback Function to call with the requested data.
1580 * @param callback_cls Closure for @c callback.
1581 * @return #GNUNET_OK / #GNUNET_SYSERR
1582 */
1583int
1584GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h,
1585 const struct GNUNET_PeerIdentity *id,
1586 GNUNET_CADET_TunnelCB callback,
1587 void *callback_cls)
1588{
1589 struct GNUNET_CADET_LocalInfo *msg;
1590 struct GNUNET_MQ_Envelope *env;
1591
1592 if (NULL != h->info_cb.tunnel_cb)
1593 {
1594 GNUNET_break (0);
1595 return GNUNET_SYSERR;
1596 }
1597 env = GNUNET_MQ_msg (msg,
1598 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1599 msg->peer = *id;
1600 GNUNET_MQ_send (h->mq,
1601 env);
1602 h->info_cb.tunnel_cb = callback;
1603 h->info_cls = callback_cls;
1604 return GNUNET_OK;
1605}
1606
1607
1608/**
1609 * Transitional function to convert an unsigned int port to a hash value.
1610 * WARNING: local static value returned, NOT reentrant!
1611 * WARNING: do not use this function for new code!
1612 *
1613 * @param port Numerical port (unsigned int format).
1614 *
1615 * @return A GNUNET_HashCode usable for the new CADET API.
1616 */
1617const struct GNUNET_HashCode *
1618GC_u2h (uint32_t port)
1619{
1620 static struct GNUNET_HashCode hash;
1621
1622 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1623 "This is a transitional function, use proper crypto hashes as CADET ports\n");
1624 GNUNET_CRYPTO_hash (&port,
1625 sizeof (port),
1626 &hash);
1627 return &hash;
1628}
1629
1630
1631/**
1632 * Connect to the MQ-based cadet service.
1633 *
1634 * @param cfg Configuration to use.
1635 *
1636 * @return Handle to the cadet service NULL on error.
1637 */
1638struct GNUNET_CADET_Handle *
1639GNUNET_CADET_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg)
1640{
1641 struct GNUNET_CADET_Handle *h;
1642
1643 LOG (GNUNET_ERROR_TYPE_DEBUG,
1644 "GNUNET_CADET_connecT()\n");
1645 h = GNUNET_new (struct GNUNET_CADET_Handle);
1646 h->cfg = cfg;
1647 h->ports = GNUNET_CONTAINER_multihashmap_create (4,
1648 GNUNET_YES);
1649 h->channels = GNUNET_CONTAINER_multihashmap32_create (4);
1650 reconnect (h);
1651 if (NULL == h->mq)
1652 {
1653 GNUNET_break (0);
1654 GNUNET_CADET_disconnect (h);
1655 return NULL;
1656 }
1657 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1658 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1659 h->reconnect_task = NULL;
1660
1661 return h;
1662}
1663
1664
1665/**
1666 * Open a port to receive incomming MQ-based channels.
1667 *
1668 * @param h CADET handle.
1669 * @param port Hash identifying the port.
1670 * @param connects Function called when an incoming channel is connected.
1671 * @param connects_cls Closure for the @a connects handler.
1672 * @param window_changes Function called when the transmit window size changes.
1673 * @param disconnects Function called when a channel is disconnected.
1674 * @param handlers Callbacks for messages we care about, NULL-terminated.
1675 * @return Port handle.
1676 */
1677struct GNUNET_CADET_Port *
1678GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h,
1679 const struct GNUNET_HashCode *port,
1680 GNUNET_CADET_ConnectEventHandler connects,
1681 void * connects_cls,
1682 GNUNET_CADET_WindowSizeEventHandler window_changes,
1683 GNUNET_CADET_DisconnectEventHandler disconnects,
1684 const struct GNUNET_MQ_MessageHandler *handlers)
1685{
1686 struct GNUNET_CADET_PortMessage *msg;
1687 struct GNUNET_MQ_Envelope *env;
1688 struct GNUNET_CADET_Port *p;
1689
1690 GNUNET_assert (NULL != connects);
1691 GNUNET_assert (NULL != disconnects);
1692
1693 p = GNUNET_new (struct GNUNET_CADET_Port);
1694 p->cadet = h;
1695 p->id = *port;
1696 p->connects = connects;
1697 p->cls = connects_cls;
1698 p->window_changes = window_changes;
1699 p->disconnects = disconnects;
1700 if (NULL != handlers)
1701 {
1702 unsigned int i;
1703
1704 for (i=0;NULL != handlers[i].cb; i++) ;
1705 p->handlers = GNUNET_new_array (i + 1,
1706 struct GNUNET_MQ_MessageHandler);
1707 GNUNET_memcpy ((struct GNUNET_MQ_MessageHandler *) p->handlers,
1708 handlers,
1709 i * sizeof (struct GNUNET_MQ_MessageHandler));
1710 }
1711
1712 GNUNET_assert (GNUNET_OK ==
1713 GNUNET_CONTAINER_multihashmap_put (h->ports,
1714 &p->id,
1715 p,
1716 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1717
1718 env = GNUNET_MQ_msg (msg,
1719 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
1720 msg->port = p->id;
1721 GNUNET_MQ_send (h->mq,
1722 env);
1723 return p;
1724}
1725
1726
1727/**
1728 * Create a new channel towards a remote peer.
1729 *
1730 * If the destination port is not open by any peer or the destination peer
1731 * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
1732 * for this channel.
1733 *
1734 * @param h CADET handle.
1735 * @param channel_cls Closure for the channel. It's given to:
1736 * - The disconnect handler @a disconnects
1737 * - Each message type callback in @a handlers
1738 * @param destination Peer identity the channel should go to.
1739 * @param port Identification of the destination port.
1740 * @param options CadetOption flag field, with all desired option bits set to 1.
1741 * @param window_changes Function called when the transmit window size changes.
1742 * @param disconnects Function called when the channel is disconnected.
1743 * @param handlers Callbacks for messages we care about, NULL-terminated.
1744 * @return Handle to the channel.
1745 */
1746struct GNUNET_CADET_Channel *
1747GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h,
1748 void *channel_cls,
1749 const struct GNUNET_PeerIdentity *destination,
1750 const struct GNUNET_HashCode *port,
1751 enum GNUNET_CADET_ChannelOption options,
1752 GNUNET_CADET_WindowSizeEventHandler window_changes,
1753 GNUNET_CADET_DisconnectEventHandler disconnects,
1754 const struct GNUNET_MQ_MessageHandler *handlers)
1755{
1756 struct GNUNET_CADET_Channel *ch;
1757 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1758 struct GNUNET_MQ_Envelope *env;
1759
1760 GNUNET_assert (NULL != disconnects);
1761 ch = create_channel (h,
1762 NULL);
1763 ch->ctx = channel_cls;
1764 ch->peer = *destination;
1765 ch->options = options;
1766 ch->window_changes = window_changes;
1767 ch->disconnects = disconnects;
1768
1769 /* Create MQ for channel */
1770 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
1771 &cadet_mq_destroy_impl,
1772 &cadet_mq_cancel_impl,
1773 ch,
1774 handlers,
1775 &cadet_mq_error_handler,
1776 ch);
1777 GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls);
1778
1779 /* Request channel creation to service */
1780 env = GNUNET_MQ_msg (msg,
1781 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1782 msg->ccn = ch->ccn;
1783 msg->port = *port;
1784 msg->peer = *destination;
1785 msg->opt = htonl (options);
1786 GNUNET_MQ_send (h->mq,
1787 env);
1788 return ch;
1789}
1790
1791
1792/**
1793 * Obtain the message queue for a connected peer.
1794 *
1795 * @param channel The channel handle from which to get the MQ.
1796 *
1797 * @return NULL if @a channel is not yet connected.
1798 */
1799struct GNUNET_MQ_Handle *
1800GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)
1801{
1802 return channel->mq;
1803}
1804
1805/* end of cadet_api.c */