diff options
author | Gabor X Toth <*@tg-x.net> | 2014-07-23 16:19:49 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2014-07-23 16:19:49 +0000 |
commit | 3cf8ba0b60f8495892fa76635e9c23555d0a304c (patch) | |
tree | 5f27648bdb3cf3409628e4e5edc26f811cbd03a5 /src/social | |
parent | 252b5599987b7ba03b879a8c2d1c455ad4c9834a (diff) | |
download | gnunet-3cf8ba0b60f8495892fa76635e9c23555d0a304c.tar.gz gnunet-3cf8ba0b60f8495892fa76635e9c23555d0a304c.zip |
social: implement enter/leave/messaging; psyc: improvements and fixes
- social: implement enter/leave, send/receive messages, slicer
- psyc, social: add struct GNUNET_PSYC_Message for single-fragment join messages
- psyc: add message callback in addition to message part callback
- client_manager, social, psyc, multicast: add disconnect callback
Diffstat (limited to 'src/social')
-rw-r--r-- | src/social/Makefile.am | 5 | ||||
-rw-r--r-- | src/social/gnunet-service-social.c | 1219 | ||||
-rw-r--r-- | src/social/social.h | 85 | ||||
-rw-r--r-- | src/social/social_api.c | 1259 | ||||
-rw-r--r-- | src/social/test_social.c | 686 |
5 files changed, 3037 insertions, 217 deletions
diff --git a/src/social/Makefile.am b/src/social/Makefile.am index 04184dbc6..02b1bf823 100644 --- a/src/social/Makefile.am +++ b/src/social/Makefile.am | |||
@@ -24,6 +24,11 @@ libgnunetsocial_la_SOURCES = \ | |||
24 | libgnunetsocial_la_LIBADD = \ | 24 | libgnunetsocial_la_LIBADD = \ |
25 | $(top_builddir)/src/util/libgnunetutil.la \ | 25 | $(top_builddir)/src/util/libgnunetutil.la \ |
26 | $(top_builddir)/src/env/libgnunetenv.la \ | 26 | $(top_builddir)/src/env/libgnunetenv.la \ |
27 | $(top_builddir)/src/psyc/libgnunetpsycutil.la \ | ||
28 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
29 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
30 | $(top_builddir)/src/gns/libgnunetgns.la \ | ||
31 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
27 | $(GN_LIBINTL) $(XLIB) | 32 | $(GN_LIBINTL) $(XLIB) |
28 | libgnunetsocial_la_LDFLAGS = \ | 33 | libgnunetsocial_la_LDFLAGS = \ |
29 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 34 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c index ab67bedd6..90d12200d 100644 --- a/src/social/gnunet-service-social.c +++ b/src/social/gnunet-service-social.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "gnunet_protocols.h" | 32 | #include "gnunet_protocols.h" |
33 | #include "gnunet_statistics_service.h" | 33 | #include "gnunet_statistics_service.h" |
34 | #include "gnunet_psyc_service.h" | 34 | #include "gnunet_psyc_service.h" |
35 | #include "gnunet_psyc_util_lib.h" | ||
35 | #include "gnunet_social_service.h" | 36 | #include "gnunet_social_service.h" |
36 | #include "social.h" | 37 | #include "social.h" |
37 | 38 | ||
@@ -71,41 +72,56 @@ static struct GNUNET_CONTAINER_MultiHashMap *place_guests; | |||
71 | 72 | ||
72 | 73 | ||
73 | /** | 74 | /** |
74 | * Message in the transmission queue. | 75 | * Message fragment transmission queue. |
75 | */ | 76 | */ |
76 | struct TransmitMessage | 77 | struct FragmentTransmitQueue |
77 | { | 78 | { |
78 | struct TransmitMessage *prev; | 79 | struct FragmentTransmitQueue *prev; |
79 | struct TransmitMessage *next; | 80 | struct FragmentTransmitQueue *next; |
80 | 81 | ||
81 | struct GNUNET_SERVER_Client *client; | 82 | struct GNUNET_SERVER_Client *client; |
82 | 83 | ||
83 | /** | 84 | /** |
84 | * ID assigned to the message. | 85 | * Pointer to the next message part inside the data after this struct. |
85 | */ | 86 | */ |
86 | uint64_t id; | 87 | struct GNUNET_MessageHeader *next_part; |
87 | 88 | ||
88 | /** | 89 | /** |
89 | * Size of @a buf | 90 | * Size of message. |
90 | */ | 91 | */ |
91 | uint16_t size; | 92 | uint16_t size; |
92 | 93 | ||
93 | /** | 94 | /** |
94 | * @see enum MessageState | 95 | * @see enum GNUNET_PSYC_MessageState |
95 | */ | 96 | */ |
96 | uint8_t state; | 97 | uint8_t state; |
97 | 98 | ||
98 | /* Followed by message */ | 99 | /* Followed by one or more message parts. */ |
99 | }; | 100 | }; |
100 | 101 | ||
101 | 102 | ||
102 | /** | 103 | /** |
104 | * Message transmission queue. | ||
105 | */ | ||
106 | struct MessageTransmitQueue | ||
107 | { | ||
108 | struct MessageTransmitQueue *prev; | ||
109 | struct MessageTransmitQueue *next; | ||
110 | |||
111 | struct FragmentTransmitQueue *frags_head; | ||
112 | struct FragmentTransmitQueue *frags_tail; | ||
113 | |||
114 | struct GNUNET_SERVER_Client *client; | ||
115 | }; | ||
116 | |||
117 | /** | ||
103 | * List of connected clients. | 118 | * List of connected clients. |
104 | */ | 119 | */ |
105 | struct ClientList | 120 | struct ClientListItem |
106 | { | 121 | { |
107 | struct ClientList *prev; | 122 | struct ClientListItem *prev; |
108 | struct ClientList *next; | 123 | struct ClientListItem *next; |
124 | |||
109 | struct GNUNET_SERVER_Client *client; | 125 | struct GNUNET_SERVER_Client *client; |
110 | }; | 126 | }; |
111 | 127 | ||
@@ -115,11 +131,11 @@ struct ClientList | |||
115 | */ | 131 | */ |
116 | struct Place | 132 | struct Place |
117 | { | 133 | { |
118 | struct ClientList *clients_head; | 134 | struct ClientListItem *clients_head; |
119 | struct ClientList *clients_tail; | 135 | struct ClientListItem *clients_tail; |
120 | 136 | ||
121 | struct TransmitMessage *tmit_head; | 137 | struct MessageTransmitQueue *tmit_msgs_head; |
122 | struct TransmitMessage *tmit_tail; | 138 | struct MessageTransmitQueue *tmit_msgs_tail; |
123 | 139 | ||
124 | /** | 140 | /** |
125 | * Public key of the channel. | 141 | * Public key of the channel. |
@@ -132,9 +148,27 @@ struct Place | |||
132 | struct GNUNET_HashCode pub_key_hash; | 148 | struct GNUNET_HashCode pub_key_hash; |
133 | 149 | ||
134 | /** | 150 | /** |
151 | * Last message ID received for the place. | ||
152 | * 0 if there is no such message. | ||
153 | */ | ||
154 | uint64_t max_message_id; | ||
155 | |||
156 | /** | ||
135 | * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? | 157 | * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? |
136 | */ | 158 | */ |
137 | uint8_t is_host; | 159 | uint8_t is_host; |
160 | |||
161 | /** | ||
162 | * Is this place ready to receive messages from client? | ||
163 | * #GNUNET_YES or #GNUNET_NO | ||
164 | */ | ||
165 | uint8_t is_ready; | ||
166 | |||
167 | /** | ||
168 | * Is the client disconnected? | ||
169 | * #GNUNET_YES or #GNUNET_NO | ||
170 | */ | ||
171 | uint8_t is_disconnected; | ||
138 | }; | 172 | }; |
139 | 173 | ||
140 | 174 | ||
@@ -146,7 +180,7 @@ struct Host | |||
146 | /** | 180 | /** |
147 | * Place struct common for Host and Guest | 181 | * Place struct common for Host and Guest |
148 | */ | 182 | */ |
149 | struct Place pl; | 183 | struct Place plc; |
150 | 184 | ||
151 | /** | 185 | /** |
152 | * Private key of the channel. | 186 | * Private key of the channel. |
@@ -184,17 +218,17 @@ struct Guest | |||
184 | /** | 218 | /** |
185 | * Place struct common for Host and Guest. | 219 | * Place struct common for Host and Guest. |
186 | */ | 220 | */ |
187 | struct Place pl; | 221 | struct Place plc; |
188 | 222 | ||
189 | /** | 223 | /** |
190 | * Private key of the slave. | 224 | * Private key of the slave. |
191 | */ | 225 | */ |
192 | struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; | 226 | struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; |
193 | 227 | ||
194 | /** | 228 | /** |
195 | * Public key of the slave. | 229 | * Public key of the slave. |
196 | */ | 230 | */ |
197 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | 231 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; |
198 | 232 | ||
199 | /** | 233 | /** |
200 | * Hash of @a pub_key. | 234 | * Hash of @a pub_key. |
@@ -230,11 +264,32 @@ struct Guest | |||
230 | * Join request to be transmitted to the master on join. | 264 | * Join request to be transmitted to the master on join. |
231 | */ | 265 | */ |
232 | struct GNUNET_MessageHeader *join_req; | 266 | struct GNUNET_MessageHeader *join_req; |
267 | |||
268 | /** | ||
269 | * Join decision received from PSYC. | ||
270 | */ | ||
271 | struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn; | ||
272 | |||
273 | }; | ||
274 | |||
275 | |||
276 | struct Client | ||
277 | { | ||
278 | /** | ||
279 | * Place where the client entered. | ||
280 | */ | ||
281 | struct Place *plc; | ||
282 | |||
283 | /** | ||
284 | * Message queue for the message currently being transmitted | ||
285 | * by this client. | ||
286 | */ | ||
287 | struct MessageTransmitQueue *tmit_msg; | ||
233 | }; | 288 | }; |
234 | 289 | ||
235 | 290 | ||
236 | static inline void | 291 | static int |
237 | transmit_message (struct Place *pl); | 292 | psyc_transmit_message (struct Place *plc); |
238 | 293 | ||
239 | 294 | ||
240 | /** | 295 | /** |
@@ -265,12 +320,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
265 | static void | 320 | static void |
266 | cleanup_host (struct Host *hst) | 321 | cleanup_host (struct Host *hst) |
267 | { | 322 | { |
268 | struct Place *pl = &hst->pl; | 323 | struct Place *plc = &hst->plc; |
269 | 324 | ||
270 | if (NULL != hst->master) | 325 | if (NULL != hst->master) |
271 | GNUNET_PSYC_master_stop (hst->master); | 326 | GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME |
272 | GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs); | 327 | GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs); |
273 | GNUNET_CONTAINER_multihashmap_remove (hosts, &pl->pub_key_hash, pl); | 328 | GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc); |
274 | } | 329 | } |
275 | 330 | ||
276 | 331 | ||
@@ -280,28 +335,28 @@ cleanup_host (struct Host *hst) | |||
280 | static void | 335 | static void |
281 | cleanup_guest (struct Guest *gst) | 336 | cleanup_guest (struct Guest *gst) |
282 | { | 337 | { |
283 | struct Place *pl = &gst->pl; | 338 | struct Place *plc = &gst->plc; |
284 | struct GNUNET_CONTAINER_MultiHashMap * | 339 | struct GNUNET_CONTAINER_MultiHashMap * |
285 | pl_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, | 340 | plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, |
286 | &pl->pub_key_hash); | 341 | &plc->pub_key_hash); |
287 | GNUNET_assert (NULL != pl_gst); | 342 | GNUNET_assert (NULL != plc_gst); |
288 | GNUNET_CONTAINER_multihashmap_remove (pl_gst, &gst->pub_key_hash, gst); | 343 | GNUNET_CONTAINER_multihashmap_remove (plc_gst, &gst->pub_key_hash, gst); |
289 | 344 | ||
290 | if (0 == GNUNET_CONTAINER_multihashmap_size (pl_gst)) | 345 | if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst)) |
291 | { | 346 | { |
292 | GNUNET_CONTAINER_multihashmap_remove (place_guests, &pl->pub_key_hash, | 347 | GNUNET_CONTAINER_multihashmap_remove (place_guests, &plc->pub_key_hash, |
293 | pl_gst); | 348 | plc_gst); |
294 | GNUNET_CONTAINER_multihashmap_destroy (pl_gst); | 349 | GNUNET_CONTAINER_multihashmap_destroy (plc_gst); |
295 | } | 350 | } |
296 | GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, gst); | 351 | GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, gst); |
297 | 352 | ||
298 | if (NULL != gst->join_req) | 353 | if (NULL != gst->join_req) |
299 | GNUNET_free (gst->join_req); | 354 | GNUNET_free (gst->join_req); |
300 | if (NULL != gst->relays) | 355 | if (NULL != gst->relays) |
301 | GNUNET_free (gst->relays); | 356 | GNUNET_free (gst->relays); |
302 | if (NULL != gst->slave) | 357 | if (NULL != gst->slave) |
303 | GNUNET_PSYC_slave_part (gst->slave); | 358 | GNUNET_PSYC_slave_part (gst->slave, GNUNET_NO, NULL, NULL); // FIXME |
304 | GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, pl); | 359 | GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc); |
305 | } | 360 | } |
306 | 361 | ||
307 | 362 | ||
@@ -309,12 +364,23 @@ cleanup_guest (struct Guest *gst) | |||
309 | * Clean up place data structures after a client disconnected. | 364 | * Clean up place data structures after a client disconnected. |
310 | */ | 365 | */ |
311 | static void | 366 | static void |
312 | cleanup_place (struct Place *pl) | 367 | cleanup_place (struct Place *plc) |
313 | { | 368 | { |
314 | (GNUNET_YES == pl->is_host) | 369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
315 | ? cleanup_host ((struct Host *) pl) | 370 | "%p Cleaning up place %s\n", |
316 | : cleanup_guest ((struct Guest *) pl); | 371 | plc, GNUNET_h2s (&plc->pub_key_hash)); |
317 | GNUNET_free (pl); | 372 | |
373 | (GNUNET_YES == plc->is_host) | ||
374 | ? cleanup_host ((struct Host *) plc) | ||
375 | : cleanup_guest ((struct Guest *) plc); | ||
376 | GNUNET_free (plc); | ||
377 | } | ||
378 | |||
379 | |||
380 | static void | ||
381 | schedule_cleanup_place (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
382 | { | ||
383 | cleanup_place (cls); | ||
318 | } | 384 | } |
319 | 385 | ||
320 | 386 | ||
@@ -331,76 +397,1073 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
331 | if (NULL == client) | 397 | if (NULL == client) |
332 | return; | 398 | return; |
333 | 399 | ||
334 | struct Place * | 400 | struct Client * |
335 | pl = GNUNET_SERVER_client_get_user_context (client, struct Place); | 401 | ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); |
336 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 402 | if (NULL == ctx) |
337 | "%p Client (%s) disconnected from place %s\n", | ||
338 | pl, (GNUNET_YES == pl->is_host) ? "host" : "guest", | ||
339 | GNUNET_h2s (&pl->pub_key_hash)); | ||
340 | |||
341 | if (NULL == pl) | ||
342 | { | 403 | { |
343 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 404 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
344 | "%p User context is NULL in client_disconnect()\n", pl); | 405 | "%p User context is NULL in client_disconnect()\n", ctx); |
345 | GNUNET_break (0); | 406 | GNUNET_break (0); |
346 | return; | 407 | return; |
347 | } | 408 | } |
348 | 409 | ||
349 | struct ClientList *cl = pl->clients_head; | 410 | struct Place *plc = ctx->plc; |
350 | while (NULL != cl) | 411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
412 | "%p Client (%s) disconnected from place %s\n", | ||
413 | plc, (GNUNET_YES == plc->is_host) ? "host" : "guest", | ||
414 | GNUNET_h2s (&plc->pub_key_hash)); | ||
415 | |||
416 | struct ClientListItem *cli = plc->clients_head; | ||
417 | while (NULL != cli) | ||
351 | { | 418 | { |
352 | if (cl->client == client) | 419 | if (cli->client == client) |
353 | { | 420 | { |
354 | GNUNET_CONTAINER_DLL_remove (pl->clients_head, pl->clients_tail, cl); | 421 | GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli); |
355 | GNUNET_free (cl); | 422 | GNUNET_free (cli); |
356 | break; | 423 | break; |
357 | } | 424 | } |
358 | cl = cl->next; | 425 | cli = cli->next; |
359 | } | 426 | } |
360 | 427 | ||
361 | if (NULL == pl->clients_head) | 428 | if (NULL == plc->clients_head) |
362 | { /* Last client disconnected. */ | 429 | { /* Last client disconnected. */ |
363 | if (NULL != pl->tmit_head) | 430 | if (GNUNET_YES != plc->is_disconnected) |
364 | { /* Send pending messages to PSYC before cleanup. */ | 431 | { |
365 | //FIXME: transmit_message (pl); | 432 | plc->is_disconnected = GNUNET_YES; |
433 | if (NULL != plc->tmit_msgs_head) | ||
434 | { /* Send pending messages to PSYC before cleanup. */ | ||
435 | psyc_transmit_message (plc); | ||
436 | } | ||
437 | else | ||
438 | { | ||
439 | cleanup_place (plc); | ||
440 | } | ||
366 | } | 441 | } |
367 | else | 442 | } |
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Send message to all clients connected to the channel. | ||
448 | */ | ||
449 | static void | ||
450 | client_send_msg (const struct Place *plc, | ||
451 | const struct GNUNET_MessageHeader *msg) | ||
452 | { | ||
453 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
454 | "%p Sending message to clients.\n", plc); | ||
455 | |||
456 | struct ClientListItem *cli = plc->clients_head; | ||
457 | while (NULL != cli) | ||
458 | { | ||
459 | GNUNET_SERVER_notification_context_add (nc, cli->client); | ||
460 | GNUNET_SERVER_notification_context_unicast (nc, cli->client, msg, GNUNET_NO); | ||
461 | cli = cli->next; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | |||
466 | /** | ||
467 | * Called after a PSYC master is started. | ||
468 | */ | ||
469 | static void | ||
470 | psyc_master_started (void *cls, uint64_t max_message_id) | ||
471 | { | ||
472 | struct Host *hst = cls; | ||
473 | struct Place *plc = &hst->plc; | ||
474 | plc->max_message_id = max_message_id; | ||
475 | plc->is_ready = GNUNET_YES; | ||
476 | |||
477 | struct CountersResult res; | ||
478 | res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); | ||
479 | res.header.size = htons (sizeof (res)); | ||
480 | res.result_code = htonl (GNUNET_OK); | ||
481 | res.max_message_id = GNUNET_htonll (plc->max_message_id); | ||
482 | |||
483 | client_send_msg (plc, &res.header); | ||
484 | } | ||
485 | |||
486 | |||
487 | /** | ||
488 | * Called when a PSYC master receives a join request. | ||
489 | */ | ||
490 | static void | ||
491 | psyc_recv_join_request (void *cls, | ||
492 | const struct GNUNET_PSYC_JoinRequestMessage *req, | ||
493 | const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, | ||
494 | const struct GNUNET_PSYC_Message *join_msg, | ||
495 | struct GNUNET_PSYC_JoinHandle *jh) | ||
496 | { | ||
497 | struct Host *hst = cls; | ||
498 | struct GNUNET_HashCode slave_key_hash; | ||
499 | GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash); | ||
500 | GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh, | ||
501 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
502 | client_send_msg (&hst->plc, &req->header); | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Called after a PSYC slave is connected. | ||
508 | */ | ||
509 | static void | ||
510 | psyc_slave_connected (void *cls, uint64_t max_message_id) | ||
511 | { | ||
512 | struct Guest *gst = cls; | ||
513 | struct Place *plc = &gst->plc; | ||
514 | plc->max_message_id = max_message_id; | ||
515 | plc->is_ready = GNUNET_YES; | ||
516 | |||
517 | struct CountersResult res; | ||
518 | res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); | ||
519 | res.header.size = htons (sizeof (res)); | ||
520 | res.result_code = htonl (GNUNET_OK); | ||
521 | res.max_message_id = GNUNET_htonll (plc->max_message_id); | ||
522 | |||
523 | client_send_msg (plc, &res.header); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Called when a PSYC slave receives a join decision. | ||
529 | */ | ||
530 | static void | ||
531 | psyc_recv_join_dcsn (void *cls, | ||
532 | const struct GNUNET_PSYC_JoinDecisionMessage *dcsn, | ||
533 | int is_admitted, | ||
534 | const struct GNUNET_PSYC_Message *join_msg) | ||
535 | { | ||
536 | struct Guest *gst = cls; | ||
537 | client_send_msg (&gst->plc, &dcsn->header); | ||
538 | } | ||
539 | |||
540 | |||
541 | /** | ||
542 | * Called when a PSYC master or slave receives a message. | ||
543 | */ | ||
544 | static void | ||
545 | psyc_recv_message (void *cls, | ||
546 | uint64_t message_id, | ||
547 | uint32_t flags, | ||
548 | const struct GNUNET_PSYC_MessageHeader *msg) | ||
549 | { | ||
550 | struct Place *plc = cls; | ||
551 | client_send_msg (plc, &msg->header); | ||
552 | |||
553 | /* FIXME: further processing */ | ||
554 | } | ||
555 | |||
556 | |||
557 | /** | ||
558 | * Initialize place data structure. | ||
559 | */ | ||
560 | static void | ||
561 | place_init (struct Place *plc) | ||
562 | { | ||
563 | |||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * Handle a connecting client entering a place as host. | ||
569 | */ | ||
570 | static void | ||
571 | client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client, | ||
572 | const struct GNUNET_MessageHeader *msg) | ||
573 | { | ||
574 | const struct HostEnterRequest *req | ||
575 | = (const struct HostEnterRequest *) msg; | ||
576 | |||
577 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
578 | struct GNUNET_HashCode pub_key_hash; | ||
579 | |||
580 | GNUNET_CRYPTO_eddsa_key_get_public (&req->place_key, &pub_key); | ||
581 | GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash); | ||
582 | |||
583 | struct Host * | ||
584 | hst = GNUNET_CONTAINER_multihashmap_get (hosts, &pub_key_hash); | ||
585 | struct Place *plc; | ||
586 | |||
587 | if (NULL == hst) | ||
588 | { | ||
589 | hst = GNUNET_new (struct Host); | ||
590 | hst->policy = ntohl (req->policy); | ||
591 | hst->priv_key = req->place_key; | ||
592 | hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
593 | |||
594 | plc = &hst->plc; | ||
595 | plc->is_host = GNUNET_YES; | ||
596 | plc->pub_key = pub_key; | ||
597 | plc->pub_key_hash = pub_key_hash; | ||
598 | place_init (plc); | ||
599 | |||
600 | GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc, | ||
601 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
602 | hst->master = GNUNET_PSYC_master_start (cfg, &hst->priv_key, hst->policy, | ||
603 | &psyc_master_started, | ||
604 | &psyc_recv_join_request, | ||
605 | &psyc_recv_message, NULL, hst); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | plc = &hst->plc; | ||
610 | |||
611 | struct CountersResult res; | ||
612 | res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); | ||
613 | res.header.size = htons (sizeof (res)); | ||
614 | res.result_code = htonl (GNUNET_OK); | ||
615 | res.max_message_id = GNUNET_htonll (plc->max_message_id); | ||
616 | |||
617 | GNUNET_SERVER_notification_context_add (nc, client); | ||
618 | GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, | ||
619 | GNUNET_NO); | ||
620 | } | ||
621 | |||
622 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
623 | "%p Client connected as host to place %s.\n", | ||
624 | hst, GNUNET_h2s (&plc->pub_key_hash)); | ||
625 | |||
626 | struct ClientListItem *cli = GNUNET_new (struct ClientListItem); | ||
627 | cli->client = client; | ||
628 | GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli); | ||
629 | |||
630 | struct Client *ctx = GNUNET_new (struct Client); | ||
631 | ctx->plc = plc; | ||
632 | GNUNET_SERVER_client_set_user_context (client, ctx); | ||
633 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Handle a connecting client entering a place as guest. | ||
639 | */ | ||
640 | static void | ||
641 | client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client, | ||
642 | const struct GNUNET_MessageHeader *msg) | ||
643 | { | ||
644 | const struct GuestEnterRequest *req | ||
645 | = (const struct GuestEnterRequest *) msg; | ||
646 | uint16_t req_size = ntohs (req->header.size); | ||
647 | |||
648 | struct GNUNET_CRYPTO_EcdsaPublicKey gst_pub_key; | ||
649 | struct GNUNET_HashCode pub_key_hash, gst_pub_key_hash; | ||
650 | |||
651 | GNUNET_CRYPTO_ecdsa_key_get_public (&req->guest_key, &gst_pub_key); | ||
652 | GNUNET_CRYPTO_hash (&gst_pub_key, sizeof (gst_pub_key), &gst_pub_key_hash); | ||
653 | GNUNET_CRYPTO_hash (&req->place_key, sizeof (req->place_key), &pub_key_hash); | ||
654 | |||
655 | struct GNUNET_CONTAINER_MultiHashMap * | ||
656 | plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &pub_key_hash); | ||
657 | struct Guest *gst = NULL; | ||
658 | struct Place *plc; | ||
659 | |||
660 | if (NULL != plc_gst) | ||
661 | { | ||
662 | gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &gst_pub_key_hash); | ||
663 | } | ||
664 | if (NULL == gst || NULL == gst->slave) | ||
665 | { | ||
666 | gst = GNUNET_new (struct Guest); | ||
667 | gst->priv_key = req->guest_key; | ||
668 | gst->pub_key = gst_pub_key; | ||
669 | gst->pub_key_hash = gst_pub_key_hash; | ||
670 | gst->origin = req->origin; | ||
671 | gst->relay_count = ntohl (req->relay_count); | ||
672 | |||
673 | const struct GNUNET_PeerIdentity * | ||
674 | relays = (const struct GNUNET_PeerIdentity *) &req[1]; | ||
675 | uint16_t relay_size = gst->relay_count * sizeof (*relays); | ||
676 | struct GNUNET_PSYC_Message *join_msg = NULL; | ||
677 | uint16_t join_msg_size = 0; | ||
678 | |||
679 | if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader) | ||
680 | <= req_size) | ||
681 | { | ||
682 | join_msg = (struct GNUNET_PSYC_Message *) | ||
683 | (((char *) &req[1]) + relay_size); | ||
684 | join_msg_size = ntohs (join_msg->header.size); | ||
685 | } | ||
686 | if (sizeof (*req) + relay_size + join_msg_size != req_size) | ||
687 | { | ||
688 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
689 | "%u + %u + %u != %u\n", | ||
690 | sizeof (*req), relay_size, join_msg_size, req_size); | ||
691 | GNUNET_break (0); | ||
692 | GNUNET_SERVER_client_disconnect (client); | ||
693 | return; | ||
694 | } | ||
695 | if (0 < gst->relay_count) | ||
696 | { | ||
697 | gst->relays = GNUNET_malloc (relay_size); | ||
698 | memcpy (gst->relays, &req[1], relay_size); | ||
699 | } | ||
700 | |||
701 | plc = &gst->plc; | ||
702 | plc->is_host = GNUNET_NO; | ||
703 | plc->pub_key = req->place_key; | ||
704 | plc->pub_key_hash = pub_key_hash; | ||
705 | place_init (plc); | ||
706 | |||
707 | if (NULL == plc_gst) | ||
708 | { | ||
709 | plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
710 | GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst, | ||
711 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
712 | } | ||
713 | GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, plc, | ||
714 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
715 | GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, plc, | ||
716 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
717 | gst->slave | ||
718 | = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key, | ||
719 | &gst->origin, gst->relay_count, gst->relays, | ||
720 | &psyc_recv_message, NULL, &psyc_slave_connected, | ||
721 | &psyc_recv_join_dcsn, gst, join_msg); | ||
722 | } | ||
723 | else | ||
724 | { | ||
725 | plc = &gst->plc; | ||
726 | |||
727 | struct CountersResult res; | ||
728 | res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); | ||
729 | res.header.size = htons (sizeof (res)); | ||
730 | res.result_code = htonl (GNUNET_OK); | ||
731 | res.max_message_id = GNUNET_htonll (plc->max_message_id); | ||
732 | |||
733 | GNUNET_SERVER_notification_context_add (nc, client); | ||
734 | GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, | ||
735 | GNUNET_NO); | ||
736 | if (NULL != gst->join_dcsn) | ||
368 | { | 737 | { |
369 | cleanup_place (pl); | 738 | GNUNET_SERVER_notification_context_add (nc, client); |
739 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
740 | &gst->join_dcsn->header, | ||
741 | GNUNET_NO); | ||
370 | } | 742 | } |
371 | } | 743 | } |
744 | |||
745 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
746 | "%p Client connected as guest to place %s.\n", | ||
747 | gst, GNUNET_h2s (&plc->pub_key_hash)); | ||
748 | |||
749 | struct ClientListItem *cli = GNUNET_new (struct ClientListItem); | ||
750 | cli->client = client; | ||
751 | GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli); | ||
752 | |||
753 | struct Client *ctx = GNUNET_new (struct Client); | ||
754 | ctx->plc = plc; | ||
755 | GNUNET_SERVER_client_set_user_context (client, ctx); | ||
756 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
372 | } | 757 | } |
373 | 758 | ||
374 | 759 | ||
760 | struct JoinDecisionClosure | ||
761 | { | ||
762 | int32_t is_admitted; | ||
763 | struct GNUNET_PSYC_Message *msg; | ||
764 | }; | ||
765 | |||
766 | |||
767 | /** | ||
768 | * Iterator callback for responding to join requests. | ||
769 | */ | ||
770 | static int | ||
771 | psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash, | ||
772 | void *value) | ||
773 | { | ||
774 | struct JoinDecisionClosure *jcls = cls; | ||
775 | struct GNUNET_PSYC_JoinHandle *jh = value; | ||
776 | // FIXME: add relays | ||
777 | GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg); | ||
778 | return GNUNET_YES; | ||
779 | } | ||
780 | |||
781 | |||
782 | /** | ||
783 | * Handle an entry decision from a host client. | ||
784 | */ | ||
375 | static void | 785 | static void |
376 | client_home_enter (void *cls, struct GNUNET_SERVER_Client *client, | 786 | client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client, |
377 | const struct GNUNET_MessageHeader *msg) | 787 | const struct GNUNET_MessageHeader *msg) |
378 | { | 788 | { |
789 | struct Client * | ||
790 | ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); | ||
791 | GNUNET_assert (NULL != ctx); | ||
792 | struct Place *plc = ctx->plc; | ||
793 | GNUNET_assert (GNUNET_YES == plc->is_host); | ||
794 | struct Host *hst = (struct Host *) plc; | ||
795 | |||
796 | struct GNUNET_PSYC_JoinDecisionMessage * | ||
797 | dcsn = (struct GNUNET_PSYC_JoinDecisionMessage *) msg; | ||
798 | struct JoinDecisionClosure jcls; | ||
799 | jcls.is_admitted = ntohl (dcsn->is_admitted); | ||
800 | jcls.msg | ||
801 | = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (msg->size)) | ||
802 | ? (struct GNUNET_PSYC_Message *) &dcsn[1] | ||
803 | : NULL; | ||
804 | |||
805 | struct GNUNET_HashCode slave_key_hash; | ||
806 | GNUNET_CRYPTO_hash (&dcsn->slave_key, sizeof (dcsn->slave_key), | ||
807 | &slave_key_hash); | ||
379 | 808 | ||
809 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
810 | "%p Got join decision (%d) from client for place %s..\n", | ||
811 | hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash)); | ||
812 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "%p ..and slave %s.\n", | ||
814 | hst, GNUNET_h2s (&slave_key_hash)); | ||
815 | |||
816 | GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_key_hash, | ||
817 | &psyc_send_join_decision, &jcls); | ||
818 | GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_key_hash); | ||
819 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
380 | } | 820 | } |
381 | 821 | ||
382 | 822 | ||
823 | /** | ||
824 | * Send acknowledgement to a client. | ||
825 | * | ||
826 | * Sent after a message fragment has been passed on to multicast. | ||
827 | * | ||
828 | * @param plc The place struct for the client. | ||
829 | */ | ||
383 | static void | 830 | static void |
384 | client_place_enter (void *cls, struct GNUNET_SERVER_Client *client, | 831 | send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client) |
385 | const struct GNUNET_MessageHeader *msg) | 832 | { |
833 | struct GNUNET_MessageHeader res; | ||
834 | res.size = htons (sizeof (res)); | ||
835 | res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK); | ||
836 | |||
837 | GNUNET_SERVER_notification_context_add (nc, client); | ||
838 | GNUNET_SERVER_notification_context_unicast (nc, client, &res, GNUNET_NO); | ||
839 | } | ||
840 | |||
841 | |||
842 | /** | ||
843 | * Proceed to the next message part in the transmission queue. | ||
844 | * | ||
845 | * @param plc | ||
846 | * Place where the transmission is going on. | ||
847 | * @param tmit_msg | ||
848 | * Currently transmitted message. | ||
849 | * @param tmit_frag | ||
850 | * Currently transmitted message fragment. | ||
851 | * | ||
852 | * @return @a tmit_frag, or NULL if reached the end of fragment. | ||
853 | */ | ||
854 | static struct FragmentTransmitQueue * | ||
855 | psyc_transmit_queue_next_part (struct Place *plc, | ||
856 | struct MessageTransmitQueue *tmit_msg, | ||
857 | struct FragmentTransmitQueue *tmit_frag) | ||
858 | { | ||
859 | uint16_t psize = ntohs (tmit_frag->next_part->size); | ||
860 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
861 | "%p psyc_transmit_queue_next_part: %x + %u - %x = %u < %u\n", | ||
862 | plc, tmit_frag->next_part, psize, &tmit_frag[1], | ||
863 | (char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1]), | ||
864 | tmit_frag->size); | ||
865 | if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1]) | ||
866 | < tmit_frag->size) | ||
867 | { | ||
868 | tmit_frag->next_part | ||
869 | = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part + psize); | ||
870 | } | ||
871 | else /* Reached end of current fragment. */ | ||
872 | { | ||
873 | if (NULL != tmit_frag->client) | ||
874 | send_message_ack (plc, tmit_frag->client); | ||
875 | GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag); | ||
876 | GNUNET_free (tmit_frag); | ||
877 | tmit_frag = NULL; | ||
878 | } | ||
879 | return tmit_frag; | ||
880 | } | ||
881 | |||
882 | |||
883 | /** | ||
884 | * Proceed to next message in transmission queue. | ||
885 | * | ||
886 | * @param plc | ||
887 | * Place where the transmission is going on. | ||
888 | * @param tmit_msg | ||
889 | * Currently transmitted message. | ||
890 | * | ||
891 | * @return The next message in queue, or NULL if queue is empty. | ||
892 | */ | ||
893 | static struct MessageTransmitQueue * | ||
894 | psyc_transmit_queue_next_msg (struct Place *plc, | ||
895 | struct MessageTransmitQueue *tmit_msg) | ||
896 | { | ||
897 | GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg); | ||
898 | GNUNET_free (tmit_msg); | ||
899 | return plc->tmit_msgs_head; | ||
900 | } | ||
901 | |||
902 | |||
903 | /** | ||
904 | * Callback for data transmission to PSYC. | ||
905 | */ | ||
906 | static int | ||
907 | psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data) | ||
386 | { | 908 | { |
909 | struct Place *plc = cls; | ||
910 | struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head; | ||
911 | GNUNET_assert (NULL != tmit_msg); | ||
912 | struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head; | ||
913 | if (NULL == tmit_frag) | ||
914 | { /* Rest of the message have not arrived yet, pause transmission */ | ||
915 | *data_size = 0; | ||
916 | return GNUNET_NO; | ||
917 | } | ||
918 | struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part; | ||
919 | if (NULL == pmsg) | ||
920 | { | ||
921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
922 | "%p psyc_transmit_notify_data: nothing to send.\n", plc); | ||
923 | *data_size = 0; | ||
924 | return GNUNET_NO; | ||
925 | } | ||
387 | 926 | ||
927 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
928 | "%p psyc_transmit_notify_data()\n", plc); | ||
929 | GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); | ||
930 | |||
931 | uint16_t ptype = ntohs (pmsg->type); | ||
932 | uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg); | ||
933 | int ret; | ||
934 | |||
935 | switch (ptype) | ||
936 | { | ||
937 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: | ||
938 | if (*data_size < pdata_size) | ||
939 | { | ||
940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
941 | "%p psyc_transmit_notify_data: buffer size too small for data.\n", plc); | ||
942 | *data_size = 0; | ||
943 | return GNUNET_NO; | ||
944 | } | ||
945 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
946 | "%p psyc_transmit_notify_data: sending %u bytes.\n", | ||
947 | plc, pdata_size); | ||
948 | |||
949 | *data_size = pdata_size; | ||
950 | memcpy (data, &pmsg[1], *data_size); | ||
951 | ret = GNUNET_NO; | ||
952 | break; | ||
953 | |||
954 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: | ||
955 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: | ||
956 | *data_size = 0; | ||
957 | ret = GNUNET_YES; | ||
958 | break; | ||
959 | |||
960 | default: | ||
961 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
962 | "%p psyc_transmit_notify_data: unexpected message part of type %u.\n", | ||
963 | plc, ptype); | ||
964 | ret = GNUNET_SYSERR; | ||
965 | } | ||
966 | |||
967 | if (GNUNET_SYSERR == ret) | ||
968 | { | ||
969 | *data_size = 0; | ||
970 | tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); | ||
971 | plc->is_disconnected = GNUNET_YES; | ||
972 | GNUNET_SERVER_client_disconnect (tmit_frag->client); | ||
973 | GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc); | ||
974 | return ret; | ||
975 | } | ||
976 | else | ||
977 | { | ||
978 | psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag); | ||
979 | |||
980 | if (NULL == tmit_msg->frags_head | ||
981 | && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype) | ||
982 | { /* Reached end of current message. */ | ||
983 | tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); | ||
984 | } | ||
985 | } | ||
986 | |||
987 | if (ret != GNUNET_NO) | ||
988 | { | ||
989 | if (NULL != tmit_msg) | ||
990 | { | ||
991 | psyc_transmit_message (plc); | ||
992 | } | ||
993 | else if (GNUNET_YES == plc->is_disconnected) | ||
994 | { | ||
995 | /* FIXME: handle partial message (when still in_transmit) */ | ||
996 | cleanup_place (plc); | ||
997 | } | ||
998 | } | ||
999 | return ret; | ||
388 | } | 1000 | } |
389 | 1001 | ||
390 | 1002 | ||
1003 | /** | ||
1004 | * Callback for modifier transmission to PSYC. | ||
1005 | */ | ||
1006 | static int | ||
1007 | psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, | ||
1008 | uint8_t *oper, uint32_t *full_value_size) | ||
1009 | { | ||
1010 | struct Place *plc = cls; | ||
1011 | struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head; | ||
1012 | GNUNET_assert (NULL != tmit_msg); | ||
1013 | struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head; | ||
1014 | if (NULL == tmit_frag) | ||
1015 | { /* Rest of the message have not arrived yet, pause transmission */ | ||
1016 | *data_size = 0; | ||
1017 | return GNUNET_NO; | ||
1018 | } | ||
1019 | struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part; | ||
1020 | if (NULL == pmsg) | ||
1021 | { | ||
1022 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1023 | "%p psyc_transmit_notify_mod: nothing to send.\n", plc); | ||
1024 | *data_size = 0; | ||
1025 | return GNUNET_NO; | ||
1026 | } | ||
1027 | |||
1028 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1029 | "%p psyc_transmit_notify_mod()\n", plc); | ||
1030 | GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); | ||
1031 | |||
1032 | uint16_t ptype = ntohs (pmsg->type); | ||
1033 | int ret; | ||
1034 | |||
1035 | switch (ptype) | ||
1036 | { | ||
1037 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: | ||
1038 | { | ||
1039 | if (NULL == oper) | ||
1040 | { | ||
1041 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1042 | "%p psyc_transmit_notify_mod: oper is NULL.\n", plc); | ||
1043 | ret = GNUNET_SYSERR; | ||
1044 | break; | ||
1045 | } | ||
1046 | struct GNUNET_PSYC_MessageModifier * | ||
1047 | pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part; | ||
1048 | uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod); | ||
1049 | |||
1050 | if (*data_size < mod_size) | ||
1051 | { | ||
1052 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1053 | "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc); | ||
1054 | *data_size = 0; | ||
1055 | return GNUNET_NO; | ||
1056 | } | ||
1057 | |||
1058 | *full_value_size = ntohl (pmod->value_size); | ||
1059 | *oper = pmod->oper; | ||
1060 | *data_size = mod_size; | ||
1061 | memcpy (data, &pmod[1], mod_size); | ||
1062 | ret = GNUNET_NO; | ||
1063 | #if REMOVE // FIXME | ||
1064 | ret = (mod_size - strnlen ((char *) &pmod[1], mod_size) - 1 | ||
1065 | == *full_value_size) | ||
1066 | ? GNUNET_YES | ||
1067 | : GNUNET_NO; | ||
1068 | #endif | ||
1069 | break; | ||
1070 | } | ||
1071 | |||
1072 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: | ||
1073 | { | ||
1074 | if (NULL != oper) | ||
1075 | { | ||
1076 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1077 | "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc); | ||
1078 | ret = GNUNET_SYSERR; | ||
1079 | break; | ||
1080 | } | ||
1081 | uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg); | ||
1082 | if (*data_size < mod_size) | ||
1083 | { | ||
1084 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1085 | "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc); | ||
1086 | *data_size = 0; | ||
1087 | return GNUNET_NO; | ||
1088 | } | ||
1089 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1090 | "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size); | ||
1091 | |||
1092 | *data_size = mod_size; | ||
1093 | memcpy (data, &pmsg[1], *data_size); | ||
1094 | ret = GNUNET_NO; | ||
1095 | break; | ||
1096 | } | ||
1097 | |||
1098 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: | ||
1099 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: | ||
1100 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: | ||
1101 | *data_size = 0; | ||
1102 | ret = GNUNET_YES; | ||
1103 | break; | ||
1104 | |||
1105 | default: | ||
1106 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1107 | "%p psyc_transmit_notify_mod: unexpected message part of type %u.\n", | ||
1108 | plc, ptype); | ||
1109 | ret = GNUNET_SYSERR; | ||
1110 | } | ||
1111 | |||
1112 | if (GNUNET_SYSERR == ret) | ||
1113 | { | ||
1114 | *data_size = 0; | ||
1115 | ret = GNUNET_SYSERR; | ||
1116 | tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); | ||
1117 | plc->is_disconnected = GNUNET_YES; | ||
1118 | GNUNET_SERVER_client_disconnect (tmit_frag->client); | ||
1119 | GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc); | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag); | ||
1124 | |||
1125 | if (NULL == tmit_msg->frags_head | ||
1126 | && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype) | ||
1127 | { /* Reached end of current message. */ | ||
1128 | tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg); | ||
1129 | } | ||
1130 | } | ||
1131 | return ret; | ||
1132 | } | ||
1133 | |||
1134 | /** | ||
1135 | * Callback for data transmission from a host to PSYC. | ||
1136 | */ | ||
1137 | static int | ||
1138 | host_transmit_notify_data (void *cls, uint16_t *data_size, void *data) | ||
1139 | { | ||
1140 | int ret = psyc_transmit_notify_data (cls, data_size, data); | ||
1141 | |||
1142 | if (GNUNET_NO != ret) | ||
1143 | { | ||
1144 | struct Host *hst = cls; | ||
1145 | hst->tmit_handle = NULL; | ||
1146 | } | ||
1147 | return ret; | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | /** | ||
1152 | * Callback for the transmit functions of multicast. | ||
1153 | */ | ||
1154 | static int | ||
1155 | guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data) | ||
1156 | { | ||
1157 | int ret = psyc_transmit_notify_data (cls, data_size, data); | ||
1158 | |||
1159 | if (GNUNET_NO != ret) | ||
1160 | { | ||
1161 | struct Guest *gst = cls; | ||
1162 | gst->tmit_handle = NULL; | ||
1163 | } | ||
1164 | return ret; | ||
1165 | } | ||
1166 | |||
1167 | |||
1168 | /** | ||
1169 | * Callback for modifier transmission from a host to PSYC. | ||
1170 | */ | ||
1171 | static int | ||
1172 | host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, | ||
1173 | uint8_t *oper, uint32_t *full_value_size) | ||
1174 | { | ||
1175 | int ret = psyc_transmit_notify_mod (cls, data_size, data, | ||
1176 | oper, full_value_size); | ||
1177 | if (GNUNET_SYSERR == ret) | ||
1178 | { | ||
1179 | struct Host *hst = cls; | ||
1180 | hst->tmit_handle = NULL; | ||
1181 | } | ||
1182 | return ret; | ||
1183 | } | ||
1184 | |||
1185 | |||
1186 | /** | ||
1187 | * Callback for modifier transmission from a guest to PSYC. | ||
1188 | */ | ||
1189 | static int | ||
1190 | guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, | ||
1191 | uint8_t *oper, uint32_t *full_value_size) | ||
1192 | { | ||
1193 | int ret = psyc_transmit_notify_mod (cls, data_size, data, | ||
1194 | oper, full_value_size); | ||
1195 | if (GNUNET_SYSERR == ret) | ||
1196 | { | ||
1197 | struct Guest *gst = cls; | ||
1198 | gst->tmit_handle = NULL; | ||
1199 | } | ||
1200 | return ret; | ||
1201 | } | ||
1202 | |||
1203 | |||
1204 | /** | ||
1205 | * Get method part of next message from transmission queue. | ||
1206 | * | ||
1207 | * @param tmit_msg | ||
1208 | * Next item in message transmission queue. | ||
1209 | * @param[out] pmeth | ||
1210 | * The message method is returned here. | ||
1211 | * | ||
1212 | * @return #GNUNET_OK on success | ||
1213 | * #GNUNET_NO if there are no more messages in queue. | ||
1214 | * #GNUNET_SYSERR if the next message is malformed. | ||
1215 | */ | ||
1216 | static int | ||
1217 | psyc_transmit_queue_next_method (struct Place *plc, | ||
1218 | struct GNUNET_PSYC_MessageMethod **pmeth) | ||
1219 | { | ||
1220 | struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head; | ||
1221 | if (NULL == tmit_msg) | ||
1222 | return GNUNET_NO; | ||
1223 | |||
1224 | struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head; | ||
1225 | if (NULL == tmit_frag) | ||
1226 | { | ||
1227 | GNUNET_break (0); | ||
1228 | return GNUNET_NO; | ||
1229 | } | ||
1230 | |||
1231 | struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part; | ||
1232 | if (NULL == pmsg | ||
1233 | || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type)) | ||
1234 | { | ||
1235 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1236 | "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n", | ||
1237 | plc, ntohs (pmsg->type)); | ||
1238 | GNUNET_break (0); | ||
1239 | return GNUNET_SYSERR; | ||
1240 | } | ||
1241 | |||
1242 | uint16_t psize = ntohs (pmsg->size); | ||
1243 | *pmeth = (struct GNUNET_PSYC_MessageMethod *) pmsg; | ||
1244 | |||
1245 | if (psize < sizeof (**pmeth) + 1 || '\0' != *((char *) *pmeth + psize - 1)) | ||
1246 | { | ||
1247 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1248 | "%p psyc_transmit_queue_next_method: invalid method name.\n", | ||
1249 | plc, ntohs (pmsg->type)); | ||
1250 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1251 | "%u <= %u || NUL != %u\n", | ||
1252 | sizeof (**pmeth), psize, *((char *) *pmeth + psize - 1)); | ||
1253 | GNUNET_break (0); | ||
1254 | return GNUNET_SYSERR; | ||
1255 | } | ||
1256 | psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag); | ||
1257 | return GNUNET_OK; | ||
1258 | } | ||
1259 | |||
1260 | |||
1261 | /** | ||
1262 | * Transmit the next message in queue from the host to the PSYC channel. | ||
1263 | */ | ||
1264 | static int | ||
1265 | psyc_master_transmit_message (struct Host *hst) | ||
1266 | { | ||
1267 | |||
1268 | if (NULL == hst->tmit_handle) | ||
1269 | { | ||
1270 | struct GNUNET_PSYC_MessageMethod *pmeth = NULL; | ||
1271 | int ret = psyc_transmit_queue_next_method (&hst->plc, &pmeth); | ||
1272 | if (GNUNET_OK != ret) | ||
1273 | return ret; | ||
1274 | |||
1275 | hst->tmit_handle | ||
1276 | = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1], | ||
1277 | &host_transmit_notify_mod, | ||
1278 | &host_transmit_notify_data, hst, | ||
1279 | pmeth->flags); | ||
1280 | } | ||
1281 | else | ||
1282 | { | ||
1283 | GNUNET_PSYC_master_transmit_resume (hst->tmit_handle); | ||
1284 | } | ||
1285 | return GNUNET_OK; | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /** | ||
1290 | * Transmit the next message in queue from a guest to the PSYC channel. | ||
1291 | */ | ||
1292 | static int | ||
1293 | psyc_slave_transmit_message (struct Guest *gst) | ||
1294 | { | ||
1295 | if (NULL == gst->tmit_handle) | ||
1296 | { | ||
1297 | struct GNUNET_PSYC_MessageMethod *pmeth = NULL; | ||
1298 | int ret = psyc_transmit_queue_next_method (&gst->plc, &pmeth); | ||
1299 | if (GNUNET_OK != ret) | ||
1300 | return ret; | ||
1301 | |||
1302 | gst->tmit_handle | ||
1303 | = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1], | ||
1304 | &guest_transmit_notify_mod, | ||
1305 | &guest_transmit_notify_data, gst, | ||
1306 | pmeth->flags); | ||
1307 | } | ||
1308 | else | ||
1309 | { | ||
1310 | GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle); | ||
1311 | } | ||
1312 | return GNUNET_OK; | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | /** | ||
1317 | * Transmit a message to PSYC. | ||
1318 | */ | ||
1319 | static int | ||
1320 | psyc_transmit_message (struct Place *plc) | ||
1321 | { | ||
1322 | return | ||
1323 | (plc->is_host) | ||
1324 | ? psyc_master_transmit_message ((struct Host *) plc) | ||
1325 | : psyc_slave_transmit_message ((struct Guest *) plc); | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /** | ||
1330 | * Queue message parts for sending to PSYC. | ||
1331 | * | ||
1332 | * @param plc Place to send to. | ||
1333 | * @param client Client the message originates from. | ||
1334 | * @param data_size Size of @a data. | ||
1335 | * @param data Concatenated message parts. | ||
1336 | * @param first_ptype First message part type in @a data. | ||
1337 | * @param last_ptype Last message part type in @a data. | ||
1338 | */ | ||
1339 | static struct MessageTransmitQueue * | ||
1340 | psyc_transmit_queue_message (struct Place *plc, | ||
1341 | struct GNUNET_SERVER_Client *client, | ||
1342 | size_t data_size, | ||
1343 | const void *data, | ||
1344 | uint16_t first_ptype, uint16_t last_ptype, | ||
1345 | struct MessageTransmitQueue *tmit_msg) | ||
1346 | { | ||
1347 | if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype) | ||
1348 | { | ||
1349 | tmit_msg = GNUNET_malloc (sizeof (*tmit_msg)); | ||
1350 | GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg); | ||
1351 | } | ||
1352 | else if (NULL == tmit_msg) | ||
1353 | { | ||
1354 | return NULL; | ||
1355 | } | ||
1356 | |||
1357 | struct FragmentTransmitQueue * | ||
1358 | tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size); | ||
1359 | memcpy (&tmit_frag[1], data, data_size); | ||
1360 | tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1]; | ||
1361 | tmit_frag->client = client; | ||
1362 | tmit_frag->size = data_size; | ||
1363 | |||
1364 | GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag); | ||
1365 | tmit_msg->client = client; | ||
1366 | return tmit_msg; | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Cancel transmission of current message to PSYC. | ||
1372 | * | ||
1373 | * @param plc Place to send to. | ||
1374 | * @param client Client the message originates from. | ||
1375 | */ | ||
391 | static void | 1376 | static void |
392 | client_join_decision (void *cls, struct GNUNET_SERVER_Client *client, | 1377 | psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client) |
393 | const struct GNUNET_MessageHeader *msg) | ||
394 | { | 1378 | { |
1379 | uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL; | ||
1380 | |||
1381 | struct GNUNET_MessageHeader msg; | ||
1382 | msg.size = htons (sizeof (msg)); | ||
1383 | msg.type = htons (type); | ||
395 | 1384 | ||
1385 | psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL); | ||
1386 | psyc_transmit_message (plc); | ||
1387 | |||
1388 | /* FIXME: cleanup */ | ||
396 | } | 1389 | } |
397 | 1390 | ||
398 | 1391 | ||
1392 | /** | ||
1393 | * Handle an incoming message from a client, to be transmitted to the place. | ||
1394 | */ | ||
399 | static void | 1395 | static void |
400 | client_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, | 1396 | client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, |
401 | const struct GNUNET_MessageHeader *msg) | 1397 | const struct GNUNET_MessageHeader *msg) |
402 | { | 1398 | { |
1399 | struct Client * | ||
1400 | ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); | ||
1401 | GNUNET_assert (NULL != ctx); | ||
1402 | struct Place *plc = ctx->plc; | ||
1403 | int ret = GNUNET_SYSERR; | ||
403 | 1404 | ||
1405 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1406 | "%p Received message from client.\n", plc); | ||
1407 | GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg); | ||
1408 | |||
1409 | if (GNUNET_YES != plc->is_ready) | ||
1410 | { | ||
1411 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1412 | "%p Place is not ready yet, disconnecting client.\n", plc); | ||
1413 | GNUNET_break (0); | ||
1414 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1415 | return; | ||
1416 | } | ||
1417 | |||
1418 | uint16_t size = ntohs (msg->size); | ||
1419 | uint16_t psize = size - sizeof (*msg); | ||
1420 | if (psize < sizeof (struct GNUNET_MessageHeader) | ||
1421 | || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize) | ||
1422 | { | ||
1423 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1424 | "%p Received message with invalid payload size (%u) from client.\n", | ||
1425 | plc, psize); | ||
1426 | GNUNET_break (0); | ||
1427 | psyc_transmit_cancel (plc, client); | ||
1428 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1429 | return; | ||
1430 | } | ||
1431 | |||
1432 | uint16_t first_ptype = 0, last_ptype = 0; | ||
1433 | if (GNUNET_SYSERR | ||
1434 | == GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1], | ||
1435 | &first_ptype, &last_ptype)) | ||
1436 | { | ||
1437 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1438 | "%p Received invalid message part from client.\n", plc); | ||
1439 | GNUNET_break (0); | ||
1440 | psyc_transmit_cancel (plc, client); | ||
1441 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1442 | return; | ||
1443 | } | ||
1444 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1445 | "%p Received message with first part type %u and last part type %u.\n", | ||
1446 | plc, first_ptype, last_ptype); | ||
1447 | |||
1448 | ctx->tmit_msg | ||
1449 | = psyc_transmit_queue_message (plc, client, psize, &msg[1], | ||
1450 | first_ptype, last_ptype, ctx->tmit_msg); | ||
1451 | if (NULL != ctx->tmit_msg) | ||
1452 | { | ||
1453 | if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype) | ||
1454 | ctx->tmit_msg = NULL; | ||
1455 | ret = psyc_transmit_message (plc); | ||
1456 | } | ||
1457 | |||
1458 | if (GNUNET_OK != ret) | ||
1459 | { | ||
1460 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1461 | "%p Received invalid message part from client.\n", plc); | ||
1462 | GNUNET_break (0); | ||
1463 | psyc_transmit_cancel (plc, client); | ||
1464 | ret = GNUNET_SYSERR; | ||
1465 | } | ||
1466 | GNUNET_SERVER_receive_done (client, ret); | ||
404 | } | 1467 | } |
405 | 1468 | ||
406 | 1469 | ||
@@ -416,16 +1479,16 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
416 | const struct GNUNET_CONFIGURATION_Handle *c) | 1479 | const struct GNUNET_CONFIGURATION_Handle *c) |
417 | { | 1480 | { |
418 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 1481 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
419 | { &client_home_enter, NULL, | 1482 | { &client_recv_host_enter, NULL, |
420 | GNUNET_MESSAGE_TYPE_SOCIAL_HOME_ENTER, 0 }, | 1483 | GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 }, |
421 | 1484 | ||
422 | { &client_place_enter, NULL, | 1485 | { &client_recv_guest_enter, NULL, |
423 | GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_ENTER, 0 }, | 1486 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 }, |
424 | 1487 | ||
425 | { &client_join_decision, NULL, | 1488 | { &client_recv_join_decision, NULL, |
426 | GNUNET_MESSAGE_TYPE_SOCIAL_JOIN_DECISION, 0 }, | 1489 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 }, |
427 | 1490 | ||
428 | { &client_psyc_message, NULL, | 1491 | { &client_recv_psyc_message, NULL, |
429 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 } | 1492 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 } |
430 | }; | 1493 | }; |
431 | 1494 | ||
diff --git a/src/social/social.h b/src/social/social.h index 7f854eed8..00edaefd1 100644 --- a/src/social/social.h +++ b/src/social/social.h | |||
@@ -19,7 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file psyc/psyc.h | 22 | * @file social/social.h |
23 | * @brief Common type definitions for the Social service and API. | 23 | * @brief Common type definitions for the Social service and API. |
24 | * @author Gabor X Toth | 24 | * @author Gabor X Toth |
25 | */ | 25 | */ |
@@ -30,16 +30,99 @@ | |||
30 | #include "platform.h" | 30 | #include "platform.h" |
31 | #include "gnunet_social_service.h" | 31 | #include "gnunet_social_service.h" |
32 | 32 | ||
33 | enum MessageState | ||
34 | { | ||
35 | MSG_STATE_START = 0, | ||
36 | MSG_STATE_HEADER = 1, | ||
37 | MSG_STATE_METHOD = 2, | ||
38 | MSG_STATE_MODIFIER = 3, | ||
39 | MSG_STATE_MOD_CONT = 4, | ||
40 | MSG_STATE_DATA = 5, | ||
41 | MSG_STATE_END = 6, | ||
42 | MSG_STATE_CANCEL = 7, | ||
43 | MSG_STATE_ERROR = 8, | ||
44 | }; | ||
45 | |||
33 | 46 | ||
34 | GNUNET_NETWORK_STRUCT_BEGIN | 47 | GNUNET_NETWORK_STRUCT_BEGIN |
35 | 48 | ||
36 | /**** library -> service ****/ | 49 | /**** library -> service ****/ |
37 | 50 | ||
38 | 51 | ||
52 | struct HostEnterRequest | ||
53 | { | ||
54 | /** | ||
55 | * Type: GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER | ||
56 | */ | ||
57 | struct GNUNET_MessageHeader header; | ||
58 | |||
59 | uint32_t policy GNUNET_PACKED; | ||
60 | |||
61 | struct GNUNET_CRYPTO_EcdsaPrivateKey host_key; | ||
62 | |||
63 | struct GNUNET_CRYPTO_EddsaPrivateKey place_key; | ||
64 | }; | ||
65 | |||
66 | |||
67 | struct GuestEnterRequest | ||
68 | { | ||
69 | /** | ||
70 | * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ADDR | ||
71 | */ | ||
72 | struct GNUNET_MessageHeader header; | ||
73 | |||
74 | uint32_t relay_count GNUNET_PACKED; | ||
75 | |||
76 | struct GNUNET_CRYPTO_EcdsaPrivateKey guest_key; | ||
77 | |||
78 | struct GNUNET_CRYPTO_EddsaPublicKey place_key; | ||
79 | |||
80 | struct GNUNET_PeerIdentity origin; | ||
81 | |||
82 | /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ | ||
83 | |||
84 | /* Followed by struct GNUNET_MessageHeader join_msg */ | ||
85 | }; | ||
86 | |||
39 | 87 | ||
40 | /**** service -> library ****/ | 88 | /**** service -> library ****/ |
41 | 89 | ||
42 | 90 | ||
91 | struct CountersResult | ||
92 | { | ||
93 | /** | ||
94 | * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS | ||
95 | */ | ||
96 | struct GNUNET_MessageHeader header; | ||
97 | |||
98 | /** | ||
99 | * Status code for the operation. | ||
100 | */ | ||
101 | int32_t result_code GNUNET_PACKED; | ||
102 | |||
103 | /** | ||
104 | * Last message ID sent to the channel. | ||
105 | */ | ||
106 | uint64_t max_message_id; | ||
107 | }; | ||
108 | |||
109 | |||
110 | #if REMOVE | ||
111 | struct NymEnterRequest | ||
112 | { | ||
113 | /** | ||
114 | * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER | ||
115 | */ | ||
116 | struct GNUNET_MessageHeader header; | ||
117 | /** | ||
118 | * Public key of the joining slave. | ||
119 | */ | ||
120 | struct GNUNET_CRYPTO_EcdsaPublicKey nym_key; | ||
121 | |||
122 | /* Followed by struct GNUNET_MessageHeader join_request */ | ||
123 | }; | ||
124 | #endif | ||
125 | |||
43 | 126 | ||
44 | GNUNET_NETWORK_STRUCT_END | 127 | GNUNET_NETWORK_STRUCT_END |
45 | 128 | ||
diff --git a/src/social/social_api.c b/src/social/social_api.c index ee13c7d61..d19f83e89 100644 --- a/src/social/social_api.c +++ b/src/social/social_api.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of GNUnet | 2 | * This file is part of GNUnet |
3 | * (C) 2013 Christian Grothoff (and other contributing authors) | 3 | * (C) 2013 Christian Grothoff (and other contributing authors) |
4 | * | 4 | * |
@@ -25,30 +25,93 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <inttypes.h> | 27 | #include <inttypes.h> |
28 | #include <string.h> | ||
28 | 29 | ||
29 | #include "platform.h" | 30 | #include "platform.h" |
30 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
31 | #include "gnunet_env_lib.h" | 32 | #include "gnunet_env_lib.h" |
33 | #include "gnunet_core_service.h" | ||
34 | #include "gnunet_identity_service.h" | ||
35 | #include "gnunet_namestore_service.h" | ||
36 | #include "gnunet_gns_service.h" | ||
32 | #include "gnunet_psyc_service.h" | 37 | #include "gnunet_psyc_service.h" |
38 | #include "gnunet_psyc_util_lib.h" | ||
33 | #include "gnunet_social_service.h" | 39 | #include "gnunet_social_service.h" |
34 | #include "social.h" | 40 | #include "social.h" |
35 | 41 | ||
42 | #define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__) | ||
36 | 43 | ||
37 | /** | ||
38 | * Handle for a pseudonym of another user in the network. | ||
39 | */ | ||
40 | struct GNUNET_SOCIAL_Nym | ||
41 | { | ||
42 | |||
43 | }; | ||
44 | 44 | ||
45 | static struct GNUNET_CORE_Handle *core; | ||
46 | static struct GNUNET_GNS_Handle *gns; | ||
47 | static struct GNUNET_NAMESTORE_Handle *namestore; | ||
48 | static struct GNUNET_PeerIdentity this_peer; | ||
45 | 49 | ||
46 | /** | 50 | /** |
47 | * Handle for a place where social interactions happen. | 51 | * Handle for a place where social interactions happen. |
48 | */ | 52 | */ |
49 | struct GNUNET_SOCIAL_Place | 53 | struct GNUNET_SOCIAL_Place |
50 | { | 54 | { |
51 | 55 | /** | |
56 | * Configuration to use. | ||
57 | */ | ||
58 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
59 | |||
60 | /** | ||
61 | * Client connection to the service. | ||
62 | */ | ||
63 | struct GNUNET_CLIENT_MANAGER_Connection *client; | ||
64 | |||
65 | /** | ||
66 | * Transmission handle; | ||
67 | */ | ||
68 | struct GNUNET_PSYC_TransmitHandle *tmit; | ||
69 | |||
70 | /** | ||
71 | * Receipt handle; | ||
72 | */ | ||
73 | struct GNUNET_PSYC_ReceiveHandle *recv; | ||
74 | |||
75 | /** | ||
76 | * Message to send on reconnect. | ||
77 | */ | ||
78 | struct GNUNET_MessageHeader *connect_msg; | ||
79 | |||
80 | /** | ||
81 | * Slicer for processing incoming methods. | ||
82 | */ | ||
83 | struct GNUNET_SOCIAL_Slicer *slicer; | ||
84 | |||
85 | /** | ||
86 | * Function called after disconnected from the service. | ||
87 | */ | ||
88 | GNUNET_ContinuationCallback disconnect_cb; | ||
89 | |||
90 | /** | ||
91 | * Closure for @a disconnect_cb. | ||
92 | */ | ||
93 | void *disconnect_cls; | ||
94 | |||
95 | /** | ||
96 | * Public key of the place. | ||
97 | */ | ||
98 | struct GNUNET_CRYPTO_EddsaPublicKey pub_key; | ||
99 | |||
100 | /** | ||
101 | * Private key of the ego. | ||
102 | */ | ||
103 | struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key; | ||
104 | |||
105 | /** | ||
106 | * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)? | ||
107 | */ | ||
108 | uint8_t is_host; | ||
109 | |||
110 | /** | ||
111 | * Is this place in the process of disconnecting from the service? | ||
112 | * #GNUNET_YES or #GNUNET_NO | ||
113 | */ | ||
114 | uint8_t is_disconnecting; | ||
52 | }; | 115 | }; |
53 | 116 | ||
54 | 117 | ||
@@ -57,7 +120,20 @@ struct GNUNET_SOCIAL_Place | |||
57 | */ | 120 | */ |
58 | struct GNUNET_SOCIAL_Host | 121 | struct GNUNET_SOCIAL_Host |
59 | { | 122 | { |
123 | struct GNUNET_SOCIAL_Place plc; | ||
60 | 124 | ||
125 | struct GNUNET_CRYPTO_EddsaPrivateKey place_key; | ||
126 | |||
127 | GNUNET_SOCIAL_HostEnterCallback enter_cb; | ||
128 | |||
129 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb; | ||
130 | |||
131 | GNUNET_SOCIAL_FarewellCallback farewell_cb; | ||
132 | |||
133 | /** | ||
134 | * Closure for callbacks. | ||
135 | */ | ||
136 | void *cb_cls; | ||
61 | }; | 137 | }; |
62 | 138 | ||
63 | 139 | ||
@@ -66,16 +142,91 @@ struct GNUNET_SOCIAL_Host | |||
66 | */ | 142 | */ |
67 | struct GNUNET_SOCIAL_Guest | 143 | struct GNUNET_SOCIAL_Guest |
68 | { | 144 | { |
145 | struct GNUNET_SOCIAL_Place plc; | ||
69 | 146 | ||
147 | GNUNET_SOCIAL_GuestEnterCallback enter_cb; | ||
148 | |||
149 | GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb; | ||
150 | |||
151 | /** | ||
152 | * Closure for callbacks. | ||
153 | */ | ||
154 | void *cb_cls; | ||
70 | }; | 155 | }; |
71 | 156 | ||
72 | 157 | ||
73 | /** | 158 | /** |
74 | * Handle to an implementation of try-and-slice. | 159 | * Handle for a pseudonym of another user in the network. |
160 | */ | ||
161 | struct GNUNET_SOCIAL_Nym | ||
162 | { | ||
163 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
164 | struct GNUNET_HashCode pub_key_hash; | ||
165 | }; | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Hash map of all nyms. | ||
170 | * pub_key_hash -> struct GNUNET_SOCIAL_Nym * | ||
171 | */ | ||
172 | struct GNUNET_CONTAINER_MultiHashMap *nyms; | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Handle for a try-and-slice instance. | ||
75 | */ | 177 | */ |
76 | struct GNUNET_SOCIAL_Slicer | 178 | struct GNUNET_SOCIAL_Slicer |
77 | { | 179 | { |
180 | /** | ||
181 | * Message handlers: method_name -> SlicerCallbacks | ||
182 | */ | ||
183 | struct GNUNET_CONTAINER_MultiHashMap *handlers; | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Currently being processed message part. | ||
188 | */ | ||
189 | const struct GNUNET_MessageHeader *msg; | ||
190 | |||
191 | /** | ||
192 | * ID of currently being received message. | ||
193 | */ | ||
194 | uint64_t message_id; | ||
195 | |||
196 | /** | ||
197 | * Method name of currently being received message. | ||
198 | */ | ||
199 | char *method_name; | ||
200 | |||
201 | /** | ||
202 | * Public key of the nym the current message originates from. | ||
203 | */ | ||
204 | struct GNUNET_CRYPTO_EcdsaPublicKey nym_key; | ||
205 | |||
206 | /** | ||
207 | * Size of @a method_name (including terminating \0). | ||
208 | */ | ||
209 | uint16_t method_name_size; | ||
210 | }; | ||
211 | |||
78 | 212 | ||
213 | /** | ||
214 | * Callbacks for a slicer method handler. | ||
215 | */ | ||
216 | struct SlicerCallbacks | ||
217 | { | ||
218 | GNUNET_SOCIAL_MethodCallback method_cb; | ||
219 | GNUNET_SOCIAL_ModifierCallback modifier_cb; | ||
220 | GNUNET_SOCIAL_DataCallback data_cb; | ||
221 | GNUNET_SOCIAL_EndOfMessageCallback eom_cb; | ||
222 | void *cls; | ||
223 | }; | ||
224 | |||
225 | |||
226 | struct SlicerRemoveClosure | ||
227 | { | ||
228 | struct GNUNET_SOCIAL_Slicer *slicer; | ||
229 | struct SlicerCallbacks rm_cbs; | ||
79 | }; | 230 | }; |
80 | 231 | ||
81 | 232 | ||
@@ -118,6 +269,181 @@ struct GNUNET_SOCIAL_HistoryLesson | |||
118 | }; | 269 | }; |
119 | 270 | ||
120 | 271 | ||
272 | static struct GNUNET_SOCIAL_Nym * | ||
273 | nym_get_or_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key) | ||
274 | { | ||
275 | struct GNUNET_SOCIAL_Nym *nym = NULL; | ||
276 | struct GNUNET_HashCode pub_key_hash; | ||
277 | |||
278 | if (NULL == pub_key) | ||
279 | return NULL; | ||
280 | |||
281 | GNUNET_CRYPTO_hash (pub_key, sizeof (*pub_key), &pub_key_hash); | ||
282 | |||
283 | if (NULL == nyms) | ||
284 | nyms = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | ||
285 | else | ||
286 | nym = GNUNET_CONTAINER_multihashmap_get (nyms, &pub_key_hash); | ||
287 | |||
288 | if (NULL == nym) | ||
289 | { | ||
290 | nym = GNUNET_new (struct GNUNET_SOCIAL_Nym); | ||
291 | nym->pub_key = *pub_key; | ||
292 | nym->pub_key_hash = pub_key_hash; | ||
293 | GNUNET_CONTAINER_multihashmap_put (nyms, &nym->pub_key_hash, nym, | ||
294 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
295 | } | ||
296 | return nym; | ||
297 | } | ||
298 | |||
299 | |||
300 | static void | ||
301 | nym_destroy (struct GNUNET_SOCIAL_Nym *nym) | ||
302 | { | ||
303 | GNUNET_CONTAINER_multihashmap_remove (nyms, &nym->pub_key_hash, nym); | ||
304 | GNUNET_free (nym); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Call a handler for an incoming message part. | ||
310 | * | ||
311 | * @param cls | ||
312 | * @param key | ||
313 | * @param value | ||
314 | * | ||
315 | * @return | ||
316 | */ | ||
317 | int | ||
318 | slicer_handler_notify (void *cls, const struct GNUNET_HashCode *key, | ||
319 | void *value) | ||
320 | { | ||
321 | struct GNUNET_SOCIAL_Slicer *slicer = cls; | ||
322 | const struct GNUNET_MessageHeader *msg = slicer->msg; | ||
323 | struct SlicerCallbacks *cbs = value; | ||
324 | uint16_t ptype = ntohs (msg->type); | ||
325 | |||
326 | switch (ptype) | ||
327 | { | ||
328 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: | ||
329 | { | ||
330 | if (NULL == cbs->method_cb) | ||
331 | break; | ||
332 | struct GNUNET_PSYC_MessageMethod * | ||
333 | meth = (struct GNUNET_PSYC_MessageMethod *) msg; | ||
334 | cbs->method_cb (cbs->cls, meth, slicer->message_id, | ||
335 | ntohl (meth->flags), | ||
336 | nym_get_or_create (&slicer->nym_key), | ||
337 | slicer->method_name); | ||
338 | break; | ||
339 | } | ||
340 | |||
341 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: | ||
342 | { | ||
343 | if (NULL == cbs->modifier_cb) | ||
344 | break; | ||
345 | struct GNUNET_PSYC_MessageModifier * | ||
346 | mod = (struct GNUNET_PSYC_MessageModifier *) msg; | ||
347 | cbs->modifier_cb (cbs->cls, mod, slicer->message_id, | ||
348 | mod->oper, (const char *) &mod[1], | ||
349 | (const void *) &mod[1] + ntohs (mod->name_size), | ||
350 | ntohs (mod->value_size)); | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: | ||
355 | { | ||
356 | if (NULL == cbs->modifier_cb) | ||
357 | break; | ||
358 | /* FIXME: concatenate until done */ | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: | ||
363 | { | ||
364 | if (NULL == cbs->data_cb) | ||
365 | break; | ||
366 | uint64_t data_offset = 0; // FIXME | ||
367 | cbs->data_cb (cbs->cls, msg, slicer->message_id, | ||
368 | data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg)); | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: | ||
373 | if (NULL == cbs->eom_cb) | ||
374 | break; | ||
375 | cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO); | ||
376 | break; | ||
377 | |||
378 | case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: | ||
379 | if (NULL == cbs->eom_cb) | ||
380 | break; | ||
381 | cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES); | ||
382 | break; | ||
383 | } | ||
384 | return GNUNET_YES; | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Process an incoming message part and call matching handlers. | ||
390 | * | ||
391 | * @param cls | ||
392 | * Closure. | ||
393 | * @param message_id | ||
394 | * ID of the message. | ||
395 | * @param flags | ||
396 | * Flags for the message. | ||
397 | * @see enum GNUNET_PSYC_MessageFlags | ||
398 | * @param msg | ||
399 | * The message part. as it arrived from the network. | ||
400 | */ | ||
401 | static void | ||
402 | slicer_message (void *cls, uint64_t message_id, uint64_t fragment_offset, | ||
403 | uint32_t flags, const struct GNUNET_MessageHeader *msg) | ||
404 | { | ||
405 | struct GNUNET_SOCIAL_Slicer *slicer = cls; | ||
406 | uint16_t ptype = ntohs (msg->type); | ||
407 | if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype) | ||
408 | { | ||
409 | struct GNUNET_PSYC_MessageMethod * | ||
410 | meth = (struct GNUNET_PSYC_MessageMethod *) msg; | ||
411 | slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth); | ||
412 | slicer->method_name = GNUNET_malloc (slicer->method_name_size); | ||
413 | memcpy (slicer->method_name, &meth[1], slicer->method_name_size); | ||
414 | slicer->message_id = message_id; | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | GNUNET_assert (message_id == slicer->message_id); | ||
419 | } | ||
420 | |||
421 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
422 | "Slicer received message of type %u and size %u, " | ||
423 | "with ID %" PRIu64 " and method %s\n", | ||
424 | ptype, ntohs (msg->size), message_id, slicer->method_name); | ||
425 | |||
426 | slicer->msg = msg; | ||
427 | char *name = GNUNET_malloc (slicer->method_name_size); | ||
428 | memcpy (name, slicer->method_name, slicer->method_name_size); | ||
429 | do | ||
430 | { | ||
431 | struct GNUNET_HashCode key; | ||
432 | uint16_t name_len = strlen (name); | ||
433 | GNUNET_CRYPTO_hash (name, name_len, &key); | ||
434 | GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key, | ||
435 | &slicer_handler_notify, slicer); | ||
436 | char *p = strrchr (name, '_'); | ||
437 | if (NULL == p) | ||
438 | break; | ||
439 | *p = '\0'; | ||
440 | } while (1); | ||
441 | GNUNET_free (name); | ||
442 | slicer->msg = NULL; | ||
443 | |||
444 | if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype) | ||
445 | GNUNET_free (slicer->method_name); | ||
446 | } | ||
121 | 447 | ||
122 | 448 | ||
123 | /** | 449 | /** |
@@ -128,7 +454,9 @@ struct GNUNET_SOCIAL_HistoryLesson | |||
128 | struct GNUNET_SOCIAL_Slicer * | 454 | struct GNUNET_SOCIAL_Slicer * |
129 | GNUNET_SOCIAL_slicer_create (void) | 455 | GNUNET_SOCIAL_slicer_create (void) |
130 | { | 456 | { |
131 | return NULL; | 457 | struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer)); |
458 | slicer->handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
459 | return slicer; | ||
132 | } | 460 | } |
133 | 461 | ||
134 | 462 | ||
@@ -148,36 +476,338 @@ void | |||
148 | GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer, | 476 | GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer, |
149 | const char *method_name, | 477 | const char *method_name, |
150 | GNUNET_SOCIAL_MethodCallback method_cb, | 478 | GNUNET_SOCIAL_MethodCallback method_cb, |
479 | GNUNET_SOCIAL_ModifierCallback modifier_cb, | ||
480 | GNUNET_SOCIAL_DataCallback data_cb, | ||
481 | GNUNET_SOCIAL_EndOfMessageCallback eom_cb, | ||
151 | void *cls) | 482 | void *cls) |
152 | { | 483 | { |
484 | struct GNUNET_HashCode key; | ||
485 | GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); | ||
486 | |||
487 | struct SlicerCallbacks *cbs = GNUNET_malloc (sizeof (*cbs)); | ||
488 | cbs->method_cb = method_cb; | ||
489 | cbs->modifier_cb = modifier_cb; | ||
490 | cbs->data_cb = data_cb; | ||
491 | cbs->eom_cb = eom_cb; | ||
492 | cbs->cls = cls; | ||
493 | |||
494 | GNUNET_CONTAINER_multihashmap_put (slicer->handlers, &key, cbs, | ||
495 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
496 | } | ||
153 | 497 | ||
498 | |||
499 | int | ||
500 | slicer_remove_handler (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
501 | { | ||
502 | struct SlicerRemoveClosure *rm_cls = cls; | ||
503 | struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer; | ||
504 | struct SlicerCallbacks *rm_cbs = &rm_cls->rm_cbs; | ||
505 | struct SlicerCallbacks *cbs = value; | ||
506 | |||
507 | if (cbs->method_cb == rm_cbs->method_cb | ||
508 | && cbs->modifier_cb == rm_cbs->modifier_cb | ||
509 | && cbs->data_cb == rm_cbs->data_cb | ||
510 | && cbs->eom_cb == rm_cbs->eom_cb) | ||
511 | { | ||
512 | GNUNET_CONTAINER_multihashmap_remove (slicer->handlers, key, cbs); | ||
513 | GNUNET_free (cbs); | ||
514 | return GNUNET_NO; | ||
515 | } | ||
516 | return GNUNET_YES; | ||
154 | } | 517 | } |
155 | 518 | ||
156 | 519 | ||
157 | /** | 520 | /** |
158 | * Remove a registered method from the try-and-slice instance. | 521 | * Remove a registered method from the try-and-slice instance. |
159 | * | 522 | * |
523 | * Removes the first matching handler registered with @a method and the given callbacks. | ||
524 | * | ||
160 | * @param slicer The try-and-slice instance. | 525 | * @param slicer The try-and-slice instance. |
161 | * @param method_name Name of the method to remove. | 526 | * @param method_name Name of the method to remove. |
162 | * @param method Method handler. | 527 | * @param method Method handler. |
528 | * | ||
529 | * @return #GNUNET_OK if a method handler was removed, | ||
530 | * #GNUNET_NO if no handler matched the given method name and callbacks. | ||
163 | */ | 531 | */ |
164 | void | 532 | int |
165 | GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer, | 533 | GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer, |
166 | const char *method_name, | 534 | const char *method_name, |
167 | GNUNET_SOCIAL_MethodCallback method_cb) | 535 | GNUNET_SOCIAL_MethodCallback method_cb, |
536 | GNUNET_SOCIAL_ModifierCallback modifier_cb, | ||
537 | GNUNET_SOCIAL_DataCallback data_cb, | ||
538 | GNUNET_SOCIAL_EndOfMessageCallback eom_cb) | ||
168 | { | 539 | { |
540 | struct GNUNET_HashCode key; | ||
541 | GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); | ||
542 | |||
543 | struct SlicerRemoveClosure rm_cls; | ||
544 | rm_cls.slicer = slicer; | ||
545 | struct SlicerCallbacks *rm_cbs = &rm_cls.rm_cbs; | ||
546 | rm_cbs->method_cb = method_cb; | ||
547 | rm_cbs->modifier_cb = modifier_cb; | ||
548 | rm_cbs->data_cb = data_cb; | ||
549 | rm_cbs->eom_cb = eom_cb; | ||
550 | |||
551 | return | ||
552 | (GNUNET_SYSERR | ||
553 | == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key, | ||
554 | &slicer_remove_handler, | ||
555 | &rm_cls)) | ||
556 | ? GNUNET_NO | ||
557 | : GNUNET_OK; | ||
558 | } | ||
559 | |||
169 | 560 | ||
561 | int | ||
562 | slicer_free_handler (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
563 | { | ||
564 | struct SlicerCallbacks *cbs = value; | ||
565 | GNUNET_free (cbs); | ||
566 | return GNUNET_YES; | ||
170 | } | 567 | } |
171 | 568 | ||
569 | |||
172 | /** | 570 | /** |
173 | * Destroy a given try-and-slice instance. | 571 | * Destroy a given try-and-slice instance. |
174 | * | 572 | * |
175 | * @param slicer slicer to destroy | 573 | * @param slicer |
574 | * Slicer to destroy | ||
176 | */ | 575 | */ |
177 | void | 576 | void |
178 | GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer) | 577 | GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer) |
179 | { | 578 | { |
579 | GNUNET_CONTAINER_multihashmap_iterate (slicer->handlers, &slicer_free_handler, | ||
580 | NULL); | ||
581 | GNUNET_CONTAINER_multihashmap_destroy (slicer->handlers); | ||
582 | GNUNET_free (slicer); | ||
583 | } | ||
584 | |||
585 | |||
586 | static void | ||
587 | place_send_connect_msg (struct GNUNET_SOCIAL_Place *plc) | ||
588 | { | ||
589 | uint16_t cmsg_size = ntohs (plc->connect_msg->size); | ||
590 | struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size); | ||
591 | memcpy (cmsg, plc->connect_msg, cmsg_size); | ||
592 | GNUNET_CLIENT_MANAGER_transmit_now (plc->client, cmsg); | ||
593 | } | ||
594 | |||
595 | |||
596 | static void | ||
597 | place_recv_message_ack (void *cls, | ||
598 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
599 | const struct GNUNET_MessageHeader *msg) | ||
600 | { | ||
601 | struct GNUNET_SOCIAL_Place * | ||
602 | plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc)); | ||
603 | GNUNET_PSYC_transmit_got_ack (plc->tmit); | ||
604 | } | ||
605 | |||
606 | |||
607 | static void | ||
608 | place_recv_message (void *cls, | ||
609 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
610 | const struct GNUNET_MessageHeader *msg) | ||
611 | { | ||
612 | struct GNUNET_SOCIAL_Place * | ||
613 | plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc)); | ||
614 | GNUNET_PSYC_receive_message (plc->recv, | ||
615 | (const struct GNUNET_PSYC_MessageHeader *) msg); | ||
616 | } | ||
617 | |||
618 | |||
619 | static void | ||
620 | place_recv_disconnect (void *cls, | ||
621 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
622 | const struct GNUNET_MessageHeader *msg) | ||
623 | { | ||
624 | struct GNUNET_SOCIAL_Place * | ||
625 | plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc)); | ||
626 | |||
627 | GNUNET_CLIENT_MANAGER_reconnect (client); | ||
628 | place_send_connect_msg (plc); | ||
629 | } | ||
630 | |||
631 | |||
632 | static void | ||
633 | host_recv_enter_ack (void *cls, | ||
634 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
635 | const struct GNUNET_MessageHeader *msg) | ||
636 | { | ||
637 | struct GNUNET_SOCIAL_Host * | ||
638 | hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, | ||
639 | sizeof (struct GNUNET_SOCIAL_Place)); | ||
640 | |||
641 | struct GNUNET_PSYC_CountersResultMessage * | ||
642 | cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; | ||
643 | if (NULL != hst->enter_cb) | ||
644 | hst->enter_cb (hst->cb_cls, GNUNET_ntohll (cres->max_message_id)); | ||
645 | } | ||
646 | |||
647 | |||
648 | static void | ||
649 | host_recv_enter_request (void *cls, | ||
650 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
651 | const struct GNUNET_MessageHeader *msg) | ||
652 | { | ||
653 | struct GNUNET_SOCIAL_Host * | ||
654 | hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, | ||
655 | sizeof (struct GNUNET_SOCIAL_Place)); | ||
656 | if (NULL == hst->answer_door_cb) | ||
657 | return; | ||
658 | |||
659 | const char *method_name = NULL; | ||
660 | struct GNUNET_ENV_Environment *env = NULL; | ||
661 | const void *data = NULL; | ||
662 | uint16_t data_size = 0; | ||
663 | |||
664 | const struct GNUNET_PSYC_JoinRequestMessage * | ||
665 | req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg; | ||
666 | const struct GNUNET_PSYC_Message *entry_msg = NULL; | ||
667 | if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size)) | ||
668 | { | ||
669 | entry_msg = (struct GNUNET_PSYC_Message *) &req[1]; | ||
670 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
671 | "Received entry_msg of type %u and size %u.\n", | ||
672 | ntohs (entry_msg->header.type), ntohs (entry_msg->header.size)); | ||
673 | |||
674 | env = GNUNET_ENV_environment_create (); | ||
675 | if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_msg, &method_name, env, | ||
676 | &data, &data_size)) | ||
677 | { | ||
678 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
679 | "Ignoring invalid entry request from nym %s.\n", | ||
680 | GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key)); | ||
681 | GNUNET_break_op (0); | ||
682 | GNUNET_ENV_environment_destroy (env); | ||
683 | return; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_key); | ||
688 | hst->answer_door_cb (hst->cb_cls, nym, method_name, env, | ||
689 | data_size, data); | ||
690 | |||
691 | if (NULL != env) | ||
692 | GNUNET_ENV_environment_destroy (env); | ||
693 | } | ||
694 | |||
695 | |||
696 | static void | ||
697 | guest_recv_enter_ack (void *cls, | ||
698 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
699 | const struct GNUNET_MessageHeader *msg) | ||
700 | { | ||
701 | struct GNUNET_SOCIAL_Guest * | ||
702 | gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, | ||
703 | sizeof (struct GNUNET_SOCIAL_Place)); | ||
704 | |||
705 | struct GNUNET_PSYC_CountersResultMessage * | ||
706 | cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; | ||
707 | if (NULL != gst->enter_cb) | ||
708 | gst->enter_cb (gst->cb_cls, ntohl (cres->result_code), | ||
709 | GNUNET_ntohll (cres->max_message_id)); | ||
710 | } | ||
711 | |||
712 | |||
713 | static void | ||
714 | guest_recv_join_decision (void *cls, | ||
715 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
716 | const struct GNUNET_MessageHeader *msg) | ||
717 | { | ||
718 | struct GNUNET_SOCIAL_Guest * | ||
719 | gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, | ||
720 | sizeof (struct GNUNET_SOCIAL_Place)); | ||
721 | const struct GNUNET_PSYC_JoinDecisionMessage * | ||
722 | dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg; | ||
723 | |||
724 | struct GNUNET_PSYC_Message *pmsg = NULL; | ||
725 | if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg)) | ||
726 | pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1]; | ||
727 | |||
728 | if (NULL != gst->entry_dcsn_cb) | ||
729 | gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg); | ||
730 | } | ||
731 | |||
732 | |||
733 | static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] = | ||
734 | { | ||
735 | { &host_recv_enter_ack, NULL, | ||
736 | GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK, | ||
737 | sizeof (struct CountersResult), GNUNET_NO }, | ||
738 | |||
739 | { &host_recv_enter_request, NULL, | ||
740 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, | ||
741 | sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES }, | ||
742 | |||
743 | { &place_recv_message, NULL, | ||
744 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, | ||
745 | sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES }, | ||
746 | |||
747 | { &place_recv_message_ack, NULL, | ||
748 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK, | ||
749 | sizeof (struct GNUNET_MessageHeader), GNUNET_NO }, | ||
750 | |||
751 | { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO }, | ||
752 | |||
753 | { NULL, NULL, 0, 0, GNUNET_NO } | ||
754 | }; | ||
755 | |||
756 | |||
757 | static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] = | ||
758 | { | ||
759 | { &guest_recv_enter_ack, NULL, | ||
760 | GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK, | ||
761 | sizeof (struct CountersResult), GNUNET_NO }, | ||
762 | |||
763 | { &host_recv_enter_request, NULL, | ||
764 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, | ||
765 | sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES }, | ||
766 | |||
767 | { &place_recv_message, NULL, | ||
768 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, | ||
769 | sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES }, | ||
770 | |||
771 | { &place_recv_message_ack, NULL, | ||
772 | GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK, | ||
773 | sizeof (struct GNUNET_MessageHeader), GNUNET_NO }, | ||
774 | |||
775 | { &guest_recv_join_decision, NULL, | ||
776 | GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, | ||
777 | sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES }, | ||
778 | |||
779 | { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO }, | ||
780 | |||
781 | { NULL, NULL, 0, 0, GNUNET_NO } | ||
782 | }; | ||
783 | |||
784 | |||
785 | static void | ||
786 | place_cleanup (struct GNUNET_SOCIAL_Place *plc) | ||
787 | { | ||
788 | GNUNET_PSYC_transmit_destroy (plc->tmit); | ||
789 | GNUNET_PSYC_receive_destroy (plc->recv); | ||
790 | GNUNET_free (plc->connect_msg); | ||
791 | if (NULL != plc->disconnect_cb) | ||
792 | plc->disconnect_cb (plc->disconnect_cls); | ||
793 | } | ||
794 | |||
795 | |||
796 | static void | ||
797 | host_cleanup (void *cls) | ||
798 | { | ||
799 | struct GNUNET_SOCIAL_Host *hst = cls; | ||
800 | place_cleanup (&hst->plc); | ||
801 | GNUNET_free (hst); | ||
802 | } | ||
803 | |||
180 | 804 | ||
805 | static void | ||
806 | guest_cleanup (void *cls) | ||
807 | { | ||
808 | struct GNUNET_SOCIAL_Guest *gst = cls; | ||
809 | place_cleanup (&gst->plc); | ||
810 | GNUNET_free (gst); | ||
181 | } | 811 | } |
182 | 812 | ||
183 | 813 | ||
@@ -187,46 +817,179 @@ GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer) | |||
187 | * A place is created upon first entering, and it is active until permanently | 817 | * A place is created upon first entering, and it is active until permanently |
188 | * left using GNUNET_SOCIAL_host_leave(). | 818 | * left using GNUNET_SOCIAL_host_leave(). |
189 | * | 819 | * |
190 | * @param cfg Configuration to contact the social service. | 820 | * @param cfg |
191 | * @param place_keyfile File with the private-public key pair of the place, | 821 | * Configuration to contact the social service. |
192 | * created if the file does not exist; pass NULL for ephemeral places. | 822 | * @param ego |
193 | * @param policy Policy specifying entry and history restrictions of the place. | 823 | * Identity of the host. |
194 | * @param ego Identity of the host. | 824 | * @param place_key |
195 | * @param slicer Slicer to handle incoming messages. | 825 | * Private-public key pair of the place. |
196 | * @param listener_cb Function to handle new nyms that want to enter. | 826 | * NULL for ephemeral places. |
197 | * @param farewell_cb Function to handle departing nyms. | 827 | * @param policy |
198 | * @param cls Closure for @a listener_cb and @a farewell_cb. | 828 | * Policy specifying entry and history restrictions for the place. |
829 | * @param slicer | ||
830 | * Slicer to handle incoming messages. | ||
831 | * @param answer_door_cb | ||
832 | * Function to handle new nyms that want to enter. | ||
833 | * @param farewell_cb | ||
834 | * Function to handle departing nyms. | ||
835 | * @param cls | ||
836 | * Closure for the callbacks. | ||
199 | * | 837 | * |
200 | * @return Handle for the host. | 838 | * @return Handle for the host. |
201 | */ | 839 | */ |
202 | struct GNUNET_SOCIAL_Host * | 840 | struct GNUNET_SOCIAL_Host * |
203 | GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, | 841 | GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, |
204 | const char *place_keyfile, | 842 | const struct GNUNET_IDENTITY_Ego *ego, |
843 | const struct GNUNET_CRYPTO_EddsaPrivateKey *place_key, | ||
205 | enum GNUNET_PSYC_Policy policy, | 844 | enum GNUNET_PSYC_Policy policy, |
206 | struct GNUNET_IDENTITY_Ego *ego, | ||
207 | struct GNUNET_SOCIAL_Slicer *slicer, | 845 | struct GNUNET_SOCIAL_Slicer *slicer, |
208 | GNUNET_SOCIAL_AnswerDoorCallback listener_cb, | 846 | GNUNET_SOCIAL_HostEnterCallback enter_cb, |
847 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, | ||
209 | GNUNET_SOCIAL_FarewellCallback farewell_cb, | 848 | GNUNET_SOCIAL_FarewellCallback farewell_cb, |
210 | void *cls) | 849 | void *cls) |
211 | { | 850 | { |
212 | return NULL; | 851 | struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst)); |
852 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
853 | struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req)); | ||
854 | |||
855 | if (NULL != place_key) | ||
856 | { | ||
857 | hst->place_key = *place_key; | ||
858 | } | ||
859 | else | ||
860 | { | ||
861 | struct GNUNET_CRYPTO_EddsaPrivateKey * | ||
862 | ephemeral_key = GNUNET_CRYPTO_eddsa_key_create (); | ||
863 | hst->place_key = *ephemeral_key; | ||
864 | GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key); | ||
865 | GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key); | ||
866 | GNUNET_free (ephemeral_key); | ||
867 | } | ||
868 | plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
869 | |||
870 | req->header.size = htons (sizeof (*req)); | ||
871 | req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER); | ||
872 | req->policy = policy; | ||
873 | req->place_key = hst->place_key; | ||
874 | req->host_key = plc->ego_key; | ||
875 | |||
876 | plc->connect_msg = (struct GNUNET_MessageHeader *) req; | ||
877 | plc->cfg = cfg; | ||
878 | plc->is_host = GNUNET_YES; | ||
879 | plc->slicer = slicer; | ||
880 | |||
881 | hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
882 | hst->enter_cb = enter_cb; | ||
883 | hst->answer_door_cb = answer_door_cb; | ||
884 | hst->cb_cls = cls; | ||
885 | |||
886 | plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers); | ||
887 | GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc)); | ||
888 | |||
889 | plc->tmit = GNUNET_PSYC_transmit_create (plc->client); | ||
890 | plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer); | ||
891 | |||
892 | place_send_connect_msg (plc); | ||
893 | return hst; | ||
213 | } | 894 | } |
214 | 895 | ||
215 | 896 | ||
216 | /** | 897 | /** |
217 | * Admit @a nym to the place. | 898 | * Enter a place as host. |
218 | * | 899 | * |
219 | * The @a nym reference will remain valid until either the @a host or @a nym | 900 | * A place is created upon first entering, and it is active until permanently |
220 | * leaves the place. | 901 | * left using GNUNET_SOCIAL_host_leave(). |
221 | * | 902 | * |
222 | * @param host Host of the place. | 903 | * @param cfg |
223 | * @param nym Handle for the entity that wants to enter. | 904 | * Configuration to contact the social service. |
905 | * @param ego | ||
906 | * Identity of the host. | ||
907 | * @param gns_name | ||
908 | * GNS name in the zone of the @a ego that contains the | ||
909 | * public key of the place in a PLACE record. | ||
910 | * @param policy | ||
911 | * Policy specifying entry and history restrictions for the place. | ||
912 | * @param slicer | ||
913 | * Slicer to handle incoming messages. | ||
914 | * @param answer_door_cb | ||
915 | * Function to handle new nyms that want to enter. | ||
916 | * @param farewell_cb | ||
917 | * Function to handle departing nyms. | ||
918 | * @param cls | ||
919 | * Closure for the callbacks. | ||
920 | * | ||
921 | * @return Handle for the host. | ||
224 | */ | 922 | */ |
225 | void | 923 | struct GNUNET_SOCIAL_Host * |
226 | GNUNET_SOCIAL_host_admit (struct GNUNET_SOCIAL_Host *host, | 924 | GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, |
227 | struct GNUNET_SOCIAL_Nym *nym) | 925 | struct GNUNET_IDENTITY_Ego *ego, |
926 | const char *gns_name, | ||
927 | enum GNUNET_PSYC_Policy policy, | ||
928 | struct GNUNET_SOCIAL_Slicer *slicer, | ||
929 | GNUNET_SOCIAL_HostEnterCallback enter_cb, | ||
930 | GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, | ||
931 | GNUNET_SOCIAL_FarewellCallback farewell_cb, | ||
932 | void *cls) | ||
228 | { | 933 | { |
934 | struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {}; | ||
229 | 935 | ||
936 | /* FIXME: | ||
937 | * 1. get public key by looking up PLACE entry under gns_name | ||
938 | * in the zone of the ego. | ||
939 | * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH | ||
940 | */ | ||
941 | |||
942 | return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer, | ||
943 | enter_cb, answer_door_cb, farewell_cb, cls); | ||
944 | } | ||
945 | |||
946 | |||
947 | /** | ||
948 | * Decision whether to admit @a nym into the place or refuse entry. | ||
949 | * | ||
950 | * @param hst | ||
951 | * Host of the place. | ||
952 | * @param nym | ||
953 | * Handle for the entity that wanted to enter. | ||
954 | * @param is_admitted | ||
955 | * #GNUNET_YES if @a nym is admitted, | ||
956 | * #GNUNET_NO if @a nym is refused entry, | ||
957 | * #GNUNET_SYSERR if we cannot answer the request. | ||
958 | * @param method_name | ||
959 | * Method name for the rejection message. | ||
960 | * @param env | ||
961 | * Environment containing variables for the message, or NULL. | ||
962 | * @param data | ||
963 | * Data for the rejection message to send back. | ||
964 | * @param data_size | ||
965 | * Number of bytes in @a data for method. | ||
966 | * @return #GNUNET_OK on success, | ||
967 | * #GNUNET_SYSERR if the message is too large. | ||
968 | */ | ||
969 | int | ||
970 | GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst, | ||
971 | struct GNUNET_SOCIAL_Nym *nym, | ||
972 | int is_admitted, | ||
973 | const struct GNUNET_PSYC_Message *entry_resp) | ||
974 | { | ||
975 | struct GNUNET_PSYC_JoinDecisionMessage *dcsn; | ||
976 | uint16_t entry_resp_size | ||
977 | = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0; | ||
978 | |||
979 | if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size) | ||
980 | return GNUNET_SYSERR; | ||
981 | |||
982 | dcsn = GNUNET_malloc (sizeof (*dcsn) + entry_resp_size); | ||
983 | dcsn->header.size = htons (sizeof (*dcsn) + entry_resp_size); | ||
984 | dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION); | ||
985 | dcsn->is_admitted = htonl (is_admitted); | ||
986 | dcsn->slave_key = nym->pub_key; | ||
987 | |||
988 | if (0 < entry_resp_size) | ||
989 | memcpy (&dcsn[1], entry_resp, entry_resp_size); | ||
990 | |||
991 | GNUNET_CLIENT_MANAGER_transmit (hst->plc.client, &dcsn->header); | ||
992 | return GNUNET_OK; | ||
230 | } | 993 | } |
231 | 994 | ||
232 | 995 | ||
@@ -249,63 +1012,60 @@ GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *host, | |||
249 | 1012 | ||
250 | 1013 | ||
251 | /** | 1014 | /** |
252 | * Refuse @a nym entry into the place. | 1015 | * Get the public key of a @a nym. |
253 | * | 1016 | * |
254 | * @param host Host of the place. | 1017 | * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name(). |
255 | * @param nym Handle for the entity that wanted to enter. | 1018 | * |
256 | * @param method_name Method name for the rejection message. | 1019 | * @param nym Pseudonym to map to a cryptographic identifier. |
257 | * @param env Environment containing variables for the message, or NULL. | 1020 | * @param[out] nym_key Set to the public key of the nym. |
258 | * @param data Data for the rejection message to send back. | ||
259 | * @param data_size Number of bytes in @a data for method. | ||
260 | */ | 1021 | */ |
261 | void | 1022 | struct GNUNET_CRYPTO_EcdsaPublicKey * |
262 | GNUNET_SOCIAL_host_refuse_entry (struct GNUNET_SOCIAL_Host *host, | 1023 | GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym) |
263 | struct GNUNET_SOCIAL_Nym *nym, | ||
264 | const char *method_name, | ||
265 | const struct GNUNET_ENV_Environment *env, | ||
266 | const void *data, | ||
267 | size_t data_size) | ||
268 | { | 1024 | { |
269 | 1025 | return &nym->pub_key; | |
270 | } | 1026 | } |
271 | 1027 | ||
272 | 1028 | ||
273 | /** | 1029 | /** |
274 | * Get the public key of a @a nym. | 1030 | * Obtain the private-public key pair of the hosted place. |
275 | * | 1031 | * |
276 | * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name(). | 1032 | * The public part is suitable for storing in GNS within a PLACE record, |
1033 | * along with peer IDs to join at. | ||
277 | * | 1034 | * |
278 | * @param nym Pseudonym to map to a cryptographic identifier. | 1035 | * @param host |
279 | * @param[out] nym_key Set to the public key of the nym. | 1036 | * Host of the place. |
1037 | * | ||
1038 | * @return Private-public key pair of the hosted place. | ||
280 | */ | 1039 | */ |
281 | void | 1040 | const struct GNUNET_CRYPTO_EddsaPrivateKey * |
282 | GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym, | 1041 | GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst) |
283 | struct GNUNET_CRYPTO_EddsaPublicKey *nym_key) | 1042 | { |
1043 | return &hst->place_key; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | static void | ||
1048 | namestore_result_host_advertise (void *cls, int32_t success, const char *emsg) | ||
284 | { | 1049 | { |
285 | 1050 | ||
286 | } | 1051 | } |
287 | 1052 | ||
288 | 1053 | ||
289 | /** | 1054 | /** |
290 | * Obtain the private-public key pair of the host. | 1055 | * Connected to core service. |
291 | * | ||
292 | * @param host Host to get the key of. | ||
293 | * @param[out] host_key Set to the private-public key pair of the host. The | ||
294 | * public part is suitable for storing in GNS within a "PLACE" | ||
295 | * record, along with peer IDs to join at. | ||
296 | */ | 1056 | */ |
297 | void | 1057 | static void |
298 | GNUNET_SOCIAL_host_get_key (struct GNUNET_SOCIAL_Host *host, | 1058 | core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) |
299 | struct GNUNET_CRYPTO_EddsaPrivateKey *host_key) | ||
300 | { | 1059 | { |
301 | 1060 | this_peer = *my_identity; | |
1061 | // FIXME | ||
302 | } | 1062 | } |
303 | 1063 | ||
304 | 1064 | ||
305 | /** | 1065 | /** |
306 | * Advertise the place in the GNS zone of the @e ego of the @a host. | 1066 | * Advertise the place in the GNS zone of the @e ego of the @a host. |
307 | * | 1067 | * |
308 | * @param host Host of the place. | 1068 | * @param hst Host of the place. |
309 | * @param name The name for the PLACE record to put in the zone. | 1069 | * @param name The name for the PLACE record to put in the zone. |
310 | * @param peer_count Number of elements in the @a peers array. | 1070 | * @param peer_count Number of elements in the @a peers array. |
311 | * @param peers List of peers in the PLACE record that can be used to send join | 1071 | * @param peers List of peers in the PLACE record that can be used to send join |
@@ -314,14 +1074,37 @@ GNUNET_SOCIAL_host_get_key (struct GNUNET_SOCIAL_Host *host, | |||
314 | * @param password Password used to encrypt the record. | 1074 | * @param password Password used to encrypt the record. |
315 | */ | 1075 | */ |
316 | void | 1076 | void |
317 | GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host, | 1077 | GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst, |
318 | const char *name, | 1078 | const char *name, |
319 | size_t peer_count, | 1079 | size_t peer_count, |
320 | const struct GNUNET_PeerIdentity *peers, | 1080 | const struct GNUNET_PeerIdentity *peers, |
321 | struct GNUNET_TIME_Relative expiration_time, | 1081 | struct GNUNET_TIME_Relative expiration_time, |
322 | const char *password) | 1082 | const char *password) |
323 | { | 1083 | { |
324 | 1084 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | |
1085 | if (NULL == namestore) | ||
1086 | namestore = GNUNET_NAMESTORE_connect (plc->cfg); | ||
1087 | if (NULL == core) | ||
1088 | core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL, | ||
1089 | NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); | ||
1090 | |||
1091 | struct GNUNET_GNSRECORD_Data rd = { 0 }; | ||
1092 | rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE; | ||
1093 | rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1094 | rd.expiration_time | ||
1095 | = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, 1).rel_value_us; | ||
1096 | |||
1097 | struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec)); | ||
1098 | rec->place_key = plc->pub_key; | ||
1099 | rec->origin = this_peer; | ||
1100 | rec->relay_count = htons (0); // FIXME | ||
1101 | |||
1102 | rd.data_size = sizeof (*rec); | ||
1103 | rd.data = rec; | ||
1104 | |||
1105 | GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key, | ||
1106 | name, 1, &rd, namestore_result_host_advertise, | ||
1107 | hst); | ||
325 | } | 1108 | } |
326 | 1109 | ||
327 | 1110 | ||
@@ -342,26 +1125,43 @@ GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host, | |||
342 | * @return NULL on error (announcement already in progress?). | 1125 | * @return NULL on error (announcement already in progress?). |
343 | */ | 1126 | */ |
344 | struct GNUNET_SOCIAL_Announcement * | 1127 | struct GNUNET_SOCIAL_Announcement * |
345 | GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *host, | 1128 | GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst, |
346 | const char *method_name, | 1129 | const char *method_name, |
347 | const struct GNUNET_ENV_Environment *env, | 1130 | const struct GNUNET_ENV_Environment *env, |
348 | GNUNET_CONNECTION_TransmitReadyNotify notify, | 1131 | GNUNET_PSYC_TransmitNotifyData notify_data, |
349 | void *notify_cls, | 1132 | void *notify_data_cls, |
350 | enum GNUNET_SOCIAL_AnnounceFlags flags) | 1133 | enum GNUNET_SOCIAL_AnnounceFlags flags) |
351 | { | 1134 | { |
352 | return NULL; | 1135 | if (GNUNET_OK == |
1136 | GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env, | ||
1137 | NULL, notify_data, notify_data_cls, flags)); | ||
1138 | return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit; | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | /** | ||
1143 | * Resume transmitting announcement. | ||
1144 | * | ||
1145 | * @param a | ||
1146 | * The announcement to resume. | ||
1147 | */ | ||
1148 | void | ||
1149 | GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a) | ||
1150 | { | ||
1151 | GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a); | ||
353 | } | 1152 | } |
354 | 1153 | ||
355 | 1154 | ||
356 | /** | 1155 | /** |
357 | * Cancel announcement. | 1156 | * Cancel announcement. |
358 | * | 1157 | * |
359 | * @param a The announcement to cancel. | 1158 | * @param a |
1159 | * The announcement to cancel. | ||
360 | */ | 1160 | */ |
361 | void | 1161 | void |
362 | GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a) | 1162 | GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a) |
363 | { | 1163 | { |
364 | 1164 | GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a); | |
365 | } | 1165 | } |
366 | 1166 | ||
367 | 1167 | ||
@@ -375,9 +1175,9 @@ GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a) | |||
375 | * @return Handle for the hosted place, valid as long as @a host is valid. | 1175 | * @return Handle for the hosted place, valid as long as @a host is valid. |
376 | */ | 1176 | */ |
377 | struct GNUNET_SOCIAL_Place * | 1177 | struct GNUNET_SOCIAL_Place * |
378 | GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *host) | 1178 | GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst) |
379 | { | 1179 | { |
380 | return NULL; | 1180 | return &hst->plc; |
381 | } | 1181 | } |
382 | 1182 | ||
383 | 1183 | ||
@@ -390,22 +1190,65 @@ GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *host) | |||
390 | * @param keep_active Keep the place active after last host disconnected. | 1190 | * @param keep_active Keep the place active after last host disconnected. |
391 | */ | 1191 | */ |
392 | void | 1192 | void |
393 | GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active) | 1193 | GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst, |
1194 | int keep_active, | ||
1195 | GNUNET_ContinuationCallback leave_cb, | ||
1196 | void *leave_cls) | ||
394 | { | 1197 | { |
1198 | struct GNUNET_SOCIAL_Place *plc = &hst->plc; | ||
1199 | |||
1200 | /* FIXME: send msg to service */ | ||
1201 | |||
1202 | plc->is_disconnecting = GNUNET_YES; | ||
1203 | plc->disconnect_cb = leave_cb; | ||
1204 | plc->disconnect_cls = leave_cls; | ||
395 | 1205 | ||
1206 | GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES, | ||
1207 | &host_cleanup, hst); | ||
396 | } | 1208 | } |
397 | 1209 | ||
398 | 1210 | ||
1211 | static struct GuestEnterRequest * | ||
1212 | guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key, | ||
1213 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_key, | ||
1214 | const struct GNUNET_PeerIdentity *origin, | ||
1215 | size_t relay_count, | ||
1216 | const struct GNUNET_PeerIdentity *relays, | ||
1217 | const struct GNUNET_PSYC_Message *join_msg) | ||
1218 | { | ||
1219 | uint16_t join_msg_size = ntohs (join_msg->header.size); | ||
1220 | uint16_t relay_size = relay_count * sizeof (*relays); | ||
1221 | |||
1222 | struct GuestEnterRequest * | ||
1223 | req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size); | ||
1224 | |||
1225 | req->header.size = htons (sizeof (*req) + relay_size + join_msg_size); | ||
1226 | req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER); | ||
1227 | req->place_key = *place_key; | ||
1228 | req->guest_key = *guest_key; | ||
1229 | req->origin = *origin; | ||
1230 | req->relay_count = relay_count; | ||
1231 | |||
1232 | uint16_t p = sizeof (*req); | ||
1233 | if (0 < relay_size) | ||
1234 | { | ||
1235 | memcpy ((char *) req + p, relays, relay_size); | ||
1236 | p += relay_size; | ||
1237 | } | ||
1238 | |||
1239 | memcpy ((char *) req + p, join_msg, join_msg_size); | ||
1240 | return req; | ||
1241 | } | ||
1242 | |||
399 | /** | 1243 | /** |
400 | * Request entry to a place as a guest. | 1244 | * Request entry to a place as a guest. |
401 | * | 1245 | * |
402 | * @param cfg Configuration to contact the social service. | 1246 | * @param cfg Configuration to contact the social service. |
403 | * @param ego Identity of the guest. | 1247 | * @param ego Identity of the guest. |
404 | * @param address GNS name of the place to enter. Either in the form of | 1248 | * @param crypto_address Public key of the place to enter. |
405 | * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to | 1249 | * @param origin Peer identity of the origin of the underlying multicast group. |
406 | * the 'PLACE' record of the empty label ("+") in the GNS zone with the | 1250 | * @param relay_count Number of elements in the @a relays array. |
407 | * nym's public key 'NYMPUBKEY', and can be used to request entry to a | 1251 | * @param relays Relays for the underlying multicast group. |
408 | * pseudonym's place directly. | ||
409 | * @param method_name Method name for the message. | 1252 | * @param method_name Method name for the message. |
410 | * @param env Environment containing variables for the message, or NULL. | 1253 | * @param env Environment containing variables for the message, or NULL. |
411 | * @param data Payload for the message to give to the enter callback. | 1254 | * @param data Payload for the message to give to the enter callback. |
@@ -416,26 +1259,132 @@ GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active) | |||
416 | */ | 1259 | */ |
417 | struct GNUNET_SOCIAL_Guest * | 1260 | struct GNUNET_SOCIAL_Guest * |
418 | GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, | 1261 | GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, |
419 | struct GNUNET_IDENTITY_Ego *ego, | 1262 | const struct GNUNET_IDENTITY_Ego *ego, |
420 | char *address, | 1263 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_key, |
421 | const char *method_name, | 1264 | const struct GNUNET_PeerIdentity *origin, |
422 | const struct GNUNET_ENV_Environment *env, | 1265 | uint32_t relay_count, |
423 | const void *data, | 1266 | const struct GNUNET_PeerIdentity *relays, |
424 | size_t data_size, | 1267 | const struct GNUNET_PSYC_Message *entry_msg, |
425 | struct GNUNET_SOCIAL_Slicer *slicer) | 1268 | struct GNUNET_SOCIAL_Slicer *slicer, |
1269 | GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, | ||
1270 | GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, | ||
1271 | void *cls) | ||
426 | { | 1272 | { |
427 | return NULL; | 1273 | struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); |
1274 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1275 | |||
1276 | struct GuestEnterRequest * | ||
1277 | req = guest_enter_request_create (&plc->ego_key, place_key, origin, | ||
1278 | relay_count, relays, entry_msg); | ||
1279 | plc->connect_msg = &req->header; | ||
1280 | plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1281 | plc->pub_key = *place_key; | ||
1282 | plc->cfg = cfg; | ||
1283 | plc->is_host = GNUNET_YES; | ||
1284 | plc->slicer = slicer; | ||
1285 | |||
1286 | gst->enter_cb = local_enter_cb; | ||
1287 | gst->entry_dcsn_cb = entry_dcsn_cb; | ||
1288 | gst->cb_cls = cls; | ||
1289 | |||
1290 | plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers); | ||
1291 | GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); | ||
1292 | |||
1293 | plc->tmit = GNUNET_PSYC_transmit_create (plc->client); | ||
1294 | plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer); | ||
1295 | |||
1296 | place_send_connect_msg (plc); | ||
1297 | return gst; | ||
1298 | } | ||
1299 | |||
1300 | |||
1301 | /** | ||
1302 | * Result of a GNS name lookup for entering a place. | ||
1303 | * | ||
1304 | * @see GNUNET_SOCIAL_guest_enter_by_name | ||
1305 | */ | ||
1306 | static void | ||
1307 | gns_result_guest_enter (void *cls, uint32_t rd_count, | ||
1308 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1309 | { | ||
1310 | struct GNUNET_SOCIAL_Guest *gst = cls; | ||
1311 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1312 | |||
1313 | const struct GNUNET_GNSRECORD_PlaceData * | ||
1314 | rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data; | ||
1315 | |||
1316 | if (0 == rd_count) | ||
1317 | { | ||
1318 | if (NULL != gst->enter_cb) | ||
1319 | gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0); | ||
1320 | return; | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | if (rd->data_size < sizeof (*rec)) | ||
1325 | { | ||
1326 | GNUNET_break_op (0); | ||
1327 | if (NULL != gst->enter_cb) | ||
1328 | gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0); | ||
1329 | return; | ||
1330 | } | ||
1331 | |||
1332 | struct GuestEnterRequest * | ||
1333 | req = (struct GuestEnterRequest *) plc->connect_msg; | ||
1334 | uint16_t req_size = ntohs (req->header.size); | ||
1335 | |||
1336 | struct GNUNET_PeerIdentity *relays = NULL; | ||
1337 | uint16_t relay_count = ntohs (rec->relay_count); | ||
1338 | |||
1339 | if (0 < relay_count) | ||
1340 | { | ||
1341 | uint16_t relay_size = relay_count * sizeof (struct GNUNET_PeerIdentity); | ||
1342 | struct GuestEnterRequest * | ||
1343 | req2 = GNUNET_malloc (req_size + relay_size); | ||
1344 | |||
1345 | req2->header.size = htons (req_size + relay_size); | ||
1346 | req2->header.type = req->header.type; | ||
1347 | req2->guest_key = req->guest_key; | ||
1348 | |||
1349 | uint16_t p = sizeof (*req); | ||
1350 | if (0 < relay_size) | ||
1351 | { | ||
1352 | memcpy ((char *) req2 + p, relays, relay_size); | ||
1353 | p += relay_size; | ||
1354 | } | ||
1355 | |||
1356 | memcpy ((char *) req + p, &req[1], req_size - sizeof (*req)); | ||
1357 | |||
1358 | plc->connect_msg = &req2->header; | ||
1359 | GNUNET_free (req); | ||
1360 | req = req2; | ||
1361 | } | ||
1362 | |||
1363 | req->place_key = rec->place_key; | ||
1364 | req->origin = rec->origin; | ||
1365 | req->relay_count = rec->relay_count; | ||
1366 | memcpy (&req[1], &rec[1], | ||
1367 | ntohl (rec->relay_count) * sizeof (struct GNUNET_PeerIdentity)); | ||
1368 | |||
1369 | plc->connect_msg = &req->header; | ||
1370 | plc->pub_key = req->place_key; | ||
1371 | |||
1372 | plc->tmit = GNUNET_PSYC_transmit_create (plc->client); | ||
1373 | plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc); | ||
1374 | |||
1375 | place_send_connect_msg (plc); | ||
428 | } | 1376 | } |
429 | 1377 | ||
430 | /** | 1378 | /** |
431 | * Request entry to a place as a guest. | 1379 | * Request entry to a place as a guest. |
432 | * | 1380 | * |
433 | * @param cfg Configuration to contact the social service. | 1381 | * @param cfg Configuration to contact the social service. |
434 | * @param ego Identity of the guest. | 1382 | * @param ego Identity of the guest. |
435 | * @param crypto_address Public key of the place to enter. | 1383 | * @param address GNS name of the place to enter. Either in the form of |
436 | * @param origin Peer identity of the origin of the underlying multicast group. | 1384 | * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to |
437 | * @param relay_count Number of elements in the @a relays array. | 1385 | * the 'PLACE' record of the empty label ("+") in the GNS zone with the |
438 | * @param relays Relays for the underlying multicast group. | 1386 | * nym's public key 'NYMPUBKEY', and can be used to request entry to a |
1387 | * pseudonym's place directly. | ||
439 | * @param method_name Method name for the message. | 1388 | * @param method_name Method name for the message. |
440 | * @param env Environment containing variables for the message, or NULL. | 1389 | * @param env Environment containing variables for the message, or NULL. |
441 | * @param data Payload for the message to give to the enter callback. | 1390 | * @param data Payload for the message to give to the enter callback. |
@@ -445,41 +1394,75 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
445 | * @return NULL on errors, otherwise handle for the guest. | 1394 | * @return NULL on errors, otherwise handle for the guest. |
446 | */ | 1395 | */ |
447 | struct GNUNET_SOCIAL_Guest * | 1396 | struct GNUNET_SOCIAL_Guest * |
448 | GNUNET_SOCIAL_guest_enter2 (const struct GNUNET_CONFIGURATION_Handle *cfg, | 1397 | GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, |
449 | struct GNUNET_IDENTITY_Ego *ego, | 1398 | struct GNUNET_IDENTITY_Ego *ego, |
450 | struct GNUNET_CRYPTO_EddsaPublicKey *crypto_address, | 1399 | char *gns_name, |
451 | struct GNUNET_PeerIdentity *origin, | 1400 | const struct GNUNET_PSYC_Message *join_msg, |
452 | size_t relay_count, | 1401 | struct GNUNET_SOCIAL_Slicer *slicer, |
453 | struct GNUNET_PeerIdentity *relays, | 1402 | GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, |
454 | const char *method_name, | 1403 | GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb, |
455 | const struct GNUNET_ENV_Environment *env, | 1404 | void *cls) |
456 | const void *data, | ||
457 | size_t data_size, | ||
458 | struct GNUNET_SOCIAL_Slicer *slicer) | ||
459 | { | 1405 | { |
460 | return NULL; | 1406 | struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); |
1407 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1408 | |||
1409 | gst->enter_cb = local_enter_cb; | ||
1410 | gst->cb_cls = cls; | ||
1411 | |||
1412 | plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1413 | plc->cfg = cfg; | ||
1414 | plc->is_host = GNUNET_NO; | ||
1415 | plc->slicer = slicer; | ||
1416 | |||
1417 | struct GuestEnterRequest * | ||
1418 | req = guest_enter_request_create (&plc->ego_key, NULL, NULL, 0, NULL, | ||
1419 | join_msg); | ||
1420 | plc->connect_msg = &req->header; | ||
1421 | |||
1422 | /* FIXME: get the public key of the origin and relays | ||
1423 | * by looking up the PLACE record of gns_name. | ||
1424 | */ | ||
1425 | if (NULL == gns) | ||
1426 | gns = GNUNET_GNS_connect (cfg); | ||
1427 | |||
1428 | plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers); | ||
1429 | GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); | ||
1430 | |||
1431 | struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; | ||
1432 | GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key); | ||
1433 | GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key, | ||
1434 | GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT, | ||
1435 | NULL, gns_result_guest_enter, gst); | ||
1436 | |||
1437 | return gst; | ||
461 | } | 1438 | } |
462 | 1439 | ||
463 | 1440 | ||
464 | /** | 1441 | /** |
465 | * Talk to the host of the place. | 1442 | * Talk to the host of the place. |
466 | * | 1443 | * |
467 | * @param place Place where we want to talk to the host. | 1444 | * @param place |
468 | * @param method_name Method to invoke on the host. | 1445 | * Place where we want to talk to the host. |
469 | * @param env Environment containing variables for the message, or NULL. | 1446 | * @param method_name |
470 | * @param notify Function to use to get the payload for the method. | 1447 | * Method to invoke on the host. |
471 | * @param notify_cls Closure for @a notify. | 1448 | * @param env |
472 | * @param flags Flags for the message being sent. | 1449 | * Environment containing variables for the message, or NULL. |
1450 | * @param notify_data | ||
1451 | * Function to use to get the payload for the method. | ||
1452 | * @param notify_data_cls | ||
1453 | * Closure for @a notify_data. | ||
1454 | * @param flags | ||
1455 | * Flags for the message being sent. | ||
473 | * | 1456 | * |
474 | * @return NULL if we are already trying to talk to the host, | 1457 | * @return NULL if we are already trying to talk to the host, |
475 | * otherwise handle to cancel the request. | 1458 | * otherwise handle to cancel the request. |
476 | */ | 1459 | */ |
477 | struct GNUNET_SOCIAL_TalkRequest * | 1460 | struct GNUNET_SOCIAL_TalkRequest * |
478 | GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Place *place, | 1461 | GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *guest, |
479 | const char *method_name, | 1462 | const char *method_name, |
480 | const struct GNUNET_ENV_Environment *env, | 1463 | const struct GNUNET_ENV_Environment *env, |
481 | GNUNET_CONNECTION_TransmitReadyNotify notify, | 1464 | GNUNET_PSYC_TransmitNotifyData notify_data, |
482 | void *notify_cls, | 1465 | void *notify_data_cls, |
483 | enum GNUNET_SOCIAL_TalkFlags flags) | 1466 | enum GNUNET_SOCIAL_TalkFlags flags) |
484 | { | 1467 | { |
485 | return NULL; | 1468 | return NULL; |
@@ -487,14 +1470,28 @@ GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Place *place, | |||
487 | 1470 | ||
488 | 1471 | ||
489 | /** | 1472 | /** |
1473 | * Resume talking to the host of the place. | ||
1474 | * | ||
1475 | * @param tr | ||
1476 | * Talk request to resume. | ||
1477 | */ | ||
1478 | void | ||
1479 | GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr) | ||
1480 | { | ||
1481 | GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr); | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /** | ||
490 | * Cancel talking to the host of the place. | 1486 | * Cancel talking to the host of the place. |
491 | * | 1487 | * |
492 | * @param tr Talk request to cancel. | 1488 | * @param tr |
1489 | * Talk request to cancel. | ||
493 | */ | 1490 | */ |
494 | void | 1491 | void |
495 | GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr) | 1492 | GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr) |
496 | { | 1493 | { |
497 | 1494 | GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr); | |
498 | } | 1495 | } |
499 | 1496 | ||
500 | 1497 | ||
@@ -507,9 +1504,21 @@ GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr) | |||
507 | * @param keep_active Keep place active after last application disconnected. | 1504 | * @param keep_active Keep place active after last application disconnected. |
508 | */ | 1505 | */ |
509 | void | 1506 | void |
510 | GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Place *place, int keep_active) | 1507 | GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, |
1508 | int keep_active, | ||
1509 | GNUNET_ContinuationCallback leave_cb, | ||
1510 | void *leave_cls) | ||
511 | { | 1511 | { |
1512 | struct GNUNET_SOCIAL_Place *plc = &gst->plc; | ||
1513 | |||
1514 | /* FIXME: send msg to service */ | ||
1515 | |||
1516 | plc->is_disconnecting = GNUNET_YES; | ||
1517 | plc->disconnect_cb = leave_cb; | ||
1518 | plc->disconnect_cls = leave_cls; | ||
512 | 1519 | ||
1520 | GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES, | ||
1521 | &guest_cleanup, gst); | ||
513 | } | 1522 | } |
514 | 1523 | ||
515 | 1524 | ||
@@ -523,9 +1532,9 @@ GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Place *place, int keep_active) | |||
523 | * @return Handle for the place, valid as long as @a guest is valid. | 1532 | * @return Handle for the place, valid as long as @a guest is valid. |
524 | */ | 1533 | */ |
525 | struct GNUNET_SOCIAL_Place * | 1534 | struct GNUNET_SOCIAL_Place * |
526 | GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Host *guest) | 1535 | GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst) |
527 | { | 1536 | { |
528 | return NULL; | 1537 | return &gst->plc; |
529 | } | 1538 | } |
530 | 1539 | ||
531 | 1540 | ||
@@ -671,6 +1680,4 @@ GNUNET_SOCIAL_place_look_at (struct GNUNET_SOCIAL_Place *place, | |||
671 | } | 1680 | } |
672 | 1681 | ||
673 | 1682 | ||
674 | |||
675 | |||
676 | /* end of social_api.c */ | 1683 | /* end of social_api.c */ |
diff --git a/src/social/test_social.c b/src/social/test_social.c index 053e347d1..340c4482a 100644 --- a/src/social/test_social.c +++ b/src/social/test_social.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | * Boston, MA 02111-1307, USA. | 18 | * Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | |||
21 | /** | 20 | /** |
22 | * @file social/test_social.c | 21 | * @file social/test_social.c |
23 | * @brief Tests for the Social API. | 22 | * @brief Tests for the Social API. |
@@ -32,32 +31,132 @@ | |||
32 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
33 | #include "gnunet_testing_lib.h" | 32 | #include "gnunet_testing_lib.h" |
34 | #include "gnunet_env_lib.h" | 33 | #include "gnunet_env_lib.h" |
34 | #include "gnunet_psyc_util_lib.h" | ||
35 | #include "gnunet_social_service.h" | 35 | #include "gnunet_social_service.h" |
36 | #include "gnunet_core_service.h" | ||
37 | #include "gnunet_identity_service.h" | ||
36 | 38 | ||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | 39 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) |
38 | 40 | ||
39 | #define DEBUG_SERVICE 0 | 41 | #define DEBUG_SERVICE 0 |
42 | #define DATA2ARG(data) data, sizeof (data) | ||
40 | 43 | ||
41 | /** | 44 | /** |
42 | * Return value from 'main'. | 45 | * Return value from 'main'. |
43 | */ | 46 | */ |
44 | static int res; | 47 | int res; |
45 | |||
46 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
47 | 48 | ||
48 | /** | 49 | /** |
49 | * Handle for task for timeout termination. | 50 | * Handle for task for timeout termination. |
50 | */ | 51 | */ |
51 | static GNUNET_SCHEDULER_TaskIdentifier end_badly_task; | 52 | GNUNET_SCHEDULER_TaskIdentifier end_badly_task; |
53 | |||
54 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
55 | |||
56 | struct GNUNET_CORE_Handle *core; | ||
57 | struct GNUNET_PeerIdentity this_peer; | ||
58 | |||
59 | struct GNUNET_IDENTITY_Handle *id; | ||
60 | |||
61 | const struct GNUNET_IDENTITY_Ego *host_ego; | ||
62 | const struct GNUNET_IDENTITY_Ego *guest_ego; | ||
63 | |||
64 | const char *host_name = "Host One"; | ||
65 | const char *guest_name = "Guest One"; | ||
66 | |||
67 | struct GNUNET_CRYPTO_EddsaPrivateKey *place_key; | ||
68 | struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key; | ||
69 | |||
70 | struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key; | ||
71 | struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key; | ||
72 | |||
73 | struct GNUNET_SOCIAL_Slicer *host_slicer; | ||
74 | struct GNUNET_SOCIAL_Slicer *guest_slicer; | ||
75 | |||
76 | struct GNUNET_SOCIAL_Host *hst; | ||
77 | struct GNUNET_SOCIAL_Guest *gst; | ||
78 | |||
79 | struct GuestEnterMessage | ||
80 | { | ||
81 | struct GNUNET_PSYC_Message *msg; | ||
82 | const char *method_name; | ||
83 | struct GNUNET_ENV_Environment *env; | ||
84 | void *data; | ||
85 | uint16_t data_size; | ||
86 | } guest_enter_msg; | ||
87 | |||
88 | struct TransmitClosure | ||
89 | { | ||
90 | struct GNUNET_SOCIAL_Announcement *host_ann; | ||
91 | struct GNUNET_SOCIAL_TalkRequest *guest_talk; | ||
92 | struct GNUNET_ENV_Environment *env; | ||
93 | char *data[16]; | ||
94 | uint8_t data_delay[16]; | ||
95 | uint8_t data_count; | ||
96 | uint8_t paused; | ||
97 | uint8_t n; | ||
98 | } tmit; | ||
99 | |||
100 | uint8_t join_req_count; | ||
101 | struct GNUNET_PSYC_Message *join_resp; | ||
102 | |||
103 | enum | ||
104 | { | ||
105 | TEST_NONE = 0, | ||
106 | TEST_HOST_ANSWER_DOOR_REFUSE = 1, | ||
107 | TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 2, | ||
108 | TEST_HOST_ANSWER_DOOR_ADMIT = 3, | ||
109 | TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 4, | ||
110 | TEST_HOST_ANNOUNCE = 5, | ||
111 | TEST_HOST_ANNOUNCE_END = 6, | ||
112 | TEST_GUEST_TALK = 7, | ||
113 | TEST_GUEST_TALK_END = 8, | ||
114 | TEST_GUEST_LEAVE = 9, | ||
115 | TEST_HOST_LEAVE = 10, | ||
116 | } test; | ||
117 | |||
118 | |||
119 | void | ||
120 | guest_enter (); | ||
121 | |||
122 | |||
123 | void | ||
124 | guest_talk (); | ||
125 | |||
126 | |||
127 | void | ||
128 | host_announce2 (); | ||
52 | 129 | ||
53 | 130 | ||
54 | /** | 131 | /** |
55 | * Clean up all resources used. | 132 | * Clean up all resources used. |
56 | */ | 133 | */ |
57 | static void | 134 | void |
58 | cleanup () | 135 | cleanup () |
59 | { | 136 | { |
137 | if (NULL != core) | ||
138 | { | ||
139 | GNUNET_CORE_disconnect (core); | ||
140 | core = NULL; | ||
141 | } | ||
60 | 142 | ||
143 | if (NULL != id) | ||
144 | { | ||
145 | GNUNET_IDENTITY_disconnect (id); | ||
146 | id = NULL; | ||
147 | } | ||
148 | |||
149 | if (NULL != gst) | ||
150 | { | ||
151 | GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, NULL, NULL); | ||
152 | gst = NULL; | ||
153 | } | ||
154 | if (NULL != hst) | ||
155 | { | ||
156 | GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, NULL, NULL); | ||
157 | hst = NULL; | ||
158 | } | ||
159 | GNUNET_SCHEDULER_shutdown (); | ||
61 | } | 160 | } |
62 | 161 | ||
63 | 162 | ||
@@ -67,7 +166,7 @@ cleanup () | |||
67 | * @param cls NULL | 166 | * @param cls NULL |
68 | * @param tc scheduler context | 167 | * @param tc scheduler context |
69 | */ | 168 | */ |
70 | static void | 169 | void |
71 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 170 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
72 | { | 171 | { |
73 | res = 1; | 172 | res = 1; |
@@ -82,7 +181,7 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
82 | * @param cls NULL | 181 | * @param cls NULL |
83 | * @param tc scheduler context | 182 | * @param tc scheduler context |
84 | */ | 183 | */ |
85 | static void | 184 | void |
86 | end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 185 | end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
87 | { | 186 | { |
88 | res = 0; | 187 | res = 0; |
@@ -94,7 +193,7 @@ end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
94 | /** | 193 | /** |
95 | * Finish the test case (successfully). | 194 | * Finish the test case (successfully). |
96 | */ | 195 | */ |
97 | static void | 196 | void |
98 | end () | 197 | end () |
99 | { | 198 | { |
100 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n"); | 199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n"); |
@@ -109,6 +208,564 @@ end () | |||
109 | } | 208 | } |
110 | 209 | ||
111 | 210 | ||
211 | static void | ||
212 | transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
213 | { | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n"); | ||
215 | struct TransmitClosure *tmit = cls; | ||
216 | if (NULL != tmit->host_ann) | ||
217 | GNUNET_SOCIAL_host_announce_resume (tmit->host_ann); | ||
218 | else | ||
219 | GNUNET_SOCIAL_guest_talk_resume (tmit->guest_talk); | ||
220 | } | ||
221 | |||
222 | |||
223 | int | ||
224 | notify_data (void *cls, uint16_t *data_size, void *data) | ||
225 | { | ||
226 | struct TransmitClosure *tmit = cls; | ||
227 | if (NULL != tmit->env) | ||
228 | { | ||
229 | GNUNET_ENV_environment_destroy (tmit->env); | ||
230 | tmit->env = NULL; | ||
231 | } | ||
232 | if (0 == tmit->data_count) | ||
233 | { | ||
234 | *data_size = 0; | ||
235 | return GNUNET_YES; | ||
236 | } | ||
237 | |||
238 | uint16_t size = strlen (tmit->data[tmit->n]) + 1; | ||
239 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
240 | "Transmit notify data: %u bytes available, " | ||
241 | "processing fragment %u/%u (size %u).\n", | ||
242 | *data_size, tmit->n + 1, tmit->data_count, size); | ||
243 | if (*data_size < size) | ||
244 | { | ||
245 | *data_size = 0; | ||
246 | GNUNET_assert (0); | ||
247 | return GNUNET_SYSERR; | ||
248 | } | ||
249 | |||
250 | if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n]) | ||
251 | { | ||
252 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n"); | ||
253 | tmit->paused = GNUNET_YES; | ||
254 | GNUNET_SCHEDULER_add_delayed ( | ||
255 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
256 | tmit->data_delay[tmit->n]), | ||
257 | &transmit_resume, tmit); | ||
258 | *data_size = 0; | ||
259 | return GNUNET_NO; | ||
260 | } | ||
261 | tmit->paused = GNUNET_NO; | ||
262 | |||
263 | *data_size = size; | ||
264 | memcpy (data, tmit->data[tmit->n], size); | ||
265 | |||
266 | return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES; | ||
267 | } | ||
268 | |||
269 | |||
270 | void host_left () | ||
271 | { | ||
272 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
273 | "The host has left the place.\n"); | ||
274 | GNUNET_SOCIAL_slicer_destroy (host_slicer); | ||
275 | host_slicer = NULL; | ||
276 | hst = NULL; | ||
277 | |||
278 | end (); | ||
279 | } | ||
280 | |||
281 | |||
282 | void | ||
283 | schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
284 | { | ||
285 | test = TEST_HOST_LEAVE; | ||
286 | GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, &host_left, NULL); | ||
287 | } | ||
288 | |||
289 | |||
290 | void | ||
291 | host_farewell (void *cls, | ||
292 | struct GNUNET_SOCIAL_Nym *nym, | ||
293 | struct GNUNET_ENV_Environment *env, | ||
294 | size_t variable_count, | ||
295 | struct GNUNET_ENV_Modifier *variables) | ||
296 | { | ||
297 | struct GNUNET_CRYPTO_EcdsaPublicKey * | ||
298 | nym_key = GNUNET_SOCIAL_nym_get_key (nym); | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
300 | "Nym %s has left the place.\n", | ||
301 | GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key)); | ||
302 | GNUNET_assert (0 == memcmp (&guest_pub_key, nym_key, sizeof (*nym_key))); | ||
303 | |||
304 | GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL); | ||
305 | } | ||
306 | |||
307 | |||
308 | void | ||
309 | guest_left (void *cls) | ||
310 | { | ||
311 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
312 | "The guest has left the place.\n"); | ||
313 | GNUNET_SOCIAL_slicer_destroy (guest_slicer); | ||
314 | guest_slicer = NULL; | ||
315 | gst = NULL; | ||
316 | |||
317 | GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL); | ||
318 | } | ||
319 | |||
320 | |||
321 | void | ||
322 | schedule_guest_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
323 | { | ||
324 | test = TEST_GUEST_LEAVE; | ||
325 | /* FIXME test keep_active */ | ||
326 | GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, &guest_left, NULL); | ||
327 | } | ||
328 | |||
329 | |||
330 | |||
331 | void | ||
332 | guest_recv_method (void *cls, | ||
333 | const struct GNUNET_PSYC_MessageMethod *meth, | ||
334 | uint64_t message_id, | ||
335 | uint32_t flags, | ||
336 | const struct GNUNET_SOCIAL_Nym *nym, | ||
337 | const char *method_name) | ||
338 | { | ||
339 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
340 | "Test #%u: Guest received method for message ID %" PRIu64 ":\n" | ||
341 | "%s\n", | ||
342 | test, message_id, method_name); | ||
343 | /* FIXME: check message */ | ||
344 | } | ||
345 | |||
346 | |||
347 | void | ||
348 | guest_recv_modifier (void *cls, | ||
349 | const struct GNUNET_PSYC_MessageModifier *mod, | ||
350 | uint64_t message_id, | ||
351 | enum GNUNET_ENV_Operator oper, | ||
352 | const char *name, | ||
353 | const void *value, | ||
354 | uint16_t value_size) | ||
355 | { | ||
356 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
357 | "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n" | ||
358 | "%c%s: %.*s\n", | ||
359 | test, message_id, oper, name, value_size, value); | ||
360 | } | ||
361 | |||
362 | |||
363 | void | ||
364 | guest_recv_data (void *cls, | ||
365 | const struct GNUNET_MessageHeader *msg, | ||
366 | uint64_t message_id, | ||
367 | uint64_t data_offset, | ||
368 | const void *data, | ||
369 | uint16_t data_size) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
372 | "Test #%u: Guest received data for message ID %" PRIu64 ":\n" | ||
373 | "%.*s\n", | ||
374 | test, message_id, data_size, data); | ||
375 | } | ||
376 | |||
377 | |||
378 | void | ||
379 | guest_recv_eom (void *cls, | ||
380 | const struct GNUNET_MessageHeader *msg, | ||
381 | uint64_t message_id, | ||
382 | uint8_t cancelled) | ||
383 | { | ||
384 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
385 | "Test #%u: Guest received end of message ID %" PRIu64 | ||
386 | ", cancelled: %u\n", | ||
387 | test, message_id, cancelled); | ||
388 | |||
389 | switch (test) | ||
390 | { | ||
391 | case TEST_HOST_ANNOUNCE: | ||
392 | test = TEST_HOST_ANNOUNCE_END; | ||
393 | break; | ||
394 | |||
395 | case TEST_HOST_ANNOUNCE_END: | ||
396 | guest_talk (); | ||
397 | break; | ||
398 | |||
399 | case TEST_GUEST_TALK: | ||
400 | test = TEST_GUEST_TALK_END; | ||
401 | break; | ||
402 | |||
403 | case TEST_GUEST_TALK_END: | ||
404 | GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL); | ||
405 | break; | ||
406 | |||
407 | default: | ||
408 | GNUNET_assert (0); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | |||
413 | void | ||
414 | host_recv_method (void *cls, | ||
415 | const struct GNUNET_PSYC_MessageMethod *meth, | ||
416 | uint64_t message_id, | ||
417 | uint32_t flags, | ||
418 | const struct GNUNET_SOCIAL_Nym *nym, | ||
419 | const char *method_name) | ||
420 | { | ||
421 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
422 | "Test #%u: Host received method for message ID %" PRIu64 ":\n" | ||
423 | "%s\n", | ||
424 | test, message_id, method_name); | ||
425 | /* FIXME: check message */ | ||
426 | } | ||
427 | |||
428 | |||
429 | void | ||
430 | host_recv_modifier (void *cls, | ||
431 | const struct GNUNET_PSYC_MessageModifier *mod, | ||
432 | uint64_t message_id, | ||
433 | enum GNUNET_ENV_Operator oper, | ||
434 | const char *name, | ||
435 | const void *value, | ||
436 | uint16_t value_size) | ||
437 | { | ||
438 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
439 | "Test #%u: Host received modifier for message ID %" PRIu64 ":\n" | ||
440 | "%c%s: %.*s\n", | ||
441 | test, message_id, oper, name, value_size, value); | ||
442 | } | ||
443 | |||
444 | |||
445 | void | ||
446 | host_recv_data (void *cls, | ||
447 | const struct GNUNET_MessageHeader *msg, | ||
448 | uint64_t message_id, | ||
449 | uint64_t data_offset, | ||
450 | const void *data, | ||
451 | uint16_t data_size) | ||
452 | { | ||
453 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
454 | "Test #%u: Host received data for message ID %" PRIu64 ":\n" | ||
455 | "%.*s\n", | ||
456 | test, message_id, data_size, data); | ||
457 | } | ||
458 | |||
459 | |||
460 | void | ||
461 | host_recv_eom (void *cls, | ||
462 | const struct GNUNET_MessageHeader *msg, | ||
463 | uint64_t message_id, | ||
464 | uint8_t cancelled) | ||
465 | { | ||
466 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
467 | "Test #%u: Host received end of message ID %" PRIu64 | ||
468 | ", cancelled: %u\n", | ||
469 | test, message_id, cancelled); | ||
470 | |||
471 | switch (test) | ||
472 | { | ||
473 | case TEST_HOST_ANNOUNCE: | ||
474 | test = TEST_HOST_ANNOUNCE_END; | ||
475 | //host_announce2 (); | ||
476 | break; | ||
477 | |||
478 | case TEST_HOST_ANNOUNCE_END: | ||
479 | guest_talk (); | ||
480 | break; | ||
481 | |||
482 | case TEST_GUEST_TALK: | ||
483 | test = TEST_GUEST_TALK_END; | ||
484 | break; | ||
485 | |||
486 | case TEST_GUEST_TALK_END: | ||
487 | GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL); | ||
488 | break; | ||
489 | |||
490 | default: | ||
491 | GNUNET_assert (0); | ||
492 | } | ||
493 | } | ||
494 | |||
495 | |||
496 | void | ||
497 | guest_talk () | ||
498 | { | ||
499 | test = TEST_GUEST_TALK; | ||
500 | |||
501 | tmit = (struct TransmitClosure) {}; | ||
502 | tmit.env = GNUNET_ENV_environment_create (); | ||
503 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
504 | "_bar_foo", DATA2ARG ("one two three")); | ||
505 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
506 | "_bar_baz", DATA2ARG ("four five")); | ||
507 | tmit.data[0] = "zzz xxx yyy"; | ||
508 | tmit.data[1] = "zyx wvu tsr qpo"; | ||
509 | tmit.data[2] = "testing ten nine eight"; | ||
510 | tmit.data_count = 3; | ||
511 | |||
512 | tmit.host_ann | ||
513 | = GNUNET_SOCIAL_host_announce (hst, "_message_guest", tmit.env, | ||
514 | ¬ify_data, &tmit, | ||
515 | GNUNET_SOCIAL_TALK_NONE); | ||
516 | } | ||
517 | |||
518 | void | ||
519 | host_announce () | ||
520 | { | ||
521 | test = TEST_HOST_ANNOUNCE; | ||
522 | |||
523 | tmit = (struct TransmitClosure) {}; | ||
524 | tmit.env = GNUNET_ENV_environment_create (); | ||
525 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
526 | "_foo", DATA2ARG ("bar baz")); | ||
527 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
528 | "_foo_bar", DATA2ARG ("foo bar")); | ||
529 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
530 | "_foo_bar_baz", DATA2ARG ("foo bar baz")); | ||
531 | tmit.data[0] = "aaa bbb ccc"; | ||
532 | tmit.data[1] = "abc def ghi jkl"; | ||
533 | tmit.data[2] = "testing one two three"; | ||
534 | tmit.data[3] = "four five"; | ||
535 | tmit.data_count = 4; | ||
536 | |||
537 | tmit.host_ann | ||
538 | = GNUNET_SOCIAL_host_announce (hst, "_message_host", tmit.env, | ||
539 | ¬ify_data, &tmit, | ||
540 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
541 | } | ||
542 | |||
543 | void | ||
544 | host_announce2 () | ||
545 | { | ||
546 | test = TEST_HOST_ANNOUNCE; | ||
547 | |||
548 | tmit = (struct TransmitClosure) {}; | ||
549 | tmit.env = GNUNET_ENV_environment_create (); | ||
550 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
551 | "_foo2", DATA2ARG ("BAR BAZ")); | ||
552 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
553 | "_foo2_bar", DATA2ARG ("FOO BAR")); | ||
554 | GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, | ||
555 | "_foo2_bar", DATA2ARG ("FOO BAR BAZ")); | ||
556 | tmit.data[0] = "AAA BBB CCC"; | ||
557 | tmit.data[1] = "ABC DEF GHI JKL"; | ||
558 | tmit.data[2] = "TESTING ONE TWO THREE"; | ||
559 | tmit.data_count = 3; | ||
560 | |||
561 | tmit.host_ann | ||
562 | = GNUNET_SOCIAL_host_announce (hst, "_message_host_two", tmit.env, | ||
563 | ¬ify_data, &tmit, | ||
564 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
565 | } | ||
566 | |||
567 | |||
568 | void | ||
569 | guest_recv_entry_decision (void *cls, | ||
570 | int is_admitted, | ||
571 | const struct GNUNET_PSYC_Message *entry_resp) | ||
572 | { | ||
573 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
574 | "Guest received entry decision (try %u): %d.\n", | ||
575 | join_req_count, is_admitted); | ||
576 | |||
577 | if (NULL != entry_resp) | ||
578 | { | ||
579 | struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); | ||
580 | const char *method_name = NULL; | ||
581 | const void *data = NULL; | ||
582 | uint16_t data_size = 0; | ||
583 | GNUNET_PSYC_message_parse (entry_resp, &method_name, env, &data, &data_size); | ||
584 | |||
585 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
586 | "%s\n%.*s\n", | ||
587 | method_name, data_size, data); | ||
588 | /* FIXME: check response message */ | ||
589 | } | ||
590 | |||
591 | switch (test) | ||
592 | { | ||
593 | case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE: | ||
594 | GNUNET_assert (GNUNET_NO == is_admitted); | ||
595 | guest_enter (); | ||
596 | break; | ||
597 | |||
598 | case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT: | ||
599 | GNUNET_assert (GNUNET_YES == is_admitted); | ||
600 | host_announce (); | ||
601 | break; | ||
602 | |||
603 | default: | ||
604 | GNUNET_assert (0); | ||
605 | } | ||
606 | } | ||
607 | |||
608 | |||
609 | void | ||
610 | host_answer_door (void *cls, | ||
611 | struct GNUNET_SOCIAL_Nym *nym, | ||
612 | const char *method_name, | ||
613 | struct GNUNET_ENV_Environment *env, | ||
614 | size_t data_size, | ||
615 | const void *data) | ||
616 | { | ||
617 | join_req_count++; | ||
618 | |||
619 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
620 | "Host received entry request from guest (try %u).\n", | ||
621 | join_req_count); | ||
622 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
623 | "%s\n%.*s\n", | ||
624 | method_name, data_size, data); | ||
625 | |||
626 | switch (test) | ||
627 | { | ||
628 | case TEST_HOST_ANSWER_DOOR_REFUSE: | ||
629 | test = TEST_GUEST_RECV_ENTRY_DCSN_REFUSE; | ||
630 | join_resp = GNUNET_PSYC_message_create ("_refuse_nym", env, | ||
631 | DATA2ARG ("Go away!")); | ||
632 | GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, join_resp); | ||
633 | break; | ||
634 | |||
635 | case TEST_HOST_ANSWER_DOOR_ADMIT: | ||
636 | test = TEST_GUEST_RECV_ENTRY_DCSN_ADMIT; | ||
637 | join_resp = GNUNET_PSYC_message_create ("_admit_nym", env, | ||
638 | DATA2ARG ("Welcome, nym!")); | ||
639 | GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp); | ||
640 | break; | ||
641 | |||
642 | default: | ||
643 | GNUNET_assert (0); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | |||
648 | void | ||
649 | guest_recv_local_enter (void *cls, int result, uint64_t max_message_id) | ||
650 | { | ||
651 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Guest entered to local place.\n"); | ||
652 | |||
653 | } | ||
654 | |||
655 | |||
656 | void | ||
657 | guest_enter () | ||
658 | { | ||
659 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as guest.\n"); | ||
660 | |||
661 | struct GuestEnterMessage *emsg = &guest_enter_msg; | ||
662 | |||
663 | emsg->method_name = "_request_enter"; | ||
664 | emsg->env = GNUNET_ENV_environment_create (); | ||
665 | GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, | ||
666 | "_abc", "abc def", 7); | ||
667 | GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, | ||
668 | "_abc_def", "abc def ghi", 11); | ||
669 | emsg->data = "let me in"; | ||
670 | emsg->data_size = strlen (emsg->data) + 1; | ||
671 | emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env, | ||
672 | emsg->data, emsg->data_size); | ||
673 | |||
674 | gst = GNUNET_SOCIAL_guest_enter (cfg, guest_ego, &place_pub_key, | ||
675 | &this_peer, 0, NULL, emsg->msg, | ||
676 | guest_slicer, &guest_recv_local_enter, | ||
677 | &guest_recv_entry_decision, NULL); | ||
678 | } | ||
679 | |||
680 | |||
681 | void id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | ||
682 | { | ||
683 | GNUNET_assert (NULL != ego); | ||
684 | guest_ego = ego; | ||
685 | |||
686 | guest_slicer = GNUNET_SOCIAL_slicer_create (); | ||
687 | GNUNET_SOCIAL_slicer_add (guest_slicer, "", | ||
688 | &guest_recv_method, &guest_recv_modifier, | ||
689 | &guest_recv_data, &guest_recv_eom, NULL); | ||
690 | test = TEST_HOST_ANSWER_DOOR_ADMIT; | ||
691 | //host_announce (); | ||
692 | guest_enter (); | ||
693 | } | ||
694 | |||
695 | |||
696 | void id_guest_created (void *cls, const char *emsg) | ||
697 | { | ||
698 | if (NULL != emsg) | ||
699 | { | ||
700 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
701 | "Could not create guest identity: %s\n", emsg); | ||
702 | #if 0 == DEBUG_SERVICE | ||
703 | GNUNET_assert (0); | ||
704 | #endif | ||
705 | } | ||
706 | |||
707 | GNUNET_IDENTITY_ego_lookup (cfg, guest_name, &id_guest_ego_cb, NULL); | ||
708 | } | ||
709 | |||
710 | |||
711 | void host_entered (void *cls, uint64_t max_message_id) | ||
712 | { | ||
713 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host entered to place.\n"); | ||
714 | |||
715 | GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL); | ||
716 | } | ||
717 | |||
718 | |||
719 | void id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | ||
720 | { | ||
721 | GNUNET_assert (NULL != ego); | ||
722 | host_ego = ego; | ||
723 | |||
724 | host_slicer = GNUNET_SOCIAL_slicer_create (); | ||
725 | GNUNET_SOCIAL_slicer_add (host_slicer, "", | ||
726 | &host_recv_method, &host_recv_modifier, | ||
727 | &host_recv_data, &host_recv_eom, NULL); | ||
728 | |||
729 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n"); | ||
730 | hst = GNUNET_SOCIAL_host_enter (cfg, host_ego, place_key, | ||
731 | GNUNET_PSYC_CHANNEL_PRIVATE, host_slicer, | ||
732 | &host_entered, &host_answer_door, | ||
733 | &host_farewell, NULL); | ||
734 | } | ||
735 | |||
736 | |||
737 | void id_host_created (void *cls, const char *emsg) | ||
738 | { | ||
739 | if (NULL != emsg) | ||
740 | { | ||
741 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
742 | "Could not create host identity: %s\n", emsg); | ||
743 | #if 0 == DEBUG_SERVICE | ||
744 | GNUNET_assert (0); | ||
745 | #endif | ||
746 | } | ||
747 | |||
748 | GNUNET_IDENTITY_ego_lookup (cfg, host_name, &id_host_ego_cb, NULL); | ||
749 | } | ||
750 | |||
751 | |||
752 | void identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, | ||
753 | void **ctx, const char *name) | ||
754 | { | ||
755 | |||
756 | } | ||
757 | |||
758 | |||
759 | void | ||
760 | core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity) | ||
761 | { | ||
762 | this_peer = *my_identity; | ||
763 | |||
764 | id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL); | ||
765 | GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL); | ||
766 | } | ||
767 | |||
768 | |||
112 | /** | 769 | /** |
113 | * Main function of the test, run from scheduler. | 770 | * Main function of the test, run from scheduler. |
114 | * | 771 | * |
@@ -116,7 +773,7 @@ end () | |||
116 | * @param cfg configuration we use (also to connect to Social service) | 773 | * @param cfg configuration we use (also to connect to Social service) |
117 | * @param peer handle to access more of the peer (not used) | 774 | * @param peer handle to access more of the peer (not used) |
118 | */ | 775 | */ |
119 | static void | 776 | void |
120 | #if DEBUG_SERVICE | 777 | #if DEBUG_SERVICE |
121 | run (void *cls, char *const *args, const char *cfgfile, | 778 | run (void *cls, char *const *args, const char *cfgfile, |
122 | const struct GNUNET_CONFIGURATION_Handle *c) | 779 | const struct GNUNET_CONFIGURATION_Handle *c) |
@@ -129,9 +786,14 @@ run (void *cls, | |||
129 | cfg = c; | 786 | cfg = c; |
130 | end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); | 787 | end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); |
131 | 788 | ||
132 | /* FIXME: add tests */ | 789 | place_key = GNUNET_CRYPTO_eddsa_key_create (); |
790 | guest_key = GNUNET_CRYPTO_ecdsa_key_create (); | ||
133 | 791 | ||
134 | end (); | 792 | GNUNET_CRYPTO_eddsa_key_get_public (place_key, &place_pub_key); |
793 | GNUNET_CRYPTO_ecdsa_key_get_public (guest_key, &guest_pub_key); | ||
794 | |||
795 | core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL, | ||
796 | NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); | ||
135 | } | 797 | } |
136 | 798 | ||
137 | 799 | ||