diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-02-17 14:12:15 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-02-17 14:12:15 +0100 |
commit | 69d9269f2c5887e73950ee3a7fc0fd5e050a8a86 (patch) | |
tree | 003e366551d619b3df9ac61df60270bb926c8db2 /src | |
parent | 9727e5e53721dace7abbcc5bcd28c838af4291cc (diff) | |
download | gnunet-69d9269f2c5887e73950ee3a7fc0fd5e050a8a86.tar.gz gnunet-69d9269f2c5887e73950ee3a7fc0fd5e050a8a86.zip |
hacking up 'new' CADET API without legacy logic
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/Makefile.am | 15 | ||||
-rw-r--r-- | src/cadet/cadet_api_new.c | 1805 |
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 | ||
32 | lib_LTLIBRARIES = \ | 32 | lib_LTLIBRARIES = \ |
33 | libgnunetcadet.la $(EXP_LIB) | 33 | libgnunetcadetnew.la \ |
34 | libgnunetcadet.la \ | ||
35 | $(EXP_LIB) | ||
34 | 36 | ||
35 | libgnunetcadet_la_SOURCES = \ | 37 | libgnunetcadet_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 | |||
48 | libgnunetcadetnew_la_SOURCES = \ | ||
49 | cadet_api_new.c | ||
50 | libgnunetcadetnew_la_LIBADD = \ | ||
51 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
52 | $(XLIB) \ | ||
53 | $(LTLIBINTL) | ||
54 | libgnunetcadetnew_la_LDFLAGS = \ | ||
55 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
56 | -version-info 6:0:0 | ||
57 | |||
45 | gnunet_cadet_SOURCES = \ | 58 | gnunet_cadet_SOURCES = \ |
46 | gnunet-cadet.c | 59 | gnunet-cadet.c |
47 | gnunet_cadet_LDADD = \ | 60 | gnunet_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 | */ | ||
38 | union 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 | */ | ||
71 | struct 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 | */ | ||
124 | struct 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 | */ | ||
194 | struct 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 | */ | ||
250 | static struct GNUNET_CADET_Port * | ||
251 | find_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 | */ | ||
266 | static struct GNUNET_CADET_Channel * | ||
267 | find_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 | */ | ||
282 | static struct GNUNET_CADET_Channel * | ||
283 | create_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 | */ | ||
324 | static void | ||
325 | destroy_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 | */ | ||
356 | static void | ||
357 | reconnect (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 | */ | ||
366 | static void | ||
367 | reconnect_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 | */ | ||
384 | static void | ||
385 | schedule_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 | */ | ||
401 | static void | ||
402 | notify_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 | */ | ||
415 | static void | ||
416 | cadet_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 | */ | ||
436 | static void | ||
437 | cadet_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 | */ | ||
493 | static void | ||
494 | cadet_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 | */ | ||
512 | static void | ||
513 | cadet_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 | */ | ||
534 | static void | ||
535 | cadet_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 | */ | ||
554 | static void | ||
555 | handle_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 | */ | ||
629 | static void | ||
630 | handle_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 | */ | ||
658 | static int | ||
659 | check_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 | */ | ||
691 | static void | ||
692 | handle_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 | */ | ||
732 | static void | ||
733 | handle_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 | */ | ||
780 | static void | ||
781 | handle_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 | */ | ||
801 | static int | ||
802 | check_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 | */ | ||
834 | static void | ||
835 | handle_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 | */ | ||
854 | static int | ||
855 | check_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 | |||
910 | clean_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 | */ | ||
923 | static void | ||
924 | handle_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 | */ | ||
973 | static int | ||
974 | check_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 | */ | ||
1005 | static void | ||
1006 | handle_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 | */ | ||
1029 | static int | ||
1030 | check_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 | |||
1076 | clean_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 | */ | ||
1089 | static void | ||
1090 | handle_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 | */ | ||
1125 | static int | ||
1126 | destroy_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 | */ | ||
1144 | static void | ||
1145 | reconnect (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 | */ | ||
1214 | static int | ||
1215 | destroy_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 | */ | ||
1243 | static int | ||
1244 | destroy_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 | */ | ||
1265 | void | ||
1266 | GNUNET_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 | */ | ||
1298 | void | ||
1299 | GNUNET_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 | */ | ||
1326 | void | ||
1327 | GNUNET_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 | */ | ||
1351 | const union GNUNET_CADET_ChannelInfo * | ||
1352 | GNUNET_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 | */ | ||
1384 | void | ||
1385 | GNUNET_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 | */ | ||
1407 | static void | ||
1408 | send_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 | */ | ||
1428 | void | ||
1429 | GNUNET_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 | */ | ||
1448 | int | ||
1449 | GNUNET_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 | */ | ||
1474 | void * | ||
1475 | GNUNET_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 | */ | ||
1498 | int | ||
1499 | GNUNET_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 | */ | ||
1535 | int | ||
1536 | GNUNET_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 | */ | ||
1559 | void * | ||
1560 | GNUNET_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 | */ | ||
1583 | int | ||
1584 | GNUNET_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 | */ | ||
1617 | const struct GNUNET_HashCode * | ||
1618 | GC_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 | */ | ||
1638 | struct GNUNET_CADET_Handle * | ||
1639 | GNUNET_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 | */ | ||
1677 | struct GNUNET_CADET_Port * | ||
1678 | GNUNET_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 | */ | ||
1746 | struct GNUNET_CADET_Channel * | ||
1747 | GNUNET_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 | */ | ||
1799 | struct GNUNET_MQ_Handle * | ||
1800 | GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) | ||
1801 | { | ||
1802 | return channel->mq; | ||
1803 | } | ||
1804 | |||
1805 | /* end of cadet_api.c */ | ||