diff options
Diffstat (limited to 'src/social/social_api.c')
-rw-r--r-- | src/social/social_api.c | 2827 |
1 files changed, 0 insertions, 2827 deletions
diff --git a/src/social/social_api.c b/src/social/social_api.c deleted file mode 100644 index 9b9658096..000000000 --- a/src/social/social_api.c +++ /dev/null | |||
@@ -1,2827 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2013 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your 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 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Gabor X Toth | ||
23 | * | ||
24 | * @file | ||
25 | * Social service; implements social interactions using the PSYC service. | ||
26 | */ | ||
27 | |||
28 | #include <inttypes.h> | ||
29 | #include <string.h> | ||
30 | |||
31 | #include "platform.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_psyc_service.h" | ||
34 | #include "gnunet_psyc_util_lib.h" | ||
35 | #include "gnunet_social_service.h" | ||
36 | #include "social.h" | ||
37 | |||
38 | #define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__) | ||
39 | |||
40 | /** | ||
41 | * Handle for an ego. | ||
42 | */ | ||
43 | struct GNUNET_SOCIAL_Ego | ||
44 | { | ||
45 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
46 | struct GNUNET_HashCode pub_key_hash; | ||
47 | char *name; | ||
48 | }; | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Handle for a pseudonym of another user in the network. | ||
53 | */ | ||
54 | struct GNUNET_SOCIAL_Nym | ||
55 | { | ||
56 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
57 | struct GNUNET_HashCode pub_key_hash; | ||
58 | }; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Handle for an application. | ||
63 | */ | ||
64 | struct GNUNET_SOCIAL_App | ||
65 | { | ||
66 | /** | ||
67 | * Configuration to use. | ||
68 | */ | ||
69 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
70 | |||
71 | /** | ||
72 | * Client connection to the service. | ||
73 | */ | ||
74 | struct GNUNET_MQ_Handle *mq; | ||
75 | |||
76 | /** | ||
77 | * Message to send on connect. | ||
78 | */ | ||
79 | struct GNUNET_MQ_Envelope *connect_env; | ||
80 | |||
81 | /** | ||
82 | * Time to wait until we try to reconnect on failure. | ||
83 | */ | ||
84 | struct GNUNET_TIME_Relative reconnect_delay; | ||
85 | |||
86 | /** | ||
87 | * Task for reconnecting when the listener fails. | ||
88 | */ | ||
89 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
90 | |||
91 | /** | ||
92 | * Async operations. | ||
93 | */ | ||
94 | struct GNUNET_OP_Handle *op; | ||
95 | |||
96 | /** | ||
97 | * Function called after disconnected from the service. | ||
98 | */ | ||
99 | GNUNET_ContinuationCallback disconnect_cb; | ||
100 | |||
101 | /** | ||
102 | * Closure for @a disconnect_cb. | ||
103 | */ | ||
104 | void *disconnect_cls; | ||
105 | |||
106 | /** | ||
107 | * Application ID. | ||
108 | */ | ||
109 | char *id; | ||
110 | |||
111 | /** | ||
112 | * Hash map of all egos. | ||
113 | * pub_key_hash -> struct GNUNET_SOCIAL_Ego * | ||
114 | */ | ||
115 | struct GNUNET_CONTAINER_MultiHashMap *egos; | ||
116 | |||
117 | GNUNET_SOCIAL_AppEgoCallback ego_cb; | ||
118 | GNUNET_SOCIAL_AppHostPlaceCallback host_cb; | ||
119 | GNUNET_SOCIAL_AppGuestPlaceCallback guest_cb; | ||
120 | GNUNET_SOCIAL_AppConnectedCallback connected_cb; | ||
121 | void *cb_cls; | ||
122 | }; | ||
123 | |||
124 | |||
125 | struct GNUNET_SOCIAL_HostConnection | ||
126 | { | ||
127 | struct GNUNET_SOCIAL_App *app; | ||
128 | |||
129 | struct AppPlaceMessage plc_msg; | ||
130 | }; | ||
131 | |||
132 | |||
133 | struct GNUNET_SOCIAL_GuestConnection | ||
134 | { | ||
135 | struct GNUNET_SOCIAL_App *app; | ||
136 | |||
137 | struct AppPlaceMessage plc_msg; | ||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Handle for a place where social interactions happen. | ||
143 | */ | ||
144 | struct GNUNET_SOCIAL_Place | ||
145 | { | ||
146 | /** | ||
147 | * Configuration to use. | ||
148 | */ | ||
149 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
150 | |||
151 | /** | ||
152 | * Client connection to the service. | ||
153 | */ | ||
154 | struct GNUNET_MQ_Handle *mq; | ||
155 | |||
156 | /** | ||
157 | * Message to send on connect. | ||
158 | */ | ||
159 | struct GNUNET_MQ_Envelope *connect_env; | ||
160 | |||
161 | /** | ||
162 | * Time to wait until we try to reconnect on failure. | ||
163 | */ | ||
164 | struct GNUNET_TIME_Relative reconnect_delay; | ||
165 | |||
166 | /** | ||
167 | * Task for reconnecting when the listener fails. | ||
168 | */ | ||
169 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
170 | |||
171 | /** | ||
172 | * Async operations. | ||
173 | */ | ||
174 | struct GNUNET_OP_Handle *op; | ||
175 | |||
176 | /** | ||
177 | * Transmission handle. | ||
178 | */ | ||
179 | struct GNUNET_PSYC_TransmitHandle *tmit; | ||
180 | |||
181 | /** | ||
182 | * Slicer for processing incoming messages. | ||
183 | */ | ||
184 | struct GNUNET_PSYC_Slicer *slicer; | ||
185 | |||
186 | // FIXME: do we need is_disconnecing like on the psyc and multicast APIs? | ||
187 | /** | ||
188 | * Function called after disconnected from the service. | ||
189 | */ | ||
190 | GNUNET_ContinuationCallback disconnect_cb; | ||
191 | |||
192 | /** | ||
193 | * Closure for @a disconnect_cb. | ||
194 | */ | ||
195 | void *disconnect_cls; | ||
196 | |||
197 | /** | ||
198 | * Public key of the place. | ||
199 | */ | ||
200 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
201 | |||
202 | /** | ||
203 | * Public key of the ego. | ||
204 | */ | ||
205 | struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; | ||
206 | |||
207 | /** | ||
208 | * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)? | ||
209 | */ | ||
210 | uint8_t is_host; | ||
211 | }; | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Host handle for a place that we entered. | ||
216 | */ | ||
217 | struct GNUNET_SOCIAL_Host | ||
218 | { | ||
219 | struct GNUNET_SOCIAL_Place plc; | ||
220 | |||
221 | /** | ||
222 | * Slicer for processing incoming messages from guests. | ||
223 | */ | ||
224 | struct GNUNET_PSYC_Slicer *slicer; | ||
225 | |||
226 | GNUNET_SOCIAL_HostEnterCallback enter_cb; | ||
227 | |||
228 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb; | ||
229 | |||
230 | GNUNET_SOCIAL_FarewellCallback farewell_cb; | ||
231 | |||
232 | /** | ||
233 | * Closure for callbacks. | ||
234 | */ | ||
235 | void *cb_cls; | ||
236 | |||
237 | struct GNUNET_SOCIAL_Nym *notice_place_leave_nym; | ||
238 | struct GNUNET_PSYC_Environment *notice_place_leave_env; | ||
239 | }; | ||
240 | |||
241 | |||
242 | /** | ||
243 | * Guest handle for place that we entered. | ||
244 | */ | ||
245 | struct GNUNET_SOCIAL_Guest | ||
246 | { | ||
247 | struct GNUNET_SOCIAL_Place plc; | ||
248 | |||
249 | GNUNET_SOCIAL_GuestEnterCallback enter_cb; | ||
250 | |||
251 | GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb; | ||
252 | |||
253 | /** | ||
254 | * Closure for callbacks. | ||
255 | */ | ||
256 | void *cb_cls; | ||
257 | }; | ||
258 | |||
259 | |||
260 | /** | ||
261 | * Hash map of all nyms. | ||
262 | * pub_key_hash -> struct GNUNET_SOCIAL_Nym * | ||
263 | */ | ||
264 | struct GNUNET_CONTAINER_MultiHashMap *nyms; | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Handle for an announcement request. | ||
269 | */ | ||
270 | struct GNUNET_SOCIAL_Announcement | ||
271 | { | ||
272 | |||
273 | }; | ||
274 | |||
275 | |||
276 | /** | ||
277 | * A talk request. | ||
278 | */ | ||
279 | struct GNUNET_SOCIAL_TalkRequest | ||
280 | { | ||
281 | |||
282 | }; | ||
283 | |||
284 | |||
285 | /** | ||
286 | * A history lesson. | ||
287 | */ | ||
288 | struct GNUNET_SOCIAL_HistoryRequest | ||
289 | { | ||
290 | /** | ||
291 | * Place. | ||
292 | */ | ||
293 | struct GNUNET_SOCIAL_Place *plc; | ||
294 | |||
295 | /** | ||
296 | * Operation ID. | ||
297 | */ | ||
298 | uint64_t op_id; | ||
299 | |||
300 | /** | ||
301 | * Slicer for processing incoming messages. | ||
302 | */ | ||
303 | struct GNUNET_PSYC_Slicer *slicer; | ||
304 | |||
305 | /** | ||
306 | * Function to call when the operation finished. | ||
307 | */ | ||
308 | GNUNET_ResultCallback result_cb; | ||
309 | |||
310 | /** | ||
311 | * Closure for @a result_cb. | ||
312 | */ | ||
313 | void *cls; | ||
314 | }; | ||
315 | |||
316 | |||
317 | struct GNUNET_SOCIAL_LookHandle | ||
318 | { | ||
319 | /** | ||
320 | * Place. | ||
321 | */ | ||
322 | struct GNUNET_SOCIAL_Place *plc; | ||
323 | |||
324 | /** | ||
325 | * Operation ID. | ||
326 | */ | ||
327 | uint64_t op_id; | ||
328 | |||
329 | /** | ||
330 | * State variable result callback. | ||
331 | */ | ||
332 | GNUNET_PSYC_StateVarCallback var_cb; | ||
333 | |||
334 | /** | ||
335 | * Function to call when the operation finished. | ||
336 | */ | ||
337 | GNUNET_ResultCallback result_cb; | ||
338 | |||
339 | /** | ||
340 | * Name of current modifier being received. | ||
341 | */ | ||
342 | char *mod_name; | ||
343 | |||
344 | /** | ||
345 | * Size of current modifier value being received. | ||
346 | */ | ||
347 | size_t mod_value_size; | ||
348 | |||
349 | /** | ||
350 | * Remaining size of current modifier value still to be received. | ||
351 | */ | ||
352 | size_t mod_value_remaining; | ||
353 | |||
354 | /** | ||
355 | * Closure for @a result_cb. | ||
356 | */ | ||
357 | void *cls; | ||
358 | }; | ||
359 | |||
360 | |||
361 | struct ZoneAddPlaceHandle | ||
362 | { | ||
363 | GNUNET_ResultCallback result_cb; | ||
364 | void *result_cls; | ||
365 | }; | ||
366 | |||
367 | |||
368 | struct ZoneAddNymHandle | ||
369 | { | ||
370 | GNUNET_ResultCallback result_cb; | ||
371 | void *result_cls; | ||
372 | }; | ||
373 | |||
374 | |||
375 | /*** CLEANUP / DISCONNECT ***/ | ||
376 | |||
377 | |||
378 | static void | ||
379 | host_cleanup (struct GNUNET_SOCIAL_Host *hst) | ||
380 | { | ||
381 | if (NULL != hst->slicer) | ||
382 | { | ||
383 | GNUNET_PSYC_slicer_destroy (hst->slicer); | ||
384 | hst->slicer = NULL; | ||
385 | } | ||
386 | GNUNET_free (hst); | ||
387 | } | ||
388 | |||
389 | |||
390 | static void | ||
391 | guest_cleanup (struct GNUNET_SOCIAL_Guest *gst) | ||
392 | { | ||
393 | GNUNET_free (gst); | ||
394 | } | ||
395 | |||
396 | |||
397 | static void | ||
398 | place_cleanup (struct GNUNET_SOCIAL_Place *plc) | ||
399 | { | ||
400 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
401 | "cleaning up place %p\n", | ||
402 | plc); | ||
403 | if (NULL != plc->tmit) | ||
404 | { | ||
405 | GNUNET_PSYC_transmit_destroy (plc->tmit); | ||
406 | plc->tmit = NULL; | ||
407 | } | ||
408 | if (NULL != plc->connect_env) | ||
409 | { | ||
410 | GNUNET_MQ_discard (plc->connect_env); | ||
411 | plc->connect_env = NULL; | ||
412 | } | ||
413 | if (NULL != plc->mq) | ||
414 | { | ||
415 | GNUNET_MQ_destroy (plc->mq); | ||
416 | plc->mq = NULL; | ||
417 | } | ||
418 | if (NULL != plc->disconnect_cb) | ||
419 | { | ||
420 | plc->disconnect_cb (plc->disconnect_cls); | ||
421 | plc->disconnect_cb = NULL; | ||
422 | } | ||
423 | |||
424 | (GNUNET_YES == plc->is_host) | ||
425 | ? host_cleanup ((struct GNUNET_SOCIAL_Host *) plc) | ||
426 | : guest_cleanup ((struct GNUNET_SOCIAL_Guest *) plc); | ||
427 | } | ||
428 | |||
429 | |||
430 | static void | ||
431 | place_disconnect (struct GNUNET_SOCIAL_Place *plc) | ||
432 | { | ||
433 | place_cleanup (plc); | ||
434 | } | ||
435 | |||
436 | |||
437 | /*** NYM ***/ | ||
438 | |||
439 | static struct GNUNET_SOCIAL_Nym * | ||
440 | nym_get_or_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key) | ||
441 | { | ||
442 | struct GNUNET_SOCIAL_Nym *nym = NULL; | ||
443 | struct GNUNET_HashCode pub_key_hash; | ||
444 | |||
445 | if (NULL == pub_key) | ||
446 | return NULL; | ||
447 | |||
448 | GNUNET_CRYPTO_hash (pub_key, sizeof (*pub_key), &pub_key_hash); | ||
449 | |||
450 | if (NULL == nyms) | ||
451 | nyms = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
452 | else | ||
453 | nym = GNUNET_CONTAINER_multihashmap_get (nyms, &pub_key_hash); | ||
454 | |||
455 | if (NULL == nym) | ||
456 | { | ||
457 | nym = GNUNET_new (struct GNUNET_SOCIAL_Nym); | ||
458 | nym->pub_key = *pub_key; | ||
459 | nym->pub_key_hash = pub_key_hash; | ||
460 | GNUNET_CONTAINER_multihashmap_put (nyms, &nym->pub_key_hash, nym, | ||
461 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
462 | } | ||
463 | return nym; | ||
464 | } | ||
465 | |||
466 | |||
467 | static void | ||
468 | nym_destroy (struct GNUNET_SOCIAL_Nym *nym) | ||
469 | { | ||
470 | GNUNET_CONTAINER_multihashmap_remove (nyms, &nym->pub_key_hash, nym); | ||
471 | GNUNET_free (nym); | ||
472 | } | ||
473 | |||
474 | |||
475 | /*** MESSAGE HANDLERS ***/ | ||
476 | |||
477 | /** _notice_place_leave from guests */ | ||
478 | |||
479 | static void | ||
480 | host_recv_notice_place_leave_method (void *cls, | ||
481 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
482 | const struct GNUNET_PSYC_MessageMethod *meth, | ||
483 | uint64_t message_id, | ||
484 | const char *method_name) | ||
485 | { | ||
486 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
487 | |||
488 | if (0 == memcmp (&(struct GNUNET_CRYPTO_EcdsaPublicKey) {}, | ||
489 | &msg->slave_pub_key, sizeof (msg->slave_pub_key))) | ||
490 | return; | ||
491 | |||
492 | struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&msg->slave_pub_key); | ||
493 | |||
494 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
495 | "Host received method for message ID %" PRIu64 " from nym %s: %s\n", | ||
496 | message_id, GNUNET_h2s (&nym->pub_key_hash), method_name); | ||
497 | |||
498 | hst->notice_place_leave_nym = (struct GNUNET_SOCIAL_Nym *) nym; | ||
499 | hst->notice_place_leave_env = GNUNET_PSYC_env_create (); | ||
500 | |||
501 | char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key); | ||
502 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
503 | "_notice_place_leave: got method from nym %s (%s).\n", | ||
504 | GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str); | ||
505 | GNUNET_free (str); | ||
506 | } | ||
507 | |||
508 | |||
509 | static void | ||
510 | host_recv_notice_place_leave_modifier (void *cls, | ||
511 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
512 | const struct GNUNET_MessageHeader *pmsg, | ||
513 | uint64_t message_id, | ||
514 | enum GNUNET_PSYC_Operator oper, | ||
515 | const char *name, | ||
516 | const void *value, | ||
517 | uint16_t value_size, | ||
518 | uint16_t full_value_size) | ||
519 | { | ||
520 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
521 | if (NULL == hst->notice_place_leave_env) | ||
522 | return; | ||
523 | |||
524 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
525 | "Host received modifier for _notice_place_leave message with ID %" PRIu64 ":\n" | ||
526 | "%c%s: %.*s\n", | ||
527 | message_id, oper, name, value_size, (const char *) value); | ||
528 | |||
529 | /* skip _nym, it's added later in eom() */ | ||
530 | if (0 == memcmp (name, "_nym", sizeof ("_nym")) | ||
531 | || 0 == memcmp (name, "_nym_", sizeof ("_nym_") - 1)) | ||
532 | return; | ||
533 | |||
534 | GNUNET_PSYC_env_add (hst->notice_place_leave_env, | ||
535 | GNUNET_PSYC_OP_SET, name, value, value_size); | ||
536 | } | ||
537 | |||
538 | |||
539 | static void | ||
540 | host_recv_notice_place_leave_eom (void *cls, | ||
541 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
542 | const struct GNUNET_MessageHeader *pmsg, | ||
543 | uint64_t message_id, | ||
544 | uint8_t is_cancelled) | ||
545 | { | ||
546 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
547 | if (NULL == hst->notice_place_leave_env) | ||
548 | return; | ||
549 | |||
550 | char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key); | ||
551 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
552 | "_notice_place_leave: got EOM from nym %s (%s).\n", | ||
553 | GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str); | ||
554 | GNUNET_free (str); | ||
555 | |||
556 | if (GNUNET_YES != is_cancelled) | ||
557 | { | ||
558 | if (NULL != hst->farewell_cb) | ||
559 | hst->farewell_cb (hst->cb_cls, hst->notice_place_leave_nym, | ||
560 | hst->notice_place_leave_env); | ||
561 | /* announce leaving guest to place */ | ||
562 | GNUNET_PSYC_env_add (hst->notice_place_leave_env, GNUNET_PSYC_OP_SET, | ||
563 | "_nym", hst->notice_place_leave_nym, | ||
564 | sizeof (*hst->notice_place_leave_nym)); | ||
565 | GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", | ||
566 | hst->notice_place_leave_env, | ||
567 | NULL, NULL, GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
568 | nym_destroy (hst->notice_place_leave_nym); | ||
569 | } | ||
570 | GNUNET_PSYC_env_destroy (hst->notice_place_leave_env); | ||
571 | hst->notice_place_leave_env = NULL; | ||
572 | } | ||
573 | |||
574 | |||
575 | /*** PLACE ***/ | ||
576 | |||
577 | |||
578 | static int | ||
579 | check_place_result (void *cls, | ||
580 | const struct GNUNET_OperationResultMessage *res) | ||
581 | { | ||
582 | uint16_t size = ntohs (res->header.size); | ||
583 | if (size < sizeof (*res)) | ||
584 | { /* Error, message too small. */ | ||
585 | GNUNET_break (0); | ||
586 | return GNUNET_SYSERR; | ||
587 | } | ||
588 | return GNUNET_OK; | ||
589 | } | ||
590 | |||
591 | |||
592 | static void | ||
593 | handle_place_result (void *cls, | ||
594 | const struct GNUNET_OperationResultMessage *res) | ||
595 | { | ||
596 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
597 | |||
598 | uint16_t size = ntohs (res->header.size); | ||
599 | uint16_t data_size = size - sizeof (*res); | ||
600 | const char *data = (0 < data_size) ? (const char *) &res[1] : NULL; | ||
601 | |||
602 | GNUNET_OP_result (plc->op, GNUNET_ntohll (res->op_id), | ||
603 | GNUNET_ntohll (res->result_code), | ||
604 | data, data_size, NULL); | ||
605 | } | ||
606 | |||
607 | |||
608 | static int | ||
609 | check_app_result (void *cls, | ||
610 | const struct GNUNET_OperationResultMessage *res) | ||
611 | { | ||
612 | uint16_t size = ntohs (res->header.size); | ||
613 | if (size < sizeof (*res)) | ||
614 | { /* Error, message too small. */ | ||
615 | GNUNET_break (0); | ||
616 | return GNUNET_SYSERR; | ||
617 | } | ||
618 | return GNUNET_OK; | ||
619 | } | ||
620 | |||
621 | |||
622 | static void | ||
623 | handle_app_result (void *cls, | ||
624 | const struct GNUNET_OperationResultMessage *res) | ||
625 | { | ||
626 | struct GNUNET_SOCIAL_App *app = cls; | ||
627 | |||
628 | uint16_t size = ntohs (res->header.size); | ||
629 | uint16_t data_size = size - sizeof (*res); | ||
630 | const char *data = (0 < data_size) ? (const char *) &res[1] : NULL; | ||
631 | |||
632 | GNUNET_OP_result (app->op, GNUNET_ntohll (res->op_id), | ||
633 | GNUNET_ntohll (res->result_code), | ||
634 | data, data_size, NULL); | ||
635 | } | ||
636 | |||
637 | |||
638 | static void | ||
639 | op_recv_history_result (void *cls, int64_t result, | ||
640 | const void *err_msg, uint16_t err_msg_size) | ||
641 | { | ||
642 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
643 | "Received history replay result: %" PRId64 ".\n", result); | ||
644 | |||
645 | struct GNUNET_SOCIAL_HistoryRequest *hist = cls; | ||
646 | |||
647 | if (NULL != hist->result_cb) | ||
648 | hist->result_cb (hist->cls, result, err_msg, err_msg_size); | ||
649 | |||
650 | GNUNET_free (hist); | ||
651 | } | ||
652 | |||
653 | |||
654 | static void | ||
655 | op_recv_state_result (void *cls, int64_t result, | ||
656 | const void *err_msg, uint16_t err_msg_size) | ||
657 | { | ||
658 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
659 | "Received state request result: %" PRId64 ".\n", result); | ||
660 | |||
661 | struct GNUNET_SOCIAL_LookHandle *look = cls; | ||
662 | |||
663 | if (NULL != look->result_cb) | ||
664 | look->result_cb (look->cls, result, err_msg, err_msg_size); | ||
665 | |||
666 | GNUNET_free (look); | ||
667 | } | ||
668 | |||
669 | |||
670 | static int | ||
671 | check_place_history_result (void *cls, | ||
672 | const struct GNUNET_OperationResultMessage *res) | ||
673 | { | ||
674 | struct GNUNET_PSYC_MessageHeader * | ||
675 | pmsg = (struct GNUNET_PSYC_MessageHeader *) GNUNET_MQ_extract_nested_mh (res); | ||
676 | uint16_t size = ntohs (res->header.size); | ||
677 | |||
678 | if (NULL == pmsg || size < sizeof (*res) + sizeof (*pmsg)) | ||
679 | { /* Error, message too small. */ | ||
680 | GNUNET_break (0); | ||
681 | return GNUNET_SYSERR; | ||
682 | } | ||
683 | return GNUNET_OK; | ||
684 | } | ||
685 | |||
686 | |||
687 | static void | ||
688 | handle_place_history_result (void *cls, | ||
689 | const struct GNUNET_OperationResultMessage *res) | ||
690 | { | ||
691 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
692 | struct GNUNET_PSYC_MessageHeader * | ||
693 | pmsg = (struct GNUNET_PSYC_MessageHeader *) GNUNET_MQ_extract_nested_mh (res); | ||
694 | |||
695 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
696 | "%p Received historic fragment for message #%" PRIu64 ".\n", | ||
697 | plc, GNUNET_ntohll (pmsg->message_id)); | ||
698 | |||
699 | GNUNET_ResultCallback result_cb = NULL; | ||
700 | struct GNUNET_SOCIAL_HistoryRequest *hist = NULL; | ||
701 | |||
702 | if (GNUNET_YES != GNUNET_OP_get (plc->op, | ||
703 | GNUNET_ntohll (res->op_id), | ||
704 | &result_cb, (void *) &hist, NULL)) | ||
705 | { /* Operation not found. */ | ||
706 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
707 | "%p Replay operation not found for historic fragment of message #%" | ||
708 | PRIu64 ".\n", | ||
709 | plc, GNUNET_ntohll (pmsg->message_id)); | ||
710 | return; | ||
711 | } | ||
712 | |||
713 | GNUNET_PSYC_slicer_message (hist->slicer, | ||
714 | (const struct GNUNET_PSYC_MessageHeader *) pmsg); | ||
715 | } | ||
716 | |||
717 | |||
718 | static int | ||
719 | check_place_state_result (void *cls, | ||
720 | const struct GNUNET_OperationResultMessage *res) | ||
721 | { | ||
722 | const struct GNUNET_MessageHeader *mod = GNUNET_MQ_extract_nested_mh (res); | ||
723 | if (NULL == mod) | ||
724 | { | ||
725 | GNUNET_break_op (0); | ||
726 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
727 | "Invalid modifier in state result\n"); | ||
728 | return GNUNET_SYSERR; | ||
729 | } | ||
730 | |||
731 | uint16_t size = ntohs (res->header.size); | ||
732 | uint16_t mod_size = ntohs (mod->size); | ||
733 | if (size - sizeof (*res) != mod_size) | ||
734 | { | ||
735 | GNUNET_break_op (0); | ||
736 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
737 | "Invalid modifier size in state result: %u - %u != %u\n", | ||
738 | ntohs (res->header.size), sizeof (*res), mod_size); | ||
739 | return GNUNET_SYSERR; | ||
740 | } | ||
741 | return GNUNET_OK; | ||
742 | } | ||
743 | |||
744 | |||
745 | static void | ||
746 | handle_place_state_result (void *cls, | ||
747 | const struct GNUNET_OperationResultMessage *res) | ||
748 | { | ||
749 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
750 | |||
751 | GNUNET_ResultCallback result_cb = NULL; | ||
752 | struct GNUNET_SOCIAL_LookHandle *look = NULL; | ||
753 | |||
754 | if (GNUNET_YES != GNUNET_OP_get (plc->op, | ||
755 | GNUNET_ntohll (res->op_id), | ||
756 | &result_cb, (void *) &look, NULL)) | ||
757 | { /* Operation not found. */ | ||
758 | return; | ||
759 | } | ||
760 | |||
761 | const struct GNUNET_MessageHeader *mod = GNUNET_MQ_extract_nested_mh (res); | ||
762 | uint16_t mod_size = ntohs (mod->size); | ||
763 | |||
764 | switch (ntohs (mod->type)) | ||
765 | { | ||
766 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: | ||
767 | { | ||
768 | const struct GNUNET_PSYC_MessageModifier * | ||
769 | pmod = (const struct GNUNET_PSYC_MessageModifier *) mod; | ||
770 | |||
771 | const char *name = (const char *) &pmod[1]; | ||
772 | uint16_t name_size = ntohs (pmod->name_size); | ||
773 | if (0 == name_size | ||
774 | || mod_size - sizeof (*pmod) < name_size | ||
775 | || '\0' != name[name_size - 1]) | ||
776 | { | ||
777 | GNUNET_break_op (0); | ||
778 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
779 | "Invalid modifier name in state result\n"); | ||
780 | return; | ||
781 | } | ||
782 | look->mod_value_size = ntohs (pmod->value_size); | ||
783 | look->var_cb (look->cls, mod, name, name + name_size, | ||
784 | mod_size - sizeof (*mod) - name_size, | ||
785 | look->mod_value_size); | ||
786 | if (look->mod_value_size > mod_size - sizeof (*mod) - name_size) | ||
787 | { | ||
788 | look->mod_value_remaining = look->mod_value_size; | ||
789 | look->mod_name = GNUNET_malloc (name_size); | ||
790 | GNUNET_memcpy (look->mod_name, name, name_size); | ||
791 | } | ||
792 | break; | ||
793 | } | ||
794 | |||
795 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: | ||
796 | look->var_cb (look->cls, mod, look->mod_name, (const char *) &mod[1], | ||
797 | mod_size - sizeof (*mod), look->mod_value_size); | ||
798 | look->mod_value_remaining -= mod_size - sizeof (*mod); | ||
799 | if (0 == look->mod_value_remaining) | ||
800 | { | ||
801 | GNUNET_free (look->mod_name); | ||
802 | } | ||
803 | break; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | |||
808 | static void | ||
809 | handle_place_message_ack (void *cls, | ||
810 | const struct GNUNET_MessageHeader *msg) | ||
811 | { | ||
812 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
813 | |||
814 | GNUNET_PSYC_transmit_got_ack (plc->tmit); | ||
815 | } | ||
816 | |||
817 | |||
818 | static int | ||
819 | check_place_message (void *cls, | ||
820 | const struct GNUNET_PSYC_MessageHeader *pmsg) | ||
821 | { | ||
822 | return GNUNET_OK; | ||
823 | } | ||
824 | |||
825 | |||
826 | static void | ||
827 | handle_place_message (void *cls, | ||
828 | const struct GNUNET_PSYC_MessageHeader *pmsg) | ||
829 | { | ||
830 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
831 | |||
832 | GNUNET_PSYC_slicer_message (plc->slicer, pmsg); | ||
833 | } | ||
834 | |||
835 | |||
836 | static int | ||
837 | check_host_message (void *cls, | ||
838 | const struct GNUNET_PSYC_MessageHeader *pmsg) | ||
839 | { | ||
840 | return GNUNET_OK; | ||
841 | } | ||
842 | |||
843 | |||
844 | static void | ||
845 | handle_host_message (void *cls, | ||
846 | const struct GNUNET_PSYC_MessageHeader *pmsg) | ||
847 | { | ||
848 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
849 | |||
850 | GNUNET_PSYC_slicer_message (hst->slicer, pmsg); | ||
851 | GNUNET_PSYC_slicer_message (hst->plc.slicer, pmsg); | ||
852 | } | ||
853 | |||
854 | |||
855 | static void | ||
856 | handle_host_enter_ack (void *cls, | ||
857 | const struct HostEnterAck *hack) | ||
858 | { | ||
859 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
860 | |||
861 | hst->plc.pub_key = hack->place_pub_key; | ||
862 | |||
863 | int32_t result = ntohl (hack->result_code); | ||
864 | if (NULL != hst->enter_cb) | ||
865 | hst->enter_cb (hst->cb_cls, result, &hack->place_pub_key, | ||
866 | GNUNET_ntohll (hack->max_message_id)); | ||
867 | } | ||
868 | |||
869 | |||
870 | static int | ||
871 | check_host_enter_request (void *cls, | ||
872 | const struct GNUNET_PSYC_JoinRequestMessage *req) | ||
873 | { | ||
874 | return GNUNET_OK; | ||
875 | } | ||
876 | |||
877 | |||
878 | static void | ||
879 | handle_host_enter_request (void *cls, | ||
880 | const struct GNUNET_PSYC_JoinRequestMessage *req) | ||
881 | { | ||
882 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
883 | |||
884 | if (NULL == hst->answer_door_cb) | ||
885 | return; | ||
886 | |||
887 | const char *method_name = NULL; | ||
888 | struct GNUNET_PSYC_Environment *env = NULL; | ||
889 | struct GNUNET_PSYC_MessageHeader *entry_pmsg = NULL; | ||
890 | const void *data = NULL; | ||
891 | uint16_t data_size = 0; | ||
892 | char *str; | ||
893 | const struct GNUNET_PSYC_Message *join_msg = NULL; | ||
894 | |||
895 | do | ||
896 | { | ||
897 | if (sizeof (*req) + sizeof (*join_msg) <= ntohs (req->header.size)) | ||
898 | { | ||
899 | join_msg = (struct GNUNET_PSYC_Message *) GNUNET_MQ_extract_nested_mh (req); | ||
900 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
901 | "Received join_msg of type %u and size %u.\n", | ||
902 | ntohs (join_msg->header.type), ntohs (join_msg->header.size)); | ||
903 | |||
904 | env = GNUNET_PSYC_env_create (); | ||
905 | entry_pmsg = GNUNET_PSYC_message_header_create_from_psyc (join_msg); | ||
906 | if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_pmsg, &method_name, env, | ||
907 | &data, &data_size)) | ||
908 | { | ||
909 | GNUNET_break_op (0); | ||
910 | str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_pub_key); | ||
911 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
912 | "Ignoring invalid entry request from nym %s.\n", | ||
913 | str); | ||
914 | GNUNET_free (str); | ||
915 | break; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_pub_key); | ||
920 | hst->answer_door_cb (hst->cb_cls, nym, method_name, env, | ||
921 | data, data_size); | ||
922 | } while (0); | ||
923 | |||
924 | if (NULL != env) | ||
925 | GNUNET_PSYC_env_destroy (env); | ||
926 | if (NULL != entry_pmsg) | ||
927 | GNUNET_free (entry_pmsg); | ||
928 | } | ||
929 | |||
930 | |||
931 | static void | ||
932 | handle_guest_enter_ack (void *cls, | ||
933 | const struct GNUNET_PSYC_CountersResultMessage *cres) | ||
934 | { | ||
935 | struct GNUNET_SOCIAL_Guest *gst = cls; | ||
936 | |||
937 | int32_t result = ntohl (cres->result_code); | ||
938 | if (NULL != gst->enter_cb) | ||
939 | gst->enter_cb (gst->cb_cls, result, &gst->plc.pub_key, | ||
940 | GNUNET_ntohll (cres->max_message_id)); | ||
941 | } | ||
942 | |||
943 | |||
944 | static int | ||
945 | check_guest_enter_decision (void *cls, | ||
946 | const struct GNUNET_PSYC_JoinDecisionMessage *dcsn) | ||
947 | { | ||
948 | return GNUNET_OK; | ||
949 | } | ||
950 | |||
951 | |||
952 | static void | ||
953 | handle_guest_enter_decision (void *cls, | ||
954 | const struct GNUNET_PSYC_JoinDecisionMessage *dcsn) | ||
955 | { | ||
956 | struct GNUNET_SOCIAL_Guest *gst = cls; | ||
957 | |||
958 | struct GNUNET_PSYC_Message *pmsg = NULL; | ||
959 | if (ntohs (dcsn->header.size) > sizeof (*dcsn)) | ||
960 | pmsg = (struct GNUNET_PSYC_Message *) GNUNET_MQ_extract_nested_mh (dcsn); | ||
961 | |||
962 | if (NULL != gst->entry_dcsn_cb) | ||
963 | gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg); | ||
964 | } | ||
965 | |||
966 | |||
967 | static int | ||
968 | check_app_ego (void *cls, | ||
969 | const struct AppEgoMessage *emsg) | ||
970 | { | ||
971 | return GNUNET_OK; | ||
972 | } | ||
973 | |||
974 | |||
975 | static void | ||
976 | handle_app_ego (void *cls, | ||
977 | const struct AppEgoMessage *emsg) | ||
978 | { | ||
979 | struct GNUNET_SOCIAL_App *app = cls; | ||
980 | |||
981 | uint16_t name_size = ntohs (emsg->header.size) - sizeof (*emsg); | ||
982 | |||
983 | struct GNUNET_HashCode ego_pub_hash; | ||
984 | GNUNET_CRYPTO_hash (&emsg->ego_pub_key, sizeof (emsg->ego_pub_key), | ||
985 | &ego_pub_hash); | ||
986 | |||
987 | struct GNUNET_SOCIAL_Ego * | ||
988 | ego = GNUNET_CONTAINER_multihashmap_get (app->egos, &ego_pub_hash); | ||
989 | if (NULL == ego) | ||
990 | { | ||
991 | ego = GNUNET_malloc (sizeof (*ego)); | ||
992 | ego->pub_key = emsg->ego_pub_key; | ||
993 | ego->name = GNUNET_malloc (name_size); | ||
994 | GNUNET_memcpy (ego->name, &emsg[1], name_size); | ||
995 | } | ||
996 | else | ||
997 | { | ||
998 | ego->name = GNUNET_realloc (ego->name, name_size); | ||
999 | GNUNET_memcpy (ego->name, &emsg[1], name_size); | ||
1000 | } | ||
1001 | |||
1002 | GNUNET_CONTAINER_multihashmap_put (app->egos, &ego_pub_hash, ego, | ||
1003 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1004 | |||
1005 | if (NULL != app->ego_cb) | ||
1006 | app->ego_cb (app->cb_cls, ego, &ego->pub_key, ego->name); | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | static void | ||
1011 | handle_app_ego_end (void *cls, | ||
1012 | const struct GNUNET_MessageHeader *msg) | ||
1013 | { | ||
1014 | //struct GNUNET_SOCIAL_App *app = cls; | ||
1015 | } | ||
1016 | |||
1017 | |||
1018 | static int | ||
1019 | check_app_place (void *cls, | ||
1020 | const struct AppPlaceMessage *pmsg) | ||
1021 | { | ||
1022 | return GNUNET_OK; | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static void | ||
1027 | handle_app_place (void *cls, | ||
1028 | const struct AppPlaceMessage *pmsg) | ||
1029 | { | ||
1030 | struct GNUNET_SOCIAL_App *app = cls; | ||
1031 | |||
1032 | if ((GNUNET_YES == pmsg->is_host && NULL == app->host_cb) | ||
1033 | || (GNUNET_NO == pmsg->is_host && NULL == app->guest_cb)) | ||
1034 | return; | ||
1035 | |||
1036 | struct GNUNET_HashCode ego_pub_hash; | ||
1037 | GNUNET_CRYPTO_hash (&pmsg->ego_pub_key, sizeof (pmsg->ego_pub_key), | ||
1038 | &ego_pub_hash); | ||
1039 | struct GNUNET_SOCIAL_Ego * | ||
1040 | ego = GNUNET_CONTAINER_multihashmap_get (app->egos, &ego_pub_hash); | ||
1041 | if (NULL == ego) | ||
1042 | { | ||
1043 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failure to obtain ego %s.\n", | ||
1044 | GNUNET_h2s (&ego_pub_hash)); | ||
1045 | GNUNET_break (0); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | if (GNUNET_YES == pmsg->is_host) | ||
1050 | { | ||
1051 | if (NULL != app->host_cb) { | ||
1052 | struct GNUNET_SOCIAL_HostConnection *hconn = GNUNET_malloc (sizeof (*hconn)); | ||
1053 | hconn->app = app; | ||
1054 | hconn->plc_msg = *pmsg; | ||
1055 | app->host_cb (app->cb_cls, hconn, ego, &pmsg->place_pub_key, pmsg->place_state); | ||
1056 | GNUNET_free (hconn); | ||
1057 | } | ||
1058 | } | ||
1059 | else if (NULL != app->guest_cb) | ||
1060 | { | ||
1061 | struct GNUNET_SOCIAL_GuestConnection *gconn = GNUNET_malloc (sizeof (*gconn)); | ||
1062 | gconn->app = app; | ||
1063 | gconn->plc_msg = *pmsg; | ||
1064 | app->guest_cb (app->cb_cls, gconn, ego, &pmsg->place_pub_key, pmsg->place_state); | ||
1065 | GNUNET_free (gconn); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | static void | ||
1071 | handle_app_place_end (void *cls, | ||
1072 | const struct GNUNET_MessageHeader *msg) | ||
1073 | { | ||
1074 | struct GNUNET_SOCIAL_App *app = cls; | ||
1075 | |||
1076 | if (NULL != app->connected_cb) | ||
1077 | app->connected_cb (app->cb_cls); | ||
1078 | } | ||
1079 | |||
1080 | |||
1081 | /** | ||
1082 | * Handler for a #GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK message received | ||
1083 | * from the social service. | ||
1084 | * | ||
1085 | * @param cls the place of type `struct GNUNET_SOCIAL_Place` | ||
1086 | * @param msg the message received from the service | ||
1087 | */ | ||
1088 | static void | ||
1089 | handle_place_leave_ack (void *cls, | ||
1090 | const struct GNUNET_MessageHeader *msg) | ||
1091 | { | ||
1092 | struct GNUNET_SOCIAL_Place *plc = cls; | ||
1093 | |||
1094 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1095 | "%s left place %p\n", | ||
1096 | plc->is_host ? "host" : "guest", | ||
1097 | plc); | ||
1098 | place_disconnect (plc); | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | /*** HOST ***/ | ||
1103 | |||
1104 | |||
1105 | static void | ||
1106 | host_connect (struct GNUNET_SOCIAL_Host *hst); | ||
1107 | |||
1108 | |||
1109 | static void | ||
1110 | host_reconnect (void *cls) | ||
1111 | { | ||
1112 | host_connect (cls); | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /** | ||
1117 | * Host client disconnected from service. | ||
1118 | * | ||
1119 | * Reconnect after backoff period. | ||
1120 | */ | ||
1121 | static void | ||
1122 | host_disconnected (void *cls, enum GNUNET_MQ_Error error) | ||
1123 | { | ||
1124 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
1125 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1126 | |||
1127 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1128 | "Host client disconnected (%d), re-connecting\n", | ||
1129 | (int) error); | ||
1130 | if (NULL != plc->tmit) | ||
1131 | { | ||
1132 | GNUNET_PSYC_transmit_destroy (plc->tmit); | ||
1133 | plc->tmit = NULL; | ||
1134 | } | ||
1135 | if (NULL != plc->mq) | ||
1136 | { | ||
1137 | GNUNET_MQ_destroy (plc->mq); | ||
1138 | plc->mq = NULL; | ||
1139 | } | ||
1140 | |||
1141 | plc->reconnect_task = GNUNET_SCHEDULER_add_delayed (plc->reconnect_delay, | ||
1142 | host_reconnect, | ||
1143 | hst); | ||
1144 | plc->reconnect_delay = GNUNET_TIME_STD_BACKOFF (plc->reconnect_delay); | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | static void | ||
1149 | host_connect (struct GNUNET_SOCIAL_Host *hst) | ||
1150 | { | ||
1151 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1152 | |||
1153 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
1154 | GNUNET_MQ_hd_fixed_size (host_enter_ack, | ||
1155 | GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK, | ||
1156 | struct HostEnterAck, | ||
1157 | hst), | ||
1158 | GNUNET_MQ_hd_fixed_size (place_leave_ack, | ||
1159 | GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK, | ||
1160 | struct GNUNET_MessageHeader, | ||
1161 | plc), | ||
1162 | GNUNET_MQ_hd_var_size (host_enter_request, | ||
1163 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, | ||
1164 | struct GNUNET_PSYC_JoinRequestMessage, | ||
1165 | hst), | ||
1166 | GNUNET_MQ_hd_var_size (host_message, | ||
1167 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, | ||
1168 | struct GNUNET_PSYC_MessageHeader, | ||
1169 | hst), | ||
1170 | GNUNET_MQ_hd_fixed_size (place_message_ack, | ||
1171 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK, | ||
1172 | struct GNUNET_MessageHeader, | ||
1173 | plc), | ||
1174 | GNUNET_MQ_hd_var_size (place_history_result, | ||
1175 | GNUNET_MESSAGE_TYPE_PSYC_HISTORY_RESULT, | ||
1176 | struct GNUNET_OperationResultMessage, | ||
1177 | plc), | ||
1178 | GNUNET_MQ_hd_var_size (place_state_result, | ||
1179 | GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT, | ||
1180 | struct GNUNET_OperationResultMessage, | ||
1181 | plc), | ||
1182 | GNUNET_MQ_hd_var_size (place_result, | ||
1183 | GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE, | ||
1184 | struct GNUNET_OperationResultMessage, | ||
1185 | plc), | ||
1186 | GNUNET_MQ_handler_end () | ||
1187 | }; | ||
1188 | |||
1189 | plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social", | ||
1190 | handlers, host_disconnected, hst); | ||
1191 | GNUNET_assert (NULL != plc->mq); | ||
1192 | plc->tmit = GNUNET_PSYC_transmit_create (plc->mq); | ||
1193 | |||
1194 | GNUNET_MQ_send_copy (plc->mq, plc->connect_env); | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | /** | ||
1199 | * Enter a place as host. | ||
1200 | * | ||
1201 | * A place is created upon first entering, and it is active until permanently | ||
1202 | * left using GNUNET_SOCIAL_host_leave(). | ||
1203 | * | ||
1204 | * @param app | ||
1205 | * Application handle. | ||
1206 | * @param ego | ||
1207 | * Identity of the host. | ||
1208 | * @param policy | ||
1209 | * Policy specifying entry and history restrictions for the place. | ||
1210 | * @param slicer | ||
1211 | * Slicer to handle incoming messages. | ||
1212 | * @param enter_cb | ||
1213 | * Function called when the place is entered and ready to use. | ||
1214 | * @param answer_door_cb | ||
1215 | * Function to handle new nyms that want to enter. | ||
1216 | * @param farewell_cb | ||
1217 | * Function to handle departing nyms. | ||
1218 | * @param cls | ||
1219 | * Closure for the callbacks. | ||
1220 | * | ||
1221 | * @return Handle for the host. This handle contains the pubkey. | ||
1222 | */ | ||
1223 | struct GNUNET_SOCIAL_Host * | ||
1224 | GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, | ||
1225 | const struct GNUNET_SOCIAL_Ego *ego, | ||
1226 | enum GNUNET_PSYC_Policy policy, | ||
1227 | struct GNUNET_PSYC_Slicer *slicer, | ||
1228 | GNUNET_SOCIAL_HostEnterCallback enter_cb, | ||
1229 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, | ||
1230 | GNUNET_SOCIAL_FarewellCallback farewell_cb, | ||
1231 | void *cls) | ||
1232 | { | ||
1233 | struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst)); | ||
1234 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1235 | |||
1236 | plc->cfg = app->cfg; | ||
1237 | plc->is_host = GNUNET_YES; | ||
1238 | plc->slicer = slicer; | ||
1239 | |||
1240 | hst->enter_cb = enter_cb; | ||
1241 | hst->answer_door_cb = answer_door_cb; | ||
1242 | hst->farewell_cb = farewell_cb; | ||
1243 | hst->cb_cls = cls; | ||
1244 | |||
1245 | plc->op = GNUNET_OP_create (); | ||
1246 | |||
1247 | hst->slicer = GNUNET_PSYC_slicer_create (); | ||
1248 | GNUNET_PSYC_slicer_method_add (hst->slicer, "_notice_place_leave", NULL, | ||
1249 | host_recv_notice_place_leave_method, | ||
1250 | host_recv_notice_place_leave_modifier, | ||
1251 | NULL, host_recv_notice_place_leave_eom, hst); | ||
1252 | |||
1253 | uint16_t app_id_size = strlen (app->id) + 1; | ||
1254 | struct HostEnterRequest *hreq; | ||
1255 | plc->connect_env = GNUNET_MQ_msg_extra (hreq, app_id_size, | ||
1256 | GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER); | ||
1257 | hreq->policy = policy; | ||
1258 | hreq->ego_pub_key = ego->pub_key; | ||
1259 | GNUNET_memcpy (&hreq[1], app->id, app_id_size); | ||
1260 | |||
1261 | host_connect (hst); | ||
1262 | return hst; | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | /** | ||
1267 | * Reconnect to an already entered place as host. | ||
1268 | * | ||
1269 | * @param hconn | ||
1270 | * Host connection handle. | ||
1271 | * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppHostPlaceCallback() | ||
1272 | * @param slicer | ||
1273 | * Slicer to handle incoming messages. | ||
1274 | * @param enter_cb | ||
1275 | * Function called when the place is entered and ready to use. | ||
1276 | * @param answer_door_cb | ||
1277 | * Function to handle new nyms that want to enter. | ||
1278 | * @param farewell_cb | ||
1279 | * Function to handle departing nyms. | ||
1280 | * @param cls | ||
1281 | * Closure for the callbacks. | ||
1282 | * | ||
1283 | * @return Handle for the host. | ||
1284 | */ | ||
1285 | struct GNUNET_SOCIAL_Host * | ||
1286 | GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn, | ||
1287 | struct GNUNET_PSYC_Slicer *slicer, | ||
1288 | GNUNET_SOCIAL_HostEnterCallback enter_cb, | ||
1289 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, | ||
1290 | GNUNET_SOCIAL_FarewellCallback farewell_cb, | ||
1291 | void *cls) | ||
1292 | { | ||
1293 | struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst)); | ||
1294 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1295 | |||
1296 | hst->enter_cb = enter_cb; | ||
1297 | hst->answer_door_cb = answer_door_cb; | ||
1298 | hst->farewell_cb = farewell_cb; | ||
1299 | hst->cb_cls = cls; | ||
1300 | |||
1301 | plc->cfg = hconn->app->cfg; | ||
1302 | plc->is_host = GNUNET_YES; | ||
1303 | plc->slicer = slicer; | ||
1304 | plc->pub_key = hconn->plc_msg.place_pub_key; | ||
1305 | plc->ego_pub_key = hconn->plc_msg.ego_pub_key; | ||
1306 | |||
1307 | plc->op = GNUNET_OP_create (); | ||
1308 | |||
1309 | hst->slicer = GNUNET_PSYC_slicer_create (); | ||
1310 | GNUNET_PSYC_slicer_method_add (hst->slicer, "_notice_place_leave", NULL, | ||
1311 | host_recv_notice_place_leave_method, | ||
1312 | host_recv_notice_place_leave_modifier, | ||
1313 | NULL, host_recv_notice_place_leave_eom, hst); | ||
1314 | |||
1315 | size_t app_id_size = strlen (hconn->app->id) + 1; | ||
1316 | struct HostEnterRequest *hreq; | ||
1317 | plc->connect_env = GNUNET_MQ_msg_extra (hreq, app_id_size, | ||
1318 | GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER); | ||
1319 | hreq->place_pub_key = hconn->plc_msg.place_pub_key; | ||
1320 | hreq->ego_pub_key = hconn->plc_msg.ego_pub_key; | ||
1321 | GNUNET_memcpy (&hreq[1], hconn->app->id, app_id_size); | ||
1322 | |||
1323 | host_connect (hst); | ||
1324 | return hst; | ||
1325 | } | ||
1326 | |||
1327 | |||
1328 | /** | ||
1329 | * Decision whether to admit @a nym into the place or refuse entry. | ||
1330 | * | ||
1331 | * @param hst | ||
1332 | * Host of the place. | ||
1333 | * @param nym | ||
1334 | * Handle for the entity that wanted to enter. | ||
1335 | * @param is_admitted | ||
1336 | * #GNUNET_YES if @a nym is admitted, | ||
1337 | * #GNUNET_NO if @a nym is refused entry, | ||
1338 | * #GNUNET_SYSERR if we cannot answer the request. | ||
1339 | * @param method_name | ||
1340 | * Method name for the rejection message. | ||
1341 | * @param env | ||
1342 | * Environment containing variables for the message, or NULL. | ||
1343 | * @param data | ||
1344 | * Data for the rejection message to send back. | ||
1345 | * @param data_size | ||
1346 | * Number of bytes in @a data for method. | ||
1347 | * @return #GNUNET_OK on success, | ||
1348 | * #GNUNET_SYSERR if the message is too large. | ||
1349 | */ | ||
1350 | int | ||
1351 | GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst, | ||
1352 | struct GNUNET_SOCIAL_Nym *nym, | ||
1353 | int is_admitted, | ||
1354 | const struct GNUNET_PSYC_Message *entry_resp) | ||
1355 | { | ||
1356 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1357 | struct GNUNET_PSYC_JoinDecisionMessage *dcsn; | ||
1358 | uint16_t entry_resp_size | ||
1359 | = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0; | ||
1360 | |||
1361 | if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size) | ||
1362 | return GNUNET_SYSERR; | ||
1363 | |||
1364 | struct GNUNET_MQ_Envelope * | ||
1365 | env = GNUNET_MQ_msg_extra (dcsn, entry_resp_size, | ||
1366 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION); | ||
1367 | dcsn->is_admitted = htonl (is_admitted); | ||
1368 | dcsn->slave_pub_key = nym->pub_key; | ||
1369 | |||
1370 | if (0 < entry_resp_size) | ||
1371 | GNUNET_memcpy (&dcsn[1], entry_resp, entry_resp_size); | ||
1372 | |||
1373 | GNUNET_MQ_send (plc->mq, env); | ||
1374 | return GNUNET_OK; | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | /** | ||
1379 | * Throw @a nym out of the place. | ||
1380 | * | ||
1381 | * The @a nym reference will remain valid until the | ||
1382 | * #GNUNET_SOCIAL_FarewellCallback is invoked, | ||
1383 | * which should be very soon after this call. | ||
1384 | * | ||
1385 | * @param host | ||
1386 | * Host of the place. | ||
1387 | * @param nym | ||
1388 | * Handle for the entity to be ejected. | ||
1389 | * @param env | ||
1390 | * Environment for the message or NULL. | ||
1391 | */ | ||
1392 | void | ||
1393 | GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *hst, | ||
1394 | const struct GNUNET_SOCIAL_Nym *nym, | ||
1395 | struct GNUNET_PSYC_Environment *e) | ||
1396 | { | ||
1397 | struct GNUNET_PSYC_Environment *env = e; | ||
1398 | if (NULL == env) | ||
1399 | env = GNUNET_PSYC_env_create (); | ||
1400 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, | ||
1401 | "_nym", &nym->pub_key, sizeof (nym->pub_key)); | ||
1402 | GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", env, NULL, NULL, | ||
1403 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
1404 | if (NULL == e) | ||
1405 | GNUNET_PSYC_env_destroy (env); | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | /** | ||
1410 | * Get the public key of @a ego. | ||
1411 | * | ||
1412 | * @param ego | ||
1413 | * Ego. | ||
1414 | * | ||
1415 | * @return Public key of ego. | ||
1416 | */ | ||
1417 | const struct GNUNET_CRYPTO_EcdsaPublicKey * | ||
1418 | GNUNET_SOCIAL_ego_get_pub_key (const struct GNUNET_SOCIAL_Ego *ego) | ||
1419 | { | ||
1420 | return &ego->pub_key; | ||
1421 | } | ||
1422 | |||
1423 | |||
1424 | /** | ||
1425 | * Get the hash of the public key of @a ego. | ||
1426 | * | ||
1427 | * @param ego | ||
1428 | * Ego. | ||
1429 | * | ||
1430 | * @return Hash of the public key of @a ego. | ||
1431 | */ | ||
1432 | const struct GNUNET_HashCode * | ||
1433 | GNUNET_SOCIAL_ego_get_pub_key_hash (const struct GNUNET_SOCIAL_Ego *ego) | ||
1434 | { | ||
1435 | return &ego->pub_key_hash; | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * Get the name of @a ego. | ||
1441 | * | ||
1442 | * @param ego | ||
1443 | * Ego. | ||
1444 | * | ||
1445 | * @return Public key of @a ego. | ||
1446 | */ | ||
1447 | const char * | ||
1448 | GNUNET_SOCIAL_ego_get_name (const struct GNUNET_SOCIAL_Ego *ego) | ||
1449 | { | ||
1450 | return ego->name; | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * Get the public key of @a nym. | ||
1456 | * | ||
1457 | * Suitable, for example, to be used with GNUNET_SOCIAL_zone_add_nym(). | ||
1458 | * | ||
1459 | * @param nym | ||
1460 | * Pseudonym. | ||
1461 | * | ||
1462 | * @return Public key of @a nym. | ||
1463 | */ | ||
1464 | const struct GNUNET_CRYPTO_EcdsaPublicKey * | ||
1465 | GNUNET_SOCIAL_nym_get_pub_key (const struct GNUNET_SOCIAL_Nym *nym) | ||
1466 | { | ||
1467 | return &nym->pub_key; | ||
1468 | } | ||
1469 | |||
1470 | |||
1471 | /** | ||
1472 | * Get the hash of the public key of @a nym. | ||
1473 | * | ||
1474 | * @param nym | ||
1475 | * Pseudonym. | ||
1476 | * | ||
1477 | * @return Hash of the public key of @a nym. | ||
1478 | */ | ||
1479 | const struct GNUNET_HashCode * | ||
1480 | GNUNET_SOCIAL_nym_get_pub_key_hash (const struct GNUNET_SOCIAL_Nym *nym) | ||
1481 | { | ||
1482 | return &nym->pub_key_hash; | ||
1483 | } | ||
1484 | |||
1485 | |||
1486 | /** | ||
1487 | * Send a message to all nyms that are present in the place. | ||
1488 | * | ||
1489 | * This function is restricted to the host. Nyms can only send requests | ||
1490 | * to the host who can decide to relay it to everyone in the place. | ||
1491 | * | ||
1492 | * @param host Host of the place. | ||
1493 | * @param method_name Method to use for the announcement. | ||
1494 | * @param env Environment containing variables for the message and operations | ||
1495 | * on objects of the place. Can be NULL. | ||
1496 | * @param notify Function to call to get the payload of the announcement. | ||
1497 | * @param notify_cls Closure for @a notify. | ||
1498 | * @param flags Flags for this announcement. | ||
1499 | * | ||
1500 | * @return NULL on error (announcement already in progress?). | ||
1501 | */ | ||
1502 | struct GNUNET_SOCIAL_Announcement * | ||
1503 | GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst, | ||
1504 | const char *method_name, | ||
1505 | const struct GNUNET_PSYC_Environment *env, | ||
1506 | GNUNET_PSYC_TransmitNotifyData notify_data, | ||
1507 | void *notify_data_cls, | ||
1508 | enum GNUNET_SOCIAL_AnnounceFlags flags) | ||
1509 | { | ||
1510 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1511 | "PSYC_transmit_message for host, method: %s\n", | ||
1512 | method_name); | ||
1513 | if (GNUNET_OK == | ||
1514 | GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env, | ||
1515 | NULL, notify_data, notify_data_cls, flags)) | ||
1516 | return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit; | ||
1517 | else | ||
1518 | return NULL; | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | /** | ||
1523 | * Resume transmitting announcement. | ||
1524 | * | ||
1525 | * @param a | ||
1526 | * The announcement to resume. | ||
1527 | */ | ||
1528 | void | ||
1529 | GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a) | ||
1530 | { | ||
1531 | GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a); | ||
1532 | } | ||
1533 | |||
1534 | |||
1535 | /** | ||
1536 | * Cancel announcement. | ||
1537 | * | ||
1538 | * @param a | ||
1539 | * The announcement to cancel. | ||
1540 | */ | ||
1541 | void | ||
1542 | GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a) | ||
1543 | { | ||
1544 | GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a); | ||
1545 | } | ||
1546 | |||
1547 | |||
1548 | /** | ||
1549 | * Obtain handle for a hosted place. | ||
1550 | * | ||
1551 | * The returned handle can be used to access the place API. | ||
1552 | * | ||
1553 | * @param host Handle for the host. | ||
1554 | * | ||
1555 | * @return Handle for the hosted place, valid as long as @a host is valid. | ||
1556 | */ | ||
1557 | struct GNUNET_SOCIAL_Place * | ||
1558 | GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst) | ||
1559 | { | ||
1560 | return &hst->plc; | ||
1561 | } | ||
1562 | |||
1563 | |||
1564 | /** | ||
1565 | * Disconnect from a home. | ||
1566 | * | ||
1567 | * Invalidates host handle. | ||
1568 | * | ||
1569 | * @param hst | ||
1570 | * The host to disconnect. | ||
1571 | */ | ||
1572 | void | ||
1573 | GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst, | ||
1574 | GNUNET_ContinuationCallback disconnect_cb, | ||
1575 | void *cls) | ||
1576 | { | ||
1577 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1578 | |||
1579 | plc->disconnect_cb = disconnect_cb; | ||
1580 | plc->disconnect_cls = cls; | ||
1581 | place_disconnect (plc); | ||
1582 | } | ||
1583 | |||
1584 | |||
1585 | /** | ||
1586 | * Stop hosting the home. | ||
1587 | * | ||
1588 | * Sends a _notice_place_closing announcement to the home. | ||
1589 | * Invalidates host handle. | ||
1590 | * | ||
1591 | * @param hst | ||
1592 | * The host leaving. | ||
1593 | * @param env | ||
1594 | * Environment for the message or NULL. | ||
1595 | * _nym is set to @e nym regardless whether an @e env is provided. | ||
1596 | * @param disconnect_cb | ||
1597 | * Function called after the host left the place | ||
1598 | * and disconnected from the social service. | ||
1599 | * @param cls | ||
1600 | * Closure for @a disconnect_cb. | ||
1601 | */ | ||
1602 | void | ||
1603 | GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst, | ||
1604 | const struct GNUNET_PSYC_Environment *env, | ||
1605 | GNUNET_ContinuationCallback disconnect_cb, | ||
1606 | void *cls) | ||
1607 | { | ||
1608 | struct GNUNET_MQ_Envelope *envelope; | ||
1609 | |||
1610 | GNUNET_SOCIAL_host_announce (hst, "_notice_place_closing", env, NULL, NULL, | ||
1611 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
1612 | hst->plc.disconnect_cb = disconnect_cb; | ||
1613 | hst->plc.disconnect_cls = cls; | ||
1614 | envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE); | ||
1615 | GNUNET_MQ_send (hst->plc.mq, | ||
1616 | envelope); | ||
1617 | } | ||
1618 | |||
1619 | |||
1620 | /*** GUEST ***/ | ||
1621 | |||
1622 | |||
1623 | static void | ||
1624 | guest_connect (struct GNUNET_SOCIAL_Guest *gst); | ||
1625 | |||
1626 | |||
1627 | static void | ||
1628 | guest_reconnect (void *cls) | ||
1629 | { | ||
1630 | guest_connect (cls); | ||
1631 | } | ||
1632 | |||
1633 | |||
1634 | /** | ||
1635 | * Guest client disconnected from service. | ||
1636 | * | ||
1637 | * Reconnect after backoff period. | ||
1638 | */ | ||
1639 | static void | ||
1640 | guest_disconnected (void *cls, enum GNUNET_MQ_Error error) | ||
1641 | { | ||
1642 | struct GNUNET_SOCIAL_Guest *gst = cls; | ||
1643 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1644 | |||
1645 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1646 | "Guest client disconnected (%d), re-connecting\n", | ||
1647 | (int) error); | ||
1648 | if (NULL != plc->tmit) | ||
1649 | { | ||
1650 | GNUNET_PSYC_transmit_destroy (plc->tmit); | ||
1651 | plc->tmit = NULL; | ||
1652 | } | ||
1653 | if (NULL != plc->mq) | ||
1654 | { | ||
1655 | GNUNET_MQ_destroy (plc->mq); | ||
1656 | plc->mq = NULL; | ||
1657 | } | ||
1658 | |||
1659 | plc->reconnect_task = GNUNET_SCHEDULER_add_delayed (plc->reconnect_delay, | ||
1660 | guest_reconnect, | ||
1661 | gst); | ||
1662 | plc->reconnect_delay = GNUNET_TIME_STD_BACKOFF (plc->reconnect_delay); | ||
1663 | } | ||
1664 | |||
1665 | |||
1666 | static void | ||
1667 | guest_connect (struct GNUNET_SOCIAL_Guest *gst) | ||
1668 | { | ||
1669 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1670 | |||
1671 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
1672 | GNUNET_MQ_hd_fixed_size (guest_enter_ack, | ||
1673 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK, | ||
1674 | struct GNUNET_PSYC_CountersResultMessage, | ||
1675 | gst), | ||
1676 | GNUNET_MQ_hd_fixed_size (place_leave_ack, | ||
1677 | GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK, | ||
1678 | struct GNUNET_MessageHeader, | ||
1679 | plc), | ||
1680 | GNUNET_MQ_hd_var_size (guest_enter_decision, | ||
1681 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, | ||
1682 | struct GNUNET_PSYC_JoinDecisionMessage, | ||
1683 | gst), | ||
1684 | GNUNET_MQ_hd_var_size (place_message, | ||
1685 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, | ||
1686 | struct GNUNET_PSYC_MessageHeader, | ||
1687 | plc), | ||
1688 | GNUNET_MQ_hd_fixed_size (place_message_ack, | ||
1689 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK, | ||
1690 | struct GNUNET_MessageHeader, | ||
1691 | plc), | ||
1692 | GNUNET_MQ_hd_var_size (place_history_result, | ||
1693 | GNUNET_MESSAGE_TYPE_PSYC_HISTORY_RESULT, | ||
1694 | struct GNUNET_OperationResultMessage, | ||
1695 | plc), | ||
1696 | GNUNET_MQ_hd_var_size (place_state_result, | ||
1697 | GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT, | ||
1698 | struct GNUNET_OperationResultMessage, | ||
1699 | plc), | ||
1700 | GNUNET_MQ_hd_var_size (place_result, | ||
1701 | GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE, | ||
1702 | struct GNUNET_OperationResultMessage, | ||
1703 | plc), | ||
1704 | GNUNET_MQ_handler_end () | ||
1705 | }; | ||
1706 | |||
1707 | plc->mq = GNUNET_CLIENT_connect (plc->cfg, "social", | ||
1708 | handlers, guest_disconnected, gst); | ||
1709 | GNUNET_assert (NULL != plc->mq); | ||
1710 | plc->tmit = GNUNET_PSYC_transmit_create (plc->mq); | ||
1711 | |||
1712 | GNUNET_MQ_send_copy (plc->mq, plc->connect_env); | ||
1713 | } | ||
1714 | |||
1715 | |||
1716 | static struct GNUNET_MQ_Envelope * | ||
1717 | guest_enter_request_create (const char *app_id, | ||
1718 | const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key, | ||
1719 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
1720 | const struct GNUNET_PeerIdentity *origin, | ||
1721 | size_t relay_count, | ||
1722 | const struct GNUNET_PeerIdentity *relays, | ||
1723 | const struct GNUNET_PSYC_Message *join_msg) | ||
1724 | { | ||
1725 | uint16_t app_id_size = strlen (app_id) + 1; | ||
1726 | uint16_t join_msg_size = ntohs (join_msg->header.size); | ||
1727 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
1728 | |||
1729 | struct GuestEnterRequest *greq; | ||
1730 | struct GNUNET_MQ_Envelope * | ||
1731 | env = GNUNET_MQ_msg_extra (greq, app_id_size + relay_size + join_msg_size, | ||
1732 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER); | ||
1733 | greq->place_pub_key = *place_pub_key; | ||
1734 | greq->ego_pub_key = *ego_pub_key; | ||
1735 | greq->origin = *origin; | ||
1736 | greq->relay_count = htonl (relay_count); | ||
1737 | |||
1738 | char *p = (char *) &greq[1]; | ||
1739 | GNUNET_memcpy (p, app_id, app_id_size); | ||
1740 | p += app_id_size; | ||
1741 | |||
1742 | if (0 < relay_size) | ||
1743 | { | ||
1744 | GNUNET_memcpy (p, relays, relay_size); | ||
1745 | p += relay_size; | ||
1746 | } | ||
1747 | |||
1748 | GNUNET_memcpy (p, join_msg, join_msg_size); | ||
1749 | return env; | ||
1750 | } | ||
1751 | |||
1752 | |||
1753 | /** | ||
1754 | * Request entry to a place as a guest. | ||
1755 | * | ||
1756 | * @param app | ||
1757 | * Application handle. | ||
1758 | * @param ego | ||
1759 | * Identity of the guest. | ||
1760 | * @param place_pub_key | ||
1761 | * Public key of the place to enter. | ||
1762 | * @param flags | ||
1763 | * Flags for the entry. | ||
1764 | * @param origin | ||
1765 | * Peer identity of the origin of the underlying multicast group. | ||
1766 | * @param relay_count | ||
1767 | * Number of elements in the @a relays array. | ||
1768 | * @param relays | ||
1769 | * Relays for the underlying multicast group. | ||
1770 | * @param method_name | ||
1771 | * Method name for the message. | ||
1772 | * @param env | ||
1773 | * Environment containing variables for the message, or NULL. | ||
1774 | * @param data | ||
1775 | * Payload for the message to give to the enter callback. | ||
1776 | * @param data_size | ||
1777 | * Number of bytes in @a data. | ||
1778 | * @param slicer | ||
1779 | * Slicer to use for processing incoming requests from guests. | ||
1780 | * | ||
1781 | * @return NULL on errors, otherwise handle for the guest. | ||
1782 | */ | ||
1783 | struct GNUNET_SOCIAL_Guest * | ||
1784 | GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, | ||
1785 | const struct GNUNET_SOCIAL_Ego *ego, | ||
1786 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
1787 | enum GNUNET_PSYC_SlaveJoinFlags flags, | ||
1788 | const struct GNUNET_PeerIdentity *origin, | ||
1789 | uint32_t relay_count, | ||
1790 | const struct GNUNET_PeerIdentity *relays, | ||
1791 | const struct GNUNET_PSYC_Message *entry_msg, | ||
1792 | struct GNUNET_PSYC_Slicer *slicer, | ||
1793 | GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, | ||
1794 | GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, | ||
1795 | void *cls) | ||
1796 | { | ||
1797 | struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); | ||
1798 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1799 | |||
1800 | plc->ego_pub_key = ego->pub_key; | ||
1801 | plc->pub_key = *place_pub_key; | ||
1802 | plc->cfg = app->cfg; | ||
1803 | plc->is_host = GNUNET_NO; | ||
1804 | plc->slicer = slicer; | ||
1805 | |||
1806 | plc->op = GNUNET_OP_create (); | ||
1807 | |||
1808 | plc->connect_env | ||
1809 | = guest_enter_request_create (app->id, &ego->pub_key, &plc->pub_key, | ||
1810 | origin, relay_count, relays, entry_msg); | ||
1811 | |||
1812 | gst->enter_cb = local_enter_cb; | ||
1813 | gst->entry_dcsn_cb = entry_dcsn_cb; | ||
1814 | gst->cb_cls = cls; | ||
1815 | |||
1816 | guest_connect (gst); | ||
1817 | return gst; | ||
1818 | } | ||
1819 | |||
1820 | |||
1821 | /** | ||
1822 | * Request entry to a place by name as a guest. | ||
1823 | * | ||
1824 | * @param app | ||
1825 | * Application handle. | ||
1826 | * @param ego | ||
1827 | * Identity of the guest. | ||
1828 | * @param gns_name | ||
1829 | * GNS name of the place to enter. Either in the form of | ||
1830 | * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to | ||
1831 | * the 'PLACE' record of the empty label ("+") in the GNS zone with the | ||
1832 | * nym's public key 'NYMPUBKEY', and can be used to request entry to a | ||
1833 | * pseudonym's place directly. | ||
1834 | * @param password | ||
1835 | * Password to decrypt the record, or NULL for cleartext records. | ||
1836 | * @param join_msg | ||
1837 | * Entry request message or NULL. | ||
1838 | * @param slicer | ||
1839 | * Slicer to use for processing incoming requests from guests. | ||
1840 | * @param local_enter_cb | ||
1841 | * Called upon connection established to the social service. | ||
1842 | * @param entry_decision_cb | ||
1843 | * Called upon receiving entry decision. | ||
1844 | * | ||
1845 | * @return NULL on errors, otherwise handle for the guest. | ||
1846 | */ | ||
1847 | struct GNUNET_SOCIAL_Guest * | ||
1848 | GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, | ||
1849 | const struct GNUNET_SOCIAL_Ego *ego, | ||
1850 | const char *gns_name, | ||
1851 | const char *password, | ||
1852 | const struct GNUNET_PSYC_Message *join_msg, | ||
1853 | struct GNUNET_PSYC_Slicer *slicer, | ||
1854 | GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, | ||
1855 | GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb, | ||
1856 | void *cls) | ||
1857 | { | ||
1858 | struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); | ||
1859 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1860 | |||
1861 | if (NULL == password) | ||
1862 | password = ""; | ||
1863 | |||
1864 | uint16_t app_id_size = strlen (app->id) + 1; | ||
1865 | uint16_t gns_name_size = strlen (gns_name) + 1; | ||
1866 | uint16_t password_size = strlen (password) + 1; | ||
1867 | |||
1868 | uint16_t join_msg_size = 0; | ||
1869 | if (NULL != join_msg) | ||
1870 | join_msg_size = ntohs (join_msg->header.size); | ||
1871 | |||
1872 | struct GuestEnterByNameRequest *greq; | ||
1873 | plc->connect_env | ||
1874 | = GNUNET_MQ_msg_extra (greq, app_id_size + gns_name_size | ||
1875 | + password_size + join_msg_size, | ||
1876 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME); | ||
1877 | |||
1878 | greq->ego_pub_key = ego->pub_key; | ||
1879 | |||
1880 | char *p = (char *) &greq[1]; | ||
1881 | GNUNET_memcpy (p, app->id, app_id_size); | ||
1882 | p += app_id_size; | ||
1883 | GNUNET_memcpy (p, gns_name, gns_name_size); | ||
1884 | p += gns_name_size; | ||
1885 | GNUNET_memcpy (p, password, password_size); | ||
1886 | p += password_size; | ||
1887 | if (NULL != join_msg) | ||
1888 | GNUNET_memcpy (p, join_msg, join_msg_size); | ||
1889 | |||
1890 | plc->ego_pub_key = ego->pub_key; | ||
1891 | plc->cfg = app->cfg; | ||
1892 | plc->is_host = GNUNET_NO; | ||
1893 | plc->slicer = slicer; | ||
1894 | |||
1895 | plc->op = GNUNET_OP_create (); | ||
1896 | |||
1897 | gst->enter_cb = local_enter_cb; | ||
1898 | gst->entry_dcsn_cb = entry_decision_cb; | ||
1899 | gst->cb_cls = cls; | ||
1900 | |||
1901 | guest_connect (gst); | ||
1902 | return gst; | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | struct ReconnectContext | ||
1907 | { | ||
1908 | struct GNUNET_SOCIAL_Guest *guest; | ||
1909 | int *result; | ||
1910 | int64_t *max_message_id; | ||
1911 | GNUNET_SOCIAL_GuestEnterCallback enter_cb; | ||
1912 | void *enter_cls; | ||
1913 | }; | ||
1914 | |||
1915 | |||
1916 | static void | ||
1917 | guest_enter_reconnect_cb (void *cls, | ||
1918 | int result, | ||
1919 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
1920 | uint64_t max_message_id) | ||
1921 | { | ||
1922 | struct ReconnectContext *reconnect_ctx = cls; | ||
1923 | |||
1924 | GNUNET_assert (NULL != reconnect_ctx); | ||
1925 | reconnect_ctx->result = GNUNET_new (int); | ||
1926 | *(reconnect_ctx->result) = result; | ||
1927 | reconnect_ctx->max_message_id = GNUNET_new (int64_t); | ||
1928 | *(reconnect_ctx->max_message_id) = max_message_id; | ||
1929 | } | ||
1930 | |||
1931 | |||
1932 | static void | ||
1933 | guest_entry_dcsn_reconnect_cb (void *cls, | ||
1934 | int is_admitted, | ||
1935 | const struct GNUNET_PSYC_Message *entry_resp) | ||
1936 | { | ||
1937 | struct ReconnectContext *reconnect_ctx = cls; | ||
1938 | struct GNUNET_SOCIAL_Guest *gst = reconnect_ctx->guest; | ||
1939 | |||
1940 | GNUNET_assert (NULL != reconnect_ctx); | ||
1941 | GNUNET_assert (NULL != reconnect_ctx->result); | ||
1942 | GNUNET_assert (NULL != reconnect_ctx->max_message_id); | ||
1943 | if (GNUNET_YES != is_admitted) | ||
1944 | { | ||
1945 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1946 | "Guest was rejected after calling " | ||
1947 | "GNUNET_SOCIAL_guest_enter_reconnect ()\n"); | ||
1948 | } | ||
1949 | else if (NULL != reconnect_ctx->enter_cb) | ||
1950 | { | ||
1951 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1952 | "guest reconnected!\n"); | ||
1953 | reconnect_ctx->enter_cb (reconnect_ctx->enter_cls, | ||
1954 | *(reconnect_ctx->result), | ||
1955 | &gst->plc.pub_key, | ||
1956 | *(reconnect_ctx->max_message_id)); | ||
1957 | } | ||
1958 | GNUNET_free (reconnect_ctx->result); | ||
1959 | GNUNET_free (reconnect_ctx->max_message_id); | ||
1960 | GNUNET_free (reconnect_ctx); | ||
1961 | } | ||
1962 | |||
1963 | |||
1964 | /** | ||
1965 | * Reconnect to an already entered place as guest. | ||
1966 | * | ||
1967 | * @param gconn | ||
1968 | * Guest connection handle. | ||
1969 | * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppGuestPlaceCallback() | ||
1970 | * @param flags | ||
1971 | * Flags for the entry. | ||
1972 | * @param slicer | ||
1973 | * Slicer to use for processing incoming requests from guests. | ||
1974 | * @param enter_cb | ||
1975 | * Called upon re-entering is complete. | ||
1976 | * @param entry_decision_cb | ||
1977 | * Called upon receiving entry decision. | ||
1978 | * | ||
1979 | * @return NULL on errors, otherwise handle for the guest. | ||
1980 | */ | ||
1981 | struct GNUNET_SOCIAL_Guest * | ||
1982 | GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn, | ||
1983 | enum GNUNET_PSYC_SlaveJoinFlags flags, | ||
1984 | struct GNUNET_PSYC_Slicer *slicer, | ||
1985 | GNUNET_SOCIAL_GuestEnterCallback enter_cb, | ||
1986 | void *cls) | ||
1987 | { | ||
1988 | struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); | ||
1989 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1990 | struct ReconnectContext *reconnect_ctx; | ||
1991 | |||
1992 | uint16_t app_id_size = strlen (gconn->app->id) + 1; | ||
1993 | struct GuestEnterRequest *greq; | ||
1994 | plc->connect_env | ||
1995 | = GNUNET_MQ_msg_extra (greq, app_id_size, | ||
1996 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER); | ||
1997 | greq->ego_pub_key = gconn->plc_msg.ego_pub_key; | ||
1998 | greq->place_pub_key = gconn->plc_msg.place_pub_key; | ||
1999 | greq->flags = htonl (flags); | ||
2000 | |||
2001 | GNUNET_memcpy (&greq[1], gconn->app->id, app_id_size); | ||
2002 | |||
2003 | plc->cfg = gconn->app->cfg; | ||
2004 | plc->is_host = GNUNET_NO; | ||
2005 | plc->slicer = slicer; | ||
2006 | plc->pub_key = gconn->plc_msg.place_pub_key; | ||
2007 | plc->ego_pub_key = gconn->plc_msg.ego_pub_key; | ||
2008 | |||
2009 | reconnect_ctx = GNUNET_new (struct ReconnectContext); | ||
2010 | reconnect_ctx->guest = gst; | ||
2011 | reconnect_ctx->enter_cb = enter_cb; | ||
2012 | reconnect_ctx->enter_cls = cls; | ||
2013 | |||
2014 | plc->op = GNUNET_OP_create (); | ||
2015 | gst->enter_cb = &guest_enter_reconnect_cb; | ||
2016 | gst->entry_dcsn_cb = &guest_entry_dcsn_reconnect_cb; | ||
2017 | gst->cb_cls = reconnect_ctx; | ||
2018 | |||
2019 | guest_connect (gst); | ||
2020 | return gst; | ||
2021 | } | ||
2022 | |||
2023 | |||
2024 | /** | ||
2025 | * Talk to the host of the place. | ||
2026 | * | ||
2027 | * @param place | ||
2028 | * Place where we want to talk to the host. | ||
2029 | * @param method_name | ||
2030 | * Method to invoke on the host. | ||
2031 | * @param env | ||
2032 | * Environment containing variables for the message, or NULL. | ||
2033 | * @param notify_data | ||
2034 | * Function to use to get the payload for the method. | ||
2035 | * @param notify_data_cls | ||
2036 | * Closure for @a notify_data. | ||
2037 | * @param flags | ||
2038 | * Flags for the message being sent. | ||
2039 | * | ||
2040 | * @return NULL if we are already trying to talk to the host, | ||
2041 | * otherwise handle to cancel the request. | ||
2042 | */ | ||
2043 | struct GNUNET_SOCIAL_TalkRequest * | ||
2044 | GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *gst, | ||
2045 | const char *method_name, | ||
2046 | const struct GNUNET_PSYC_Environment *env, | ||
2047 | GNUNET_PSYC_TransmitNotifyData notify_data, | ||
2048 | void *notify_data_cls, | ||
2049 | enum GNUNET_SOCIAL_TalkFlags flags) | ||
2050 | { | ||
2051 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
2052 | GNUNET_assert (NULL != plc->tmit); | ||
2053 | |||
2054 | if (GNUNET_OK == | ||
2055 | GNUNET_PSYC_transmit_message (plc->tmit, method_name, env, | ||
2056 | NULL, notify_data, notify_data_cls, flags)) | ||
2057 | return (struct GNUNET_SOCIAL_TalkRequest *) plc->tmit; | ||
2058 | else | ||
2059 | return NULL; | ||
2060 | } | ||
2061 | |||
2062 | |||
2063 | /** | ||
2064 | * Resume talking to the host of the place. | ||
2065 | * | ||
2066 | * @param tr | ||
2067 | * Talk request to resume. | ||
2068 | */ | ||
2069 | void | ||
2070 | GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr) | ||
2071 | { | ||
2072 | GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr); | ||
2073 | } | ||
2074 | |||
2075 | |||
2076 | /** | ||
2077 | * Cancel talking to the host of the place. | ||
2078 | * | ||
2079 | * @param tr | ||
2080 | * Talk request to cancel. | ||
2081 | */ | ||
2082 | void | ||
2083 | GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr) | ||
2084 | { | ||
2085 | GNUNET_PSYC_transmit_cancel ( (struct GNUNET_PSYC_TransmitHandle *) tr); | ||
2086 | } | ||
2087 | |||
2088 | |||
2089 | /** | ||
2090 | * Disconnect from a place. | ||
2091 | * | ||
2092 | * Invalidates guest handle. | ||
2093 | * | ||
2094 | * @param gst | ||
2095 | * The guest to disconnect. | ||
2096 | */ | ||
2097 | void | ||
2098 | GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst, | ||
2099 | GNUNET_ContinuationCallback disconnect_cb, | ||
2100 | void *cls) | ||
2101 | { | ||
2102 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
2103 | |||
2104 | plc->disconnect_cb = disconnect_cb; | ||
2105 | plc->disconnect_cls = cls; | ||
2106 | place_disconnect (plc); | ||
2107 | } | ||
2108 | |||
2109 | |||
2110 | /** | ||
2111 | * Leave a place temporarily or permanently. | ||
2112 | * | ||
2113 | * Notifies the owner of the place about leaving, and destroys the place handle. | ||
2114 | * | ||
2115 | * @param place | ||
2116 | * Place to leave. | ||
2117 | * @param keep_active | ||
2118 | * Keep place active after last application disconnected. | ||
2119 | * #GNUNET_YES or #GNUNET_NO | ||
2120 | * @param env | ||
2121 | * Optional environment for the leave message if @a keep_active | ||
2122 | * is #GNUNET_NO. NULL if not needed. | ||
2123 | * @param leave_cb | ||
2124 | * Called upon disconnecting from the social service. | ||
2125 | */ | ||
2126 | void | ||
2127 | GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, | ||
2128 | struct GNUNET_PSYC_Environment *env, | ||
2129 | GNUNET_ContinuationCallback disconnect_cb, | ||
2130 | void *cls) | ||
2131 | { | ||
2132 | struct GNUNET_MQ_Envelope *envelope; | ||
2133 | |||
2134 | GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL, | ||
2135 | GNUNET_SOCIAL_TALK_NONE); | ||
2136 | gst->plc.disconnect_cb = disconnect_cb; | ||
2137 | gst->plc.disconnect_cls = cls; | ||
2138 | envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE); | ||
2139 | GNUNET_MQ_send (gst->plc.mq, | ||
2140 | envelope); | ||
2141 | } | ||
2142 | |||
2143 | |||
2144 | /** | ||
2145 | * Obtain handle for a place entered as guest. | ||
2146 | * | ||
2147 | * The returned handle can be used to access the place API. | ||
2148 | * | ||
2149 | * @param guest Handle for the guest. | ||
2150 | * | ||
2151 | * @return Handle for the place, valid as long as @a guest is valid. | ||
2152 | */ | ||
2153 | struct GNUNET_SOCIAL_Place * | ||
2154 | GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst) | ||
2155 | { | ||
2156 | return &gst->plc; | ||
2157 | } | ||
2158 | |||
2159 | |||
2160 | /** | ||
2161 | * Obtain the public key of a place. | ||
2162 | * | ||
2163 | * @param plc | ||
2164 | * Place. | ||
2165 | * | ||
2166 | * @return Public key of the place. | ||
2167 | */ | ||
2168 | const struct GNUNET_CRYPTO_EddsaPublicKey * | ||
2169 | GNUNET_SOCIAL_place_get_pub_key (const struct GNUNET_SOCIAL_Place *plc) | ||
2170 | { | ||
2171 | return &plc->pub_key; | ||
2172 | } | ||
2173 | |||
2174 | |||
2175 | /** | ||
2176 | * Set message processing @a flags for a @a method_prefix. | ||
2177 | * | ||
2178 | * @param plc | ||
2179 | * Place. | ||
2180 | * @param method_prefix | ||
2181 | * Method prefix @a flags apply to. | ||
2182 | * @param flags | ||
2183 | * The flags that apply to a matching @a method_prefix. | ||
2184 | */ | ||
2185 | void | ||
2186 | GNUNET_SOCIAL_place_msg_proc_set (struct GNUNET_SOCIAL_Place *plc, | ||
2187 | const char *method_prefix, | ||
2188 | enum GNUNET_SOCIAL_MsgProcFlags flags) | ||
2189 | { | ||
2190 | GNUNET_assert (NULL != method_prefix); | ||
2191 | struct MsgProcRequest *mpreq; | ||
2192 | uint16_t method_size = strnlen (method_prefix, | ||
2193 | GNUNET_MAX_MESSAGE_SIZE | ||
2194 | - sizeof (*mpreq)) + 1; | ||
2195 | GNUNET_assert ('\0' == method_prefix[method_size - 1]); | ||
2196 | |||
2197 | struct GNUNET_MQ_Envelope * | ||
2198 | env = GNUNET_MQ_msg_extra (mpreq, method_size, | ||
2199 | GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET); | ||
2200 | mpreq->flags = htonl (flags); | ||
2201 | GNUNET_memcpy (&mpreq[1], method_prefix, method_size); | ||
2202 | |||
2203 | GNUNET_MQ_send (plc->mq, env); | ||
2204 | } | ||
2205 | |||
2206 | |||
2207 | /** | ||
2208 | * Clear all message processing flags previously set for this place. | ||
2209 | */ | ||
2210 | void | ||
2211 | GNUNET_SOCIAL_place_msg_proc_clear (struct GNUNET_SOCIAL_Place *plc) | ||
2212 | { | ||
2213 | struct GNUNET_MessageHeader *req; | ||
2214 | struct GNUNET_MQ_Envelope * | ||
2215 | env = GNUNET_MQ_msg (req, GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR); | ||
2216 | |||
2217 | GNUNET_MQ_send (plc->mq, env); | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | static struct GNUNET_SOCIAL_HistoryRequest * | ||
2222 | place_history_replay (struct GNUNET_SOCIAL_Place *plc, | ||
2223 | uint64_t start_message_id, | ||
2224 | uint64_t end_message_id, | ||
2225 | uint64_t message_limit, | ||
2226 | const char *method_prefix, | ||
2227 | uint32_t flags, | ||
2228 | struct GNUNET_PSYC_Slicer *slicer, | ||
2229 | GNUNET_ResultCallback result_cb, | ||
2230 | void *cls) | ||
2231 | { | ||
2232 | struct GNUNET_PSYC_HistoryRequestMessage *req; | ||
2233 | struct GNUNET_SOCIAL_HistoryRequest *hist = GNUNET_malloc (sizeof (*hist)); | ||
2234 | hist->plc = plc; | ||
2235 | hist->slicer = slicer; | ||
2236 | hist->result_cb = result_cb; | ||
2237 | hist->cls = cls; | ||
2238 | hist->op_id = GNUNET_OP_add (plc->op, op_recv_history_result, hist, NULL); | ||
2239 | |||
2240 | GNUNET_assert (NULL != method_prefix); | ||
2241 | uint16_t method_size = strnlen (method_prefix, | ||
2242 | GNUNET_MAX_MESSAGE_SIZE | ||
2243 | - sizeof (*req)) + 1; | ||
2244 | GNUNET_assert ('\0' == method_prefix[method_size - 1]); | ||
2245 | |||
2246 | struct GNUNET_MQ_Envelope * | ||
2247 | env = GNUNET_MQ_msg_extra (req, method_size, | ||
2248 | GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY); | ||
2249 | req->start_message_id = GNUNET_htonll (start_message_id); | ||
2250 | req->end_message_id = GNUNET_htonll (end_message_id); | ||
2251 | req->message_limit = GNUNET_htonll (message_limit); | ||
2252 | req->flags = htonl (flags); | ||
2253 | req->op_id = GNUNET_htonll (hist->op_id); | ||
2254 | GNUNET_memcpy (&req[1], method_prefix, method_size); | ||
2255 | |||
2256 | GNUNET_MQ_send (plc->mq, env); | ||
2257 | return hist; | ||
2258 | } | ||
2259 | |||
2260 | |||
2261 | /** | ||
2262 | * Learn about the history of a place. | ||
2263 | * | ||
2264 | * Messages are returned through the @a slicer function | ||
2265 | * and have the #GNUNET_PSYC_MESSAGE_HISTORIC flag set. | ||
2266 | * | ||
2267 | * @param place | ||
2268 | * Place we want to learn more about. | ||
2269 | * @param start_message_id | ||
2270 | * First historic message we are interested in. | ||
2271 | * @param end_message_id | ||
2272 | * Last historic message we are interested in (inclusive). | ||
2273 | * @param method_prefix | ||
2274 | * Only retrieve messages with this method prefix. | ||
2275 | * @param flags | ||
2276 | * OR'ed GNUNET_PSYC_HistoryReplayFlags | ||
2277 | * @param slicer | ||
2278 | * Slicer to use for retrieved messages. | ||
2279 | * Can be the same as the slicer of the place. | ||
2280 | * @param result_cb | ||
2281 | * Function called after all messages retrieved. | ||
2282 | * NULL if not needed. | ||
2283 | * @param cls Closure for @a result_cb. | ||
2284 | */ | ||
2285 | struct GNUNET_SOCIAL_HistoryRequest * | ||
2286 | GNUNET_SOCIAL_place_history_replay (struct GNUNET_SOCIAL_Place *plc, | ||
2287 | uint64_t start_message_id, | ||
2288 | uint64_t end_message_id, | ||
2289 | const char *method_prefix, | ||
2290 | uint32_t flags, | ||
2291 | struct GNUNET_PSYC_Slicer *slicer, | ||
2292 | GNUNET_ResultCallback result_cb, | ||
2293 | void *cls) | ||
2294 | { | ||
2295 | return place_history_replay (plc, start_message_id, end_message_id, 0, | ||
2296 | method_prefix, flags, slicer, result_cb, cls); | ||
2297 | } | ||
2298 | |||
2299 | |||
2300 | /** | ||
2301 | * Learn about the history of a place. | ||
2302 | * | ||
2303 | * Sends messages through the slicer function of the place where | ||
2304 | * start_message_id <= message_id <= end_message_id. | ||
2305 | * The messages will have the #GNUNET_PSYC_MESSAGE_HISTORIC flag set. | ||
2306 | * | ||
2307 | * To get the latest message, use 0 for both the start and end message ID. | ||
2308 | * | ||
2309 | * @param place | ||
2310 | * Place we want to learn more about. | ||
2311 | * @param message_limit | ||
2312 | * Maximum number of historic messages we are interested in. | ||
2313 | * @param method_prefix | ||
2314 | * Only retrieve messages with this method prefix. | ||
2315 | * @param flags | ||
2316 | * OR'ed GNUNET_PSYC_HistoryReplayFlags | ||
2317 | * @param result_cb | ||
2318 | * Function called after all messages retrieved. | ||
2319 | * NULL if not needed. | ||
2320 | * @param cls Closure for @a result_cb. | ||
2321 | */ | ||
2322 | struct GNUNET_SOCIAL_HistoryRequest * | ||
2323 | GNUNET_SOCIAL_place_history_replay_latest (struct GNUNET_SOCIAL_Place *plc, | ||
2324 | uint64_t message_limit, | ||
2325 | const char *method_prefix, | ||
2326 | uint32_t flags, | ||
2327 | struct GNUNET_PSYC_Slicer *slicer, | ||
2328 | GNUNET_ResultCallback result_cb, | ||
2329 | void *cls) | ||
2330 | { | ||
2331 | return place_history_replay (plc, 0, 0, message_limit, method_prefix, flags, | ||
2332 | slicer, result_cb, cls); | ||
2333 | } | ||
2334 | |||
2335 | |||
2336 | /** | ||
2337 | * Cancel learning about the history of a place. | ||
2338 | * | ||
2339 | * @param hist | ||
2340 | * History lesson to cancel. | ||
2341 | */ | ||
2342 | void | ||
2343 | GNUNET_SOCIAL_place_history_replay_cancel (struct GNUNET_SOCIAL_HistoryRequest *hist) | ||
2344 | { | ||
2345 | GNUNET_OP_remove (hist->plc->op, hist->op_id); | ||
2346 | GNUNET_free (hist); | ||
2347 | } | ||
2348 | |||
2349 | |||
2350 | /** | ||
2351 | * Request matching state variables. | ||
2352 | */ | ||
2353 | static struct GNUNET_SOCIAL_LookHandle * | ||
2354 | place_state_get (struct GNUNET_SOCIAL_Place *plc, | ||
2355 | uint16_t type, const char *name, | ||
2356 | GNUNET_PSYC_StateVarCallback var_cb, | ||
2357 | GNUNET_ResultCallback result_cb, void *cls) | ||
2358 | { | ||
2359 | struct GNUNET_PSYC_StateRequestMessage *req; | ||
2360 | struct GNUNET_SOCIAL_LookHandle *look = GNUNET_malloc (sizeof (*look)); | ||
2361 | look->plc = plc; | ||
2362 | look->var_cb = var_cb; | ||
2363 | look->result_cb = result_cb; | ||
2364 | look->cls = cls; | ||
2365 | look->op_id = GNUNET_OP_add (plc->op, &op_recv_state_result, look, NULL); | ||
2366 | |||
2367 | GNUNET_assert (NULL != name); | ||
2368 | size_t name_size = strnlen (name, GNUNET_MAX_MESSAGE_SIZE | ||
2369 | - sizeof (*req)) + 1; | ||
2370 | struct GNUNET_MQ_Envelope * | ||
2371 | env = GNUNET_MQ_msg_extra (req, name_size, type); | ||
2372 | req->op_id = GNUNET_htonll (look->op_id); | ||
2373 | GNUNET_memcpy (&req[1], name, name_size); | ||
2374 | |||
2375 | GNUNET_MQ_send (plc->mq, env); | ||
2376 | return look; | ||
2377 | } | ||
2378 | |||
2379 | |||
2380 | /** | ||
2381 | * Look at a particular object in the place. | ||
2382 | * | ||
2383 | * The best matching object is returned (its name might be less specific than | ||
2384 | * what was requested). | ||
2385 | * | ||
2386 | * @param place | ||
2387 | * The place where to look. | ||
2388 | * @param full_name | ||
2389 | * Full name of the object. | ||
2390 | * @param value_size | ||
2391 | * Set to the size of the returned value. | ||
2392 | * | ||
2393 | * @return NULL if there is no such object at this place. | ||
2394 | */ | ||
2395 | struct GNUNET_SOCIAL_LookHandle * | ||
2396 | GNUNET_SOCIAL_place_look_at (struct GNUNET_SOCIAL_Place *plc, | ||
2397 | const char *full_name, | ||
2398 | GNUNET_PSYC_StateVarCallback var_cb, | ||
2399 | GNUNET_ResultCallback result_cb, | ||
2400 | void *cls) | ||
2401 | { | ||
2402 | return place_state_get (plc, GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, | ||
2403 | full_name, var_cb, result_cb, cls); | ||
2404 | } | ||
2405 | |||
2406 | |||
2407 | /** | ||
2408 | * Look for objects in the place with a matching name prefix. | ||
2409 | * | ||
2410 | * @param place | ||
2411 | * The place where to look. | ||
2412 | * @param name_prefix | ||
2413 | * Look at objects with names beginning with this value. | ||
2414 | * @param var_cb | ||
2415 | * Function to call for each object found. | ||
2416 | * @param cls | ||
2417 | * Closure for callback function. | ||
2418 | * | ||
2419 | * @return Handle that can be used to stop looking at objects. | ||
2420 | */ | ||
2421 | struct GNUNET_SOCIAL_LookHandle * | ||
2422 | GNUNET_SOCIAL_place_look_for (struct GNUNET_SOCIAL_Place *plc, | ||
2423 | const char *name_prefix, | ||
2424 | GNUNET_PSYC_StateVarCallback var_cb, | ||
2425 | GNUNET_ResultCallback result_cb, | ||
2426 | void *cls) | ||
2427 | { | ||
2428 | return place_state_get (plc, GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, | ||
2429 | name_prefix, var_cb, result_cb, cls); | ||
2430 | } | ||
2431 | |||
2432 | |||
2433 | /** | ||
2434 | * Cancel a state request operation. | ||
2435 | * | ||
2436 | * @param sr | ||
2437 | * Handle for the operation to cancel. | ||
2438 | */ | ||
2439 | void | ||
2440 | GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *look) | ||
2441 | { | ||
2442 | GNUNET_OP_remove (look->plc->op, look->op_id); | ||
2443 | GNUNET_free (look); | ||
2444 | } | ||
2445 | |||
2446 | |||
2447 | static void | ||
2448 | op_recv_zone_add_place_result (void *cls, int64_t result, | ||
2449 | const void *err_msg, uint16_t err_msg_size) | ||
2450 | { | ||
2451 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2452 | "Received zone add place result: %" PRId64 ".\n", result); | ||
2453 | |||
2454 | struct ZoneAddPlaceHandle *add_plc = cls; | ||
2455 | if (NULL != add_plc->result_cb) | ||
2456 | add_plc->result_cb (add_plc->result_cls, result, err_msg, err_msg_size); | ||
2457 | |||
2458 | GNUNET_free (add_plc); | ||
2459 | } | ||
2460 | |||
2461 | |||
2462 | /** | ||
2463 | * Advertise @e place in the GNS zone of @e ego. | ||
2464 | * | ||
2465 | * @param app | ||
2466 | * Application handle. | ||
2467 | * @param ego | ||
2468 | * Ego. | ||
2469 | * @param place_pub_key | ||
2470 | * Public key of place to add. | ||
2471 | * @param name | ||
2472 | * The name for the PLACE record to put in the zone. | ||
2473 | * @param password | ||
2474 | * Password used to encrypt the record or NULL to keep it cleartext. | ||
2475 | * @param relay_count | ||
2476 | * Number of elements in the @a relays array. | ||
2477 | * @param relays | ||
2478 | * List of relays to put in the PLACE record to advertise | ||
2479 | * as entry points to the place in addition to the origin. | ||
2480 | * @param expiration_time | ||
2481 | * Expiration time of the record, use 0 to remove the record. | ||
2482 | * @param result_cb | ||
2483 | * Function called with the result of the operation. | ||
2484 | * @param result_cls | ||
2485 | * Closure for @a result_cb | ||
2486 | * | ||
2487 | * @return #GNUNET_OK if the request was sent, | ||
2488 | * #GNUNET_SYSERR on error, e.g. the name/password is too long. | ||
2489 | */ | ||
2490 | int | ||
2491 | GNUNET_SOCIAL_zone_add_place (const struct GNUNET_SOCIAL_App *app, | ||
2492 | const struct GNUNET_SOCIAL_Ego *ego, | ||
2493 | const char *name, | ||
2494 | const char *password, | ||
2495 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
2496 | const struct GNUNET_PeerIdentity *origin, | ||
2497 | uint32_t relay_count, | ||
2498 | const struct GNUNET_PeerIdentity *relays, | ||
2499 | struct GNUNET_TIME_Absolute expiration_time, | ||
2500 | GNUNET_ResultCallback result_cb, | ||
2501 | void *result_cls) | ||
2502 | { | ||
2503 | struct ZoneAddPlaceRequest *preq; | ||
2504 | size_t name_size = strlen (name) + 1; | ||
2505 | size_t password_size = strlen (password) + 1; | ||
2506 | size_t relay_size = relay_count * sizeof (*relays); | ||
2507 | size_t payload_size = name_size + password_size + relay_size; | ||
2508 | |||
2509 | if (GNUNET_MAX_MESSAGE_SIZE < sizeof (*preq) + payload_size) | ||
2510 | return GNUNET_SYSERR; | ||
2511 | |||
2512 | struct GNUNET_MQ_Envelope * | ||
2513 | env = GNUNET_MQ_msg_extra (preq, payload_size, | ||
2514 | GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE); | ||
2515 | preq->expiration_time = GNUNET_htonll (expiration_time.abs_value_us); | ||
2516 | preq->ego_pub_key = ego->pub_key; | ||
2517 | preq->place_pub_key = *place_pub_key; | ||
2518 | preq->origin = *origin; | ||
2519 | preq->relay_count = htonl (relay_count); | ||
2520 | |||
2521 | char *p = (char *) &preq[1]; | ||
2522 | GNUNET_memcpy (p, name, name_size); | ||
2523 | p += name_size; | ||
2524 | GNUNET_memcpy (p, password, password_size); | ||
2525 | p += password_size; | ||
2526 | GNUNET_memcpy (p, relays, relay_size); | ||
2527 | |||
2528 | struct ZoneAddPlaceHandle * add_plc = GNUNET_malloc (sizeof (*add_plc)); | ||
2529 | add_plc->result_cb = result_cb; | ||
2530 | add_plc->result_cls = result_cls; | ||
2531 | |||
2532 | preq->op_id = GNUNET_htonll (GNUNET_OP_add (app->op, | ||
2533 | op_recv_zone_add_place_result, | ||
2534 | add_plc, NULL)); | ||
2535 | |||
2536 | GNUNET_MQ_send (app->mq, env); | ||
2537 | return GNUNET_OK; | ||
2538 | } | ||
2539 | |||
2540 | |||
2541 | static void | ||
2542 | op_recv_zone_add_nym_result (void *cls, int64_t result, | ||
2543 | const void *err_msg, uint16_t err_msg_size) | ||
2544 | { | ||
2545 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2546 | "Received zone add nym result: %" PRId64 ".\n", result); | ||
2547 | |||
2548 | struct ZoneAddNymHandle *add_nym = cls; | ||
2549 | if (NULL != add_nym->result_cb) | ||
2550 | add_nym->result_cb (add_nym->result_cls, result, err_msg, err_msg_size); | ||
2551 | |||
2552 | GNUNET_free (add_nym); | ||
2553 | } | ||
2554 | |||
2555 | |||
2556 | /** | ||
2557 | * Add nym to the GNS zone of @e ego. | ||
2558 | * | ||
2559 | * @param cfg | ||
2560 | * Configuration. | ||
2561 | * @param ego | ||
2562 | * Ego. | ||
2563 | * @param name | ||
2564 | * The name for the PKEY record to put in the zone. | ||
2565 | * @param nym_pub_key | ||
2566 | * Public key of nym to add. | ||
2567 | * @param expiration_time | ||
2568 | * Expiration time of the record, use 0 to remove the record. | ||
2569 | * @param result_cb | ||
2570 | * Function called with the result of the operation. | ||
2571 | * @param result_cls | ||
2572 | * Closure for @a result_cb | ||
2573 | * | ||
2574 | * @return #GNUNET_OK if the request was sent, | ||
2575 | * #GNUNET_SYSERR on error, e.g. the name is too long. | ||
2576 | */ | ||
2577 | int | ||
2578 | GNUNET_SOCIAL_zone_add_nym (const struct GNUNET_SOCIAL_App *app, | ||
2579 | const struct GNUNET_SOCIAL_Ego *ego, | ||
2580 | const char *name, | ||
2581 | const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, | ||
2582 | struct GNUNET_TIME_Absolute expiration_time, | ||
2583 | GNUNET_ResultCallback result_cb, | ||
2584 | void *result_cls) | ||
2585 | { | ||
2586 | struct ZoneAddNymRequest *nreq; | ||
2587 | |||
2588 | size_t name_size = strlen (name) + 1; | ||
2589 | if (GNUNET_MAX_MESSAGE_SIZE < sizeof (*nreq) + name_size) | ||
2590 | return GNUNET_SYSERR; | ||
2591 | |||
2592 | struct GNUNET_MQ_Envelope * | ||
2593 | env = GNUNET_MQ_msg_extra (nreq, name_size, | ||
2594 | GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM); | ||
2595 | nreq->expiration_time = GNUNET_htonll (expiration_time.abs_value_us); | ||
2596 | nreq->ego_pub_key = ego->pub_key; | ||
2597 | nreq->nym_pub_key = *nym_pub_key; | ||
2598 | GNUNET_memcpy (&nreq[1], name, name_size); | ||
2599 | |||
2600 | struct ZoneAddNymHandle *add_nym = GNUNET_malloc (sizeof (*add_nym)); | ||
2601 | add_nym->result_cb = result_cb; | ||
2602 | add_nym->result_cls = result_cls; | ||
2603 | |||
2604 | nreq->op_id = GNUNET_htonll (GNUNET_OP_add (app->op, | ||
2605 | op_recv_zone_add_nym_result, | ||
2606 | add_nym, NULL)); | ||
2607 | |||
2608 | GNUNET_MQ_send (app->mq, env); | ||
2609 | return GNUNET_OK; | ||
2610 | } | ||
2611 | |||
2612 | |||
2613 | /*** APP ***/ | ||
2614 | |||
2615 | |||
2616 | static void | ||
2617 | app_connect (struct GNUNET_SOCIAL_App *app); | ||
2618 | |||
2619 | |||
2620 | static void | ||
2621 | app_reconnect (void *cls) | ||
2622 | { | ||
2623 | app_connect (cls); | ||
2624 | } | ||
2625 | |||
2626 | |||
2627 | /** | ||
2628 | * App client disconnected from service. | ||
2629 | * | ||
2630 | * Reconnect after backoff period. | ||
2631 | */ | ||
2632 | static void | ||
2633 | app_disconnected (void *cls, enum GNUNET_MQ_Error error) | ||
2634 | { | ||
2635 | struct GNUNET_SOCIAL_App *app = cls; | ||
2636 | |||
2637 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2638 | "App client disconnected (%d), re-connecting\n", | ||
2639 | (int) error); | ||
2640 | if (NULL != app->mq) | ||
2641 | { | ||
2642 | GNUNET_MQ_destroy (app->mq); | ||
2643 | app->mq = NULL; | ||
2644 | } | ||
2645 | |||
2646 | app->reconnect_task = GNUNET_SCHEDULER_add_delayed (app->reconnect_delay, | ||
2647 | app_reconnect, | ||
2648 | app); | ||
2649 | app->reconnect_delay = GNUNET_TIME_STD_BACKOFF (app->reconnect_delay); | ||
2650 | } | ||
2651 | |||
2652 | |||
2653 | static void | ||
2654 | app_connect (struct GNUNET_SOCIAL_App *app) | ||
2655 | { | ||
2656 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
2657 | GNUNET_MQ_hd_var_size (app_ego, | ||
2658 | GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO, | ||
2659 | struct AppEgoMessage, | ||
2660 | app), | ||
2661 | GNUNET_MQ_hd_fixed_size (app_ego_end, | ||
2662 | GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END, | ||
2663 | struct GNUNET_MessageHeader, | ||
2664 | app), | ||
2665 | GNUNET_MQ_hd_var_size (app_place, | ||
2666 | GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE, | ||
2667 | struct AppPlaceMessage, | ||
2668 | app), | ||
2669 | GNUNET_MQ_hd_fixed_size (app_place_end, | ||
2670 | GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END, | ||
2671 | struct GNUNET_MessageHeader, | ||
2672 | app), | ||
2673 | GNUNET_MQ_hd_var_size (app_result, | ||
2674 | GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE, | ||
2675 | struct GNUNET_OperationResultMessage, | ||
2676 | app), | ||
2677 | GNUNET_MQ_handler_end () | ||
2678 | }; | ||
2679 | |||
2680 | app->mq = GNUNET_CLIENT_connect (app->cfg, "social", | ||
2681 | handlers, app_disconnected, app); | ||
2682 | GNUNET_assert (NULL != app->mq); | ||
2683 | GNUNET_MQ_send_copy (app->mq, app->connect_env); | ||
2684 | } | ||
2685 | |||
2686 | |||
2687 | /** | ||
2688 | * Connect application to the social service. | ||
2689 | * | ||
2690 | * The @host_place_cb and @guest_place_cb functions are | ||
2691 | * initially called for each entered places, | ||
2692 | * then later each time a new place is entered with the current application ID. | ||
2693 | * | ||
2694 | * @param cfg | ||
2695 | * Configuration. | ||
2696 | * @param id | ||
2697 | * Application ID. | ||
2698 | * @param ego_cb | ||
2699 | * Function to notify about an available ego. | ||
2700 | * @param host_cb | ||
2701 | * Function to notify about a place entered as host. | ||
2702 | * @param guest_cb | ||
2703 | * Function to notify about a place entered as guest. | ||
2704 | * @param cls | ||
2705 | * Closure for the callbacks. | ||
2706 | * | ||
2707 | * @return Handle that can be used to stop listening. | ||
2708 | */ | ||
2709 | struct GNUNET_SOCIAL_App * | ||
2710 | GNUNET_SOCIAL_app_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2711 | const char *id, | ||
2712 | GNUNET_SOCIAL_AppEgoCallback ego_cb, | ||
2713 | GNUNET_SOCIAL_AppHostPlaceCallback host_cb, | ||
2714 | GNUNET_SOCIAL_AppGuestPlaceCallback guest_cb, | ||
2715 | GNUNET_SOCIAL_AppConnectedCallback connected_cb, | ||
2716 | void *cls) | ||
2717 | { | ||
2718 | uint16_t app_id_size = strnlen (id, GNUNET_SOCIAL_APP_MAX_ID_SIZE); | ||
2719 | if (GNUNET_SOCIAL_APP_MAX_ID_SIZE == app_id_size) | ||
2720 | return NULL; | ||
2721 | app_id_size++; | ||
2722 | |||
2723 | struct GNUNET_SOCIAL_App *app = GNUNET_malloc (sizeof *app); | ||
2724 | app->cfg = cfg; | ||
2725 | app->ego_cb = ego_cb; | ||
2726 | app->host_cb = host_cb; | ||
2727 | app->guest_cb = guest_cb; | ||
2728 | app->connected_cb = connected_cb; | ||
2729 | app->cb_cls = cls; | ||
2730 | app->egos = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
2731 | app->op = GNUNET_OP_create (); | ||
2732 | app->id = GNUNET_malloc (app_id_size); | ||
2733 | GNUNET_memcpy (app->id, id, app_id_size); | ||
2734 | |||
2735 | struct AppConnectRequest *creq; | ||
2736 | app->connect_env = GNUNET_MQ_msg_extra (creq, app_id_size, | ||
2737 | GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT); | ||
2738 | GNUNET_memcpy (&creq[1], app->id, app_id_size); | ||
2739 | |||
2740 | app_connect (app); | ||
2741 | return app; | ||
2742 | } | ||
2743 | |||
2744 | |||
2745 | static void | ||
2746 | app_cleanup (struct GNUNET_SOCIAL_App *app) | ||
2747 | { | ||
2748 | if (NULL != app->mq) | ||
2749 | { | ||
2750 | GNUNET_MQ_destroy (app->mq); | ||
2751 | app->mq = NULL; | ||
2752 | } | ||
2753 | if (NULL != app->disconnect_cb) | ||
2754 | { | ||
2755 | app->disconnect_cb (app->disconnect_cls); | ||
2756 | app->disconnect_cb = NULL; | ||
2757 | } | ||
2758 | GNUNET_free (app); | ||
2759 | } | ||
2760 | |||
2761 | /** | ||
2762 | * Disconnect application. | ||
2763 | * | ||
2764 | * @param app | ||
2765 | * Application handle. | ||
2766 | * @param disconnect_cb | ||
2767 | * Disconnect callback. | ||
2768 | * @param disconnect_cls | ||
2769 | * Disconnect closure. | ||
2770 | */ | ||
2771 | void | ||
2772 | GNUNET_SOCIAL_app_disconnect (struct GNUNET_SOCIAL_App *app, | ||
2773 | GNUNET_ContinuationCallback disconnect_cb, | ||
2774 | void *disconnect_cls) | ||
2775 | { | ||
2776 | if (NULL == app) return; | ||
2777 | |||
2778 | app->disconnect_cb = disconnect_cb; | ||
2779 | app->disconnect_cls = disconnect_cls; | ||
2780 | |||
2781 | if (NULL != app->mq) | ||
2782 | { | ||
2783 | struct GNUNET_MQ_Envelope *env = GNUNET_MQ_get_last_envelope (app->mq); | ||
2784 | if (NULL != env) | ||
2785 | { | ||
2786 | GNUNET_MQ_notify_sent (env, (GNUNET_SCHEDULER_TaskCallback) app_cleanup, app); | ||
2787 | } | ||
2788 | else | ||
2789 | { | ||
2790 | app_cleanup (app); | ||
2791 | } | ||
2792 | } | ||
2793 | else | ||
2794 | { | ||
2795 | app_cleanup (app); | ||
2796 | } | ||
2797 | } | ||
2798 | |||
2799 | |||
2800 | /** | ||
2801 | * Detach application from a place. | ||
2802 | * | ||
2803 | * Removes the place from the entered places list for this application. | ||
2804 | * Note: this does not disconnect from the place. | ||
2805 | * | ||
2806 | * @see GNUNET_SOCIAL_host_disconnect() and GNUNET_SOCIAL_guest_disconnect() | ||
2807 | * | ||
2808 | * @param app | ||
2809 | * Application. | ||
2810 | * @param plc | ||
2811 | * Place. | ||
2812 | */ | ||
2813 | void | ||
2814 | GNUNET_SOCIAL_app_detach (struct GNUNET_SOCIAL_App *app, | ||
2815 | struct GNUNET_SOCIAL_Place *plc) | ||
2816 | { | ||
2817 | struct AppDetachRequest *dreq; | ||
2818 | struct GNUNET_MQ_Envelope * | ||
2819 | env = GNUNET_MQ_msg (dreq, GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH); | ||
2820 | dreq->place_pub_key = plc->pub_key; | ||
2821 | dreq->ego_pub_key = plc->ego_pub_key; | ||
2822 | |||
2823 | GNUNET_MQ_send (app->mq, env); | ||
2824 | } | ||
2825 | |||
2826 | |||
2827 | /* end of social_api.c */ | ||