diff options
Diffstat (limited to 'src/social/gnunet-social.c')
-rw-r--r-- | src/social/gnunet-social.c | 1411 |
1 files changed, 0 insertions, 1411 deletions
diff --git a/src/social/gnunet-social.c b/src/social/gnunet-social.c deleted file mode 100644 index 14701bfda..000000000 --- a/src/social/gnunet-social.c +++ /dev/null | |||
@@ -1,1411 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * CLI tool to interact with the social service. | ||
23 | * | ||
24 | * @author Gabor X Toth | ||
25 | */ | ||
26 | |||
27 | #include <inttypes.h> | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_social_service.h" | ||
32 | |||
33 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
34 | |||
35 | #define DATA2ARG(data) data, sizeof (data) | ||
36 | |||
37 | /* operations corresponding to API calls */ | ||
38 | |||
39 | /** --status */ | ||
40 | static int op_status; | ||
41 | |||
42 | /** --host-enter */ | ||
43 | static int op_host_enter; | ||
44 | |||
45 | /** --host-reconnect */ | ||
46 | static int op_host_reconnect; | ||
47 | |||
48 | /** --host-leave */ | ||
49 | static int op_host_leave; | ||
50 | |||
51 | /** --host-announce */ | ||
52 | static int op_host_announce; | ||
53 | |||
54 | /** --host-assign */ | ||
55 | static int op_host_assign; | ||
56 | |||
57 | /** --guest-enter */ | ||
58 | static int op_guest_enter; | ||
59 | |||
60 | /** --guest-reconnect */ | ||
61 | static int op_guest_reconnect; | ||
62 | |||
63 | /** --guest-leave */ | ||
64 | static int op_guest_leave; | ||
65 | |||
66 | /** --guest-talk */ | ||
67 | static int op_guest_talk; | ||
68 | |||
69 | /** --replay */ | ||
70 | static int op_replay; | ||
71 | |||
72 | /** --replay-latest */ | ||
73 | static int op_replay_latest; | ||
74 | |||
75 | /** --look-at */ | ||
76 | static int op_look_at; | ||
77 | |||
78 | /** --look-for */ | ||
79 | static int op_look_for; | ||
80 | |||
81 | |||
82 | /* options */ | ||
83 | |||
84 | /** --app */ | ||
85 | static char *opt_app = "cli"; | ||
86 | |||
87 | /** --place */ | ||
88 | static char *opt_place; | ||
89 | |||
90 | /** --ego */ | ||
91 | static char *opt_ego; | ||
92 | |||
93 | /** --gns */ | ||
94 | static char *opt_gns; | ||
95 | |||
96 | /** --peer */ | ||
97 | static char *opt_peer; | ||
98 | |||
99 | /** --follow */ | ||
100 | static int opt_follow; | ||
101 | |||
102 | /** --welcome */ | ||
103 | static int opt_welcome; | ||
104 | |||
105 | /** --deny */ | ||
106 | static int opt_deny; | ||
107 | |||
108 | /** --method */ | ||
109 | static char *opt_method; | ||
110 | |||
111 | /** --data */ | ||
112 | // FIXME: should come from STDIN | ||
113 | static char *opt_data; | ||
114 | |||
115 | /** --name */ | ||
116 | static char *opt_name; | ||
117 | |||
118 | /** --start */ | ||
119 | static unsigned long long opt_start; | ||
120 | |||
121 | /** --until */ | ||
122 | static unsigned long long opt_until; | ||
123 | |||
124 | /** --limit */ | ||
125 | static unsigned long long opt_limit; | ||
126 | |||
127 | |||
128 | /* global vars */ | ||
129 | |||
130 | /** exit code */ | ||
131 | static int ret = 1; | ||
132 | |||
133 | /** are we waiting for service to close our connection */ | ||
134 | static char is_disconnecting = 0; | ||
135 | |||
136 | /** Task handle for timeout termination. */ | ||
137 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
138 | |||
139 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
140 | |||
141 | struct GNUNET_PeerIdentity peer, this_peer; | ||
142 | |||
143 | struct GNUNET_SOCIAL_App *app; | ||
144 | |||
145 | /** public key of connected place */ | ||
146 | struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key; | ||
147 | |||
148 | struct GNUNET_PSYC_Slicer *slicer; | ||
149 | |||
150 | struct GNUNET_SOCIAL_Ego *ego; | ||
151 | struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; | ||
152 | |||
153 | struct GNUNET_SOCIAL_Host *hst; | ||
154 | struct GNUNET_SOCIAL_Guest *gst; | ||
155 | struct GNUNET_SOCIAL_Place *plc; | ||
156 | |||
157 | const char *method_received; | ||
158 | |||
159 | |||
160 | /* DISCONNECT */ | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Callback called after the host or guest place disconnected. | ||
165 | */ | ||
166 | static void | ||
167 | disconnected (void *cls) | ||
168 | { | ||
169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnected()\n"); | ||
170 | GNUNET_SCHEDULER_shutdown (); | ||
171 | } | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Callback called after the application disconnected. | ||
176 | */ | ||
177 | static void | ||
178 | app_disconnected (void *cls) | ||
179 | { | ||
180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "app_disconnected()\n"); | ||
181 | if (hst || gst) | ||
182 | { | ||
183 | if (hst) | ||
184 | { | ||
185 | GNUNET_SOCIAL_host_disconnect (hst, disconnected, NULL); | ||
186 | } | ||
187 | if (gst) | ||
188 | { | ||
189 | GNUNET_SOCIAL_guest_disconnect (gst, disconnected, NULL); | ||
190 | } | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | GNUNET_SCHEDULER_shutdown (); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Disconnect from connected GNUnet services. | ||
201 | */ | ||
202 | static void | ||
203 | disconnect () | ||
204 | { | ||
205 | // handle that we get called several times from several places, but should we? | ||
206 | if (!is_disconnecting++) { | ||
207 | GNUNET_SOCIAL_app_disconnect (app, app_disconnected, NULL); | ||
208 | } | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect() called for the #%d time\n", is_disconnecting); | ||
210 | } | ||
211 | |||
212 | |||
213 | static void | ||
214 | scheduler_shutdown (void *cls) | ||
215 | { | ||
216 | disconnect (); | ||
217 | } | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Callback called when the program failed to finish the requested operation in time. | ||
222 | */ | ||
223 | static void | ||
224 | timeout (void *cls) | ||
225 | { | ||
226 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "timeout()\n"); | ||
227 | disconnect (); | ||
228 | } | ||
229 | |||
230 | static void | ||
231 | schedule_success (void *cls) | ||
232 | { | ||
233 | ret = 0; | ||
234 | disconnect (); | ||
235 | } | ||
236 | |||
237 | |||
238 | static void | ||
239 | schedule_fail (void *cls) | ||
240 | { | ||
241 | disconnect (); | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Schedule exit with success result. | ||
247 | */ | ||
248 | static void | ||
249 | exit_success () | ||
250 | { | ||
251 | if (timeout_task != NULL) | ||
252 | { | ||
253 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
254 | timeout_task = NULL; | ||
255 | } | ||
256 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, schedule_success, NULL); | ||
257 | } | ||
258 | |||
259 | |||
260 | /** | ||
261 | * Schedule exit with failure result. | ||
262 | */ | ||
263 | static void | ||
264 | exit_fail () | ||
265 | { | ||
266 | if (timeout_task != NULL) | ||
267 | { | ||
268 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
269 | timeout_task = NULL; | ||
270 | } | ||
271 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, schedule_fail, NULL); | ||
272 | } | ||
273 | |||
274 | |||
275 | /* LEAVE */ | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Callback notifying about the host has left and stopped hosting the place. | ||
280 | * | ||
281 | * This also indicates the end of the connection to the service. | ||
282 | */ | ||
283 | static void | ||
284 | host_left (void *cls) | ||
285 | { | ||
286 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
287 | "The host has left the place.\n"); | ||
288 | exit_success (); | ||
289 | } | ||
290 | |||
291 | |||
292 | /** | ||
293 | * Leave a place permanently and stop hosting a place. | ||
294 | */ | ||
295 | static void | ||
296 | host_leave () | ||
297 | { | ||
298 | GNUNET_SOCIAL_host_leave (hst, NULL, host_left, NULL); | ||
299 | hst = NULL; | ||
300 | plc = NULL; | ||
301 | } | ||
302 | |||
303 | |||
304 | /** | ||
305 | * Callback notifying about the guest has left the place. | ||
306 | * | ||
307 | * This also indicates the end of the connection to the service. | ||
308 | */ | ||
309 | static void | ||
310 | guest_left (void *cls) | ||
311 | { | ||
312 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
313 | "Guest has left the place.\n"); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Leave a place permanently as guest. | ||
319 | */ | ||
320 | static void | ||
321 | guest_leave () | ||
322 | { | ||
323 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
324 | // FIXME: wrong use of vars | ||
325 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, | ||
326 | "_message", DATA2ARG ("Leaving.")); | ||
327 | GNUNET_SOCIAL_guest_leave (gst, env, guest_left, NULL); | ||
328 | GNUNET_PSYC_env_destroy (env); | ||
329 | gst = NULL; | ||
330 | plc = NULL; | ||
331 | } | ||
332 | |||
333 | |||
334 | /* ANNOUNCE / ASSIGN / TALK */ | ||
335 | |||
336 | |||
337 | struct TransmitClosure | ||
338 | { | ||
339 | const char *data; | ||
340 | size_t size; | ||
341 | } tmit; | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Callback notifying about available buffer space to write message data | ||
346 | * when transmitting messages using host_announce() or guest_talk() | ||
347 | */ | ||
348 | static int | ||
349 | notify_data (void *cls, uint16_t *data_size, void *data) | ||
350 | { | ||
351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
352 | "Transmit notify data: %u bytes available\n", | ||
353 | *data_size); | ||
354 | |||
355 | struct TransmitClosure *tmit = cls; | ||
356 | uint16_t size = tmit->size < *data_size ? tmit->size : *data_size; | ||
357 | *data_size = size; | ||
358 | GNUNET_memcpy (data, tmit->data, size); | ||
359 | |||
360 | tmit->size -= size; | ||
361 | tmit->data += size; | ||
362 | |||
363 | if (0 == tmit->size) | ||
364 | { | ||
365 | if ((op_host_announce || op_host_assign || op_guest_talk) && !opt_follow) | ||
366 | { | ||
367 | exit_success (); | ||
368 | } | ||
369 | return GNUNET_YES; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | return GNUNET_NO; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | |||
378 | /** | ||
379 | * Host announcement - send a message to the place. | ||
380 | */ | ||
381 | static void | ||
382 | host_announce (const char *method, const char *data, size_t data_size) | ||
383 | { | ||
384 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
385 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, | ||
386 | "_foo", DATA2ARG ("bar baz")); | ||
387 | |||
388 | tmit = (struct TransmitClosure) {}; | ||
389 | tmit.data = data; | ||
390 | tmit.size = data_size; | ||
391 | |||
392 | GNUNET_SOCIAL_host_announce (hst, method, env, | ||
393 | notify_data, &tmit, | ||
394 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
395 | GNUNET_PSYC_env_destroy (env); | ||
396 | } | ||
397 | |||
398 | |||
399 | /** | ||
400 | * Assign a state var of @a name to the value of @a data. | ||
401 | */ | ||
402 | static void | ||
403 | host_assign (const char *name, const char *data, size_t data_size) | ||
404 | { | ||
405 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
406 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, | ||
407 | name, data, data_size); | ||
408 | |||
409 | tmit = (struct TransmitClosure) {}; | ||
410 | GNUNET_SOCIAL_host_announce (hst, "_assign", env, | ||
411 | notify_data, &tmit, | ||
412 | GNUNET_SOCIAL_ANNOUNCE_NONE); | ||
413 | GNUNET_PSYC_env_destroy (env); | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Guest talk request to host. | ||
419 | */ | ||
420 | static void | ||
421 | guest_talk (const char *method, | ||
422 | const char *data, size_t data_size) | ||
423 | { | ||
424 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
425 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, | ||
426 | "_foo", DATA2ARG ("bar baz")); | ||
427 | |||
428 | tmit = (struct TransmitClosure) {}; | ||
429 | tmit.data = data; | ||
430 | tmit.size = data_size; | ||
431 | |||
432 | GNUNET_SOCIAL_guest_talk (gst, method, env, | ||
433 | notify_data, &tmit, | ||
434 | GNUNET_SOCIAL_TALK_NONE); | ||
435 | GNUNET_PSYC_env_destroy (env); | ||
436 | } | ||
437 | |||
438 | |||
439 | /* HISTORY REPLAY */ | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Callback notifying about the end of history replay results. | ||
444 | */ | ||
445 | static void | ||
446 | recv_history_replay_result (void *cls, int64_t result, | ||
447 | const void *data, uint16_t data_size) | ||
448 | { | ||
449 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
450 | "Received history replay result: %" PRId64 "\n" | ||
451 | "%.*s\n", | ||
452 | result, data_size, (const char *) data); | ||
453 | |||
454 | if (op_replay || op_replay_latest) | ||
455 | { | ||
456 | exit_success (); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Replay history between a given @a start and @a end message IDs, | ||
463 | * optionally filtered by a method @a prefix. | ||
464 | */ | ||
465 | static void | ||
466 | history_replay (uint64_t start, uint64_t end, const char *prefix) | ||
467 | { | ||
468 | GNUNET_SOCIAL_place_history_replay (plc, start, end, prefix, | ||
469 | GNUNET_PSYC_HISTORY_REPLAY_LOCAL, | ||
470 | slicer, | ||
471 | recv_history_replay_result, | ||
472 | NULL); | ||
473 | } | ||
474 | |||
475 | |||
476 | /** | ||
477 | * Replay latest @a limit messages. | ||
478 | */ | ||
479 | static void | ||
480 | history_replay_latest (uint64_t limit, const char *prefix) | ||
481 | { | ||
482 | GNUNET_SOCIAL_place_history_replay_latest (plc, limit, prefix, | ||
483 | GNUNET_PSYC_HISTORY_REPLAY_LOCAL, | ||
484 | slicer, | ||
485 | recv_history_replay_result, | ||
486 | NULL); | ||
487 | } | ||
488 | |||
489 | |||
490 | /* LOOK AT/FOR */ | ||
491 | |||
492 | |||
493 | /** | ||
494 | * Callback notifying about the end of state var results. | ||
495 | */ | ||
496 | static void | ||
497 | look_result (void *cls, int64_t result_code, | ||
498 | const void *data, uint16_t data_size) | ||
499 | { | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
501 | "Received look result: %" PRId64 "\n", result_code); | ||
502 | |||
503 | if (op_look_at || op_look_for) | ||
504 | { | ||
505 | exit_success (); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | |||
510 | /** | ||
511 | * Callback notifying about a state var result. | ||
512 | */ | ||
513 | static void | ||
514 | look_var (void *cls, | ||
515 | const struct GNUNET_MessageHeader *mod, | ||
516 | const char *name, | ||
517 | const void *value, | ||
518 | uint32_t value_size, | ||
519 | uint32_t full_value_size) | ||
520 | { | ||
521 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
522 | "Received var: %s\n%.*s\n", | ||
523 | name, value_size, (const char *) value); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Look for a state var using exact match of the name. | ||
529 | */ | ||
530 | static void | ||
531 | look_at (const char *full_name) | ||
532 | { | ||
533 | GNUNET_SOCIAL_place_look_at (plc, full_name, look_var, look_result, NULL); | ||
534 | } | ||
535 | |||
536 | |||
537 | /** | ||
538 | * Look for state vars by name prefix. | ||
539 | */ | ||
540 | static void | ||
541 | look_for (const char *name_prefix) | ||
542 | { | ||
543 | GNUNET_SOCIAL_place_look_for (plc, name_prefix, look_var, look_result, NULL); | ||
544 | } | ||
545 | |||
546 | |||
547 | /* SLICER */ | ||
548 | |||
549 | |||
550 | /** | ||
551 | * Callback notifying about the start of a new incoming message. | ||
552 | */ | ||
553 | static void | ||
554 | slicer_recv_method (void *cls, | ||
555 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
556 | const struct GNUNET_PSYC_MessageMethod *meth, | ||
557 | uint64_t message_id, | ||
558 | const char *method_name) | ||
559 | { | ||
560 | method_received = method_name; | ||
561 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
562 | "Received method for message ID %" PRIu64 ":\n" | ||
563 | "%s (flags: %x)\n", | ||
564 | message_id, method_name, ntohl (meth->flags)); | ||
565 | /* routing header is missing, so we just print double newline */ | ||
566 | printf("\n"); | ||
567 | /* we output . instead of | to indicate that this is not proper PSYC syntax */ | ||
568 | /* FIXME: use libpsyc here */ | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Callback notifying about an incoming modifier. | ||
574 | */ | ||
575 | static void | ||
576 | slicer_recv_modifier (void *cls, | ||
577 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
578 | const struct GNUNET_MessageHeader *pmsg, | ||
579 | uint64_t message_id, | ||
580 | enum GNUNET_PSYC_Operator oper, | ||
581 | const char *name, | ||
582 | const void *value, | ||
583 | uint16_t value_size, | ||
584 | uint16_t full_value_size) | ||
585 | { | ||
586 | #if 0 | ||
587 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
588 | "Received modifier for message ID %" PRIu64 ":\n" | ||
589 | "%c%s: %.*s (size: %u)\n", | ||
590 | message_id, oper, name, value_size, (const char *) value, value_size); | ||
591 | #else | ||
592 | /* obviously not binary safe */ | ||
593 | printf("%c%s\t%.*s\n", | ||
594 | oper, name, value_size, (const char *) value); | ||
595 | #endif | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * Callback notifying about an incoming data fragment. | ||
601 | */ | ||
602 | static void | ||
603 | slicer_recv_data (void *cls, | ||
604 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
605 | const struct GNUNET_MessageHeader *pmsg, | ||
606 | uint64_t message_id, | ||
607 | const void *data, | ||
608 | uint16_t data_size) | ||
609 | { | ||
610 | #if 0 | ||
611 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
612 | "Received data for message ID %" PRIu64 ":\n" | ||
613 | "%.*s\n", | ||
614 | message_id, data_size, (const char *) data); | ||
615 | #else | ||
616 | /* obviously not binary safe */ | ||
617 | printf("%s\n%.*s\n", | ||
618 | method_received, data_size, (const char *) data); | ||
619 | #endif | ||
620 | } | ||
621 | |||
622 | |||
623 | /** | ||
624 | * Callback notifying about the end of a message. | ||
625 | */ | ||
626 | static void | ||
627 | slicer_recv_eom (void *cls, | ||
628 | const struct GNUNET_PSYC_MessageHeader *msg, | ||
629 | const struct GNUNET_MessageHeader *pmsg, | ||
630 | uint64_t message_id, | ||
631 | uint8_t is_cancelled) | ||
632 | { | ||
633 | printf(".\n"); | ||
634 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
635 | "Received end of message ID %" PRIu64 | ||
636 | ", cancelled: %u\n", | ||
637 | message_id, is_cancelled); | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Create a slicer for receiving message parts. | ||
643 | */ | ||
644 | static struct GNUNET_PSYC_Slicer * | ||
645 | slicer_create () | ||
646 | { | ||
647 | slicer = GNUNET_PSYC_slicer_create (); | ||
648 | |||
649 | /* register slicer to receive incoming messages with any method name */ | ||
650 | GNUNET_PSYC_slicer_method_add (slicer, "", NULL, | ||
651 | slicer_recv_method, slicer_recv_modifier, | ||
652 | slicer_recv_data, slicer_recv_eom, NULL); | ||
653 | return slicer; | ||
654 | } | ||
655 | |||
656 | |||
657 | /* GUEST ENTER */ | ||
658 | |||
659 | |||
660 | /** | ||
661 | * Callback called when the guest receives an entry decision from the host. | ||
662 | * | ||
663 | * It is called once after using guest_enter() or guest_enter_by_name(), | ||
664 | * in case of a reconnection only the local enter callback is called. | ||
665 | */ | ||
666 | static void | ||
667 | guest_recv_entry_decision (void *cls, | ||
668 | int is_admitted, | ||
669 | const struct GNUNET_PSYC_Message *entry_msg) | ||
670 | { | ||
671 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
672 | "Guest received entry decision %d\n", | ||
673 | is_admitted); | ||
674 | |||
675 | if (NULL != entry_msg) | ||
676 | { | ||
677 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
678 | const char *method_name = NULL; | ||
679 | const void *data = NULL; | ||
680 | uint16_t data_size = 0; | ||
681 | struct GNUNET_PSYC_MessageHeader * | ||
682 | pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg); | ||
683 | GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size); | ||
684 | GNUNET_free (pmsg); | ||
685 | |||
686 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
687 | "%s\n%.*s\n", | ||
688 | method_name, data_size, (const char *) data); | ||
689 | } | ||
690 | |||
691 | if (op_guest_enter && !opt_follow) | ||
692 | { | ||
693 | exit_success (); | ||
694 | } | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Callback called after a guest connection is established to the local service. | ||
700 | */ | ||
701 | static void | ||
702 | guest_recv_local_enter (void *cls, int result, | ||
703 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key, | ||
704 | uint64_t max_message_id) | ||
705 | { | ||
706 | char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key); | ||
707 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
708 | "Guest entered local place: %s, max_message_id: %" PRIu64 "\n", | ||
709 | pub_str, max_message_id); | ||
710 | GNUNET_free (pub_str); | ||
711 | GNUNET_assert (0 <= result); | ||
712 | |||
713 | if (op_guest_enter && !opt_follow) | ||
714 | { | ||
715 | exit_success (); | ||
716 | } | ||
717 | } | ||
718 | |||
719 | |||
720 | /** | ||
721 | * Create entry request message. | ||
722 | */ | ||
723 | static struct GNUNET_PSYC_Message * | ||
724 | guest_enter_msg_create () | ||
725 | { | ||
726 | const char *method_name = "_request_enter"; | ||
727 | struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); | ||
728 | GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, | ||
729 | "_foo", DATA2ARG ("bar")); | ||
730 | void *data = "let me in"; | ||
731 | uint16_t data_size = strlen (data) + 1; | ||
732 | |||
733 | return GNUNET_PSYC_message_create (method_name, env, data, data_size); | ||
734 | } | ||
735 | |||
736 | |||
737 | /** | ||
738 | * Enter a place as guest, using its public key and peer ID. | ||
739 | */ | ||
740 | static void | ||
741 | guest_enter (const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key, | ||
742 | const struct GNUNET_PeerIdentity *peer) | ||
743 | { | ||
744 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
745 | "Entering to place as guest.\n"); | ||
746 | |||
747 | if (NULL == ego) | ||
748 | { | ||
749 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n"); | ||
750 | exit_fail (); | ||
751 | return; | ||
752 | } | ||
753 | |||
754 | struct GNUNET_PSYC_Message *join_msg = guest_enter_msg_create (); | ||
755 | gst = GNUNET_SOCIAL_guest_enter (app, ego, pub_key, | ||
756 | GNUNET_PSYC_SLAVE_JOIN_NONE, | ||
757 | peer, 0, NULL, join_msg, slicer_create (), | ||
758 | guest_recv_local_enter, | ||
759 | guest_recv_entry_decision, NULL); | ||
760 | GNUNET_free (join_msg); | ||
761 | plc = GNUNET_SOCIAL_guest_get_place (gst); | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Enter a place as guest using its GNS address. | ||
767 | */ | ||
768 | static void | ||
769 | guest_enter_by_name (const char *gns_name) | ||
770 | { | ||
771 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
772 | "Entering to place by name as guest.\n"); | ||
773 | |||
774 | struct GNUNET_PSYC_Message *join_msg = guest_enter_msg_create (); | ||
775 | gst = GNUNET_SOCIAL_guest_enter_by_name (app, ego, gns_name, NULL, | ||
776 | join_msg, slicer, | ||
777 | guest_recv_local_enter, | ||
778 | guest_recv_entry_decision, NULL); | ||
779 | GNUNET_free (join_msg); | ||
780 | plc = GNUNET_SOCIAL_guest_get_place (gst); | ||
781 | } | ||
782 | |||
783 | |||
784 | /* HOST ENTER */ | ||
785 | |||
786 | |||
787 | /** | ||
788 | * Callback called when a @a nym wants to enter the place. | ||
789 | * | ||
790 | * The request needs to be replied with an entry decision. | ||
791 | */ | ||
792 | static void | ||
793 | host_answer_door (void *cls, | ||
794 | struct GNUNET_SOCIAL_Nym *nym, | ||
795 | const char *method_name, | ||
796 | struct GNUNET_PSYC_Environment *env, | ||
797 | const void *data, | ||
798 | size_t data_size) | ||
799 | { | ||
800 | const struct GNUNET_CRYPTO_EcdsaPublicKey * | ||
801 | nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym); | ||
802 | char * | ||
803 | nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); | ||
804 | |||
805 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
806 | "Entry request: %s\n", nym_str); | ||
807 | GNUNET_free (nym_str); | ||
808 | |||
809 | if (opt_welcome) | ||
810 | { | ||
811 | struct GNUNET_PSYC_Message * | ||
812 | resp = GNUNET_PSYC_message_create ("_notice_place_admit", env, | ||
813 | DATA2ARG ("Welcome, nym!")); | ||
814 | GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, resp); | ||
815 | GNUNET_free (resp); | ||
816 | } | ||
817 | else if (opt_deny) | ||
818 | { | ||
819 | struct GNUNET_PSYC_Message * | ||
820 | resp = GNUNET_PSYC_message_create ("_notice_place_refuse", NULL, | ||
821 | DATA2ARG ("Go away!")); | ||
822 | GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, resp); | ||
823 | GNUNET_free (resp); | ||
824 | } | ||
825 | |||
826 | |||
827 | } | ||
828 | |||
829 | |||
830 | /** | ||
831 | * Callback called when a @a nym has left the place. | ||
832 | */ | ||
833 | static void | ||
834 | host_farewell (void *cls, | ||
835 | const struct GNUNET_SOCIAL_Nym *nym, | ||
836 | struct GNUNET_PSYC_Environment *env) | ||
837 | { | ||
838 | const struct GNUNET_CRYPTO_EcdsaPublicKey * | ||
839 | nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym); | ||
840 | char * | ||
841 | nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); | ||
842 | |||
843 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
844 | "Farewell: %s\n", nym_str); | ||
845 | GNUNET_free (nym_str); | ||
846 | } | ||
847 | |||
848 | |||
849 | /** | ||
850 | * Callback called after the host entered the place. | ||
851 | */ | ||
852 | static void | ||
853 | host_entered (void *cls, int result, | ||
854 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key, | ||
855 | uint64_t max_message_id) | ||
856 | { | ||
857 | place_pub_key = *pub_key; | ||
858 | char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key); | ||
859 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
860 | "Host entered: %s, max_message_id: %" PRIu64 "\n", | ||
861 | pub_str, max_message_id); | ||
862 | GNUNET_free (pub_str); | ||
863 | |||
864 | if (op_host_enter && !opt_follow) | ||
865 | { | ||
866 | exit_success (); | ||
867 | } | ||
868 | } | ||
869 | |||
870 | |||
871 | /** | ||
872 | * Enter and start hosting a place. | ||
873 | */ | ||
874 | static void | ||
875 | host_enter () | ||
876 | { | ||
877 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "host_enter()\n"); | ||
878 | |||
879 | if (NULL == ego) | ||
880 | { | ||
881 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n"); | ||
882 | exit_fail (); | ||
883 | return; | ||
884 | } | ||
885 | |||
886 | hst = GNUNET_SOCIAL_host_enter (app, ego, | ||
887 | GNUNET_PSYC_CHANNEL_PRIVATE, | ||
888 | slicer_create (), host_entered, | ||
889 | host_answer_door, host_farewell, NULL); | ||
890 | plc = GNUNET_SOCIAL_host_get_place (hst); | ||
891 | } | ||
892 | |||
893 | |||
894 | /* PLACE RECONNECT */ | ||
895 | |||
896 | |||
897 | /** | ||
898 | * Perform operations common to both host & guest places. | ||
899 | */ | ||
900 | static void | ||
901 | place_reconnected () | ||
902 | { | ||
903 | static int first_run = GNUNET_YES; | ||
904 | if (GNUNET_NO == first_run) | ||
905 | return; | ||
906 | first_run = GNUNET_NO; | ||
907 | |||
908 | if (op_replay) { | ||
909 | history_replay (opt_start, opt_until, opt_method); | ||
910 | } | ||
911 | else if (op_replay_latest) { | ||
912 | history_replay_latest (opt_limit, opt_method); | ||
913 | } | ||
914 | else if (op_look_at) { | ||
915 | look_at (opt_name); | ||
916 | } | ||
917 | else if (op_look_for) { | ||
918 | look_for (opt_name); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | |||
923 | /** | ||
924 | * Callback called after reconnecting to a host place. | ||
925 | */ | ||
926 | static void | ||
927 | host_reconnected (void *cls, int result, | ||
928 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
929 | uint64_t max_message_id) | ||
930 | { | ||
931 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
932 | "Host reconnected.\n"); | ||
933 | |||
934 | if (op_host_leave) { | ||
935 | host_leave (); | ||
936 | } | ||
937 | else if (op_host_announce) { | ||
938 | host_announce (opt_method, opt_data, strlen (opt_data)); | ||
939 | } | ||
940 | else if (op_host_assign) { | ||
941 | host_assign (opt_name, opt_data, strlen (opt_data) + 1); | ||
942 | } | ||
943 | else { | ||
944 | place_reconnected (); | ||
945 | } | ||
946 | } | ||
947 | |||
948 | |||
949 | /** | ||
950 | * Callback called after reconnecting to a guest place. | ||
951 | */ | ||
952 | static void | ||
953 | guest_reconnected (void *cls, int result, | ||
954 | const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, | ||
955 | uint64_t max_message_id) | ||
956 | { | ||
957 | char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (place_pub_key); | ||
958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
959 | "Guest reconnected to place %s.\n", place_pub_str); | ||
960 | GNUNET_free (place_pub_str); | ||
961 | |||
962 | if (op_guest_leave) { | ||
963 | guest_leave (); | ||
964 | } | ||
965 | else if (op_guest_talk) { | ||
966 | guest_talk (opt_method, opt_data, strlen (opt_data)); | ||
967 | } | ||
968 | else { | ||
969 | place_reconnected (); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | |||
974 | /* APP */ | ||
975 | |||
976 | |||
977 | /** | ||
978 | * Callback called after the ego and place callbacks. | ||
979 | */ | ||
980 | static void | ||
981 | app_connected (void *cls) | ||
982 | { | ||
983 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
984 | "App connected: %p\n", cls); | ||
985 | |||
986 | if (op_status) | ||
987 | { | ||
988 | exit_success (); | ||
989 | } | ||
990 | else if (op_host_enter) | ||
991 | { | ||
992 | host_enter (); | ||
993 | } | ||
994 | else if (op_guest_enter) | ||
995 | { | ||
996 | if (opt_gns) | ||
997 | { | ||
998 | guest_enter_by_name (opt_gns); | ||
999 | } | ||
1000 | else | ||
1001 | { | ||
1002 | if (opt_peer) | ||
1003 | { | ||
1004 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_peer, | ||
1005 | strlen (opt_peer), | ||
1006 | &peer.public_key)) | ||
1007 | { | ||
1008 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1009 | "--peer invalid"); | ||
1010 | exit_fail (); | ||
1011 | return; | ||
1012 | } | ||
1013 | } | ||
1014 | else | ||
1015 | { | ||
1016 | peer = this_peer; | ||
1017 | } | ||
1018 | guest_enter (&place_pub_key, &peer); | ||
1019 | } | ||
1020 | } | ||
1021 | printf(".\n"); | ||
1022 | } | ||
1023 | |||
1024 | |||
1025 | /** | ||
1026 | * Callback notifying about a host place available for reconnection. | ||
1027 | */ | ||
1028 | static void | ||
1029 | app_recv_host (void *cls, | ||
1030 | struct GNUNET_SOCIAL_HostConnection *hconn, | ||
1031 | struct GNUNET_SOCIAL_Ego *ego, | ||
1032 | const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key, | ||
1033 | enum GNUNET_SOCIAL_AppPlaceState place_state) | ||
1034 | { | ||
1035 | char *host_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (host_pub_key); | ||
1036 | printf ("Host\t%s\n", host_pub_str); | ||
1037 | GNUNET_free (host_pub_str); | ||
1038 | |||
1039 | if ((op_host_reconnect || op_host_leave || op_host_announce || op_host_assign | ||
1040 | || op_replay || op_replay_latest | ||
1041 | || op_look_at || op_look_for) | ||
1042 | && 0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key))) | ||
1043 | { | ||
1044 | hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, slicer_create (), host_reconnected, | ||
1045 | host_answer_door, host_farewell, NULL); | ||
1046 | plc = GNUNET_SOCIAL_host_get_place (hst); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | |||
1051 | /** | ||
1052 | * Callback notifying about a guest place available for reconnection. | ||
1053 | */ | ||
1054 | static void | ||
1055 | app_recv_guest (void *cls, | ||
1056 | struct GNUNET_SOCIAL_GuestConnection *gconn, | ||
1057 | struct GNUNET_SOCIAL_Ego *ego, | ||
1058 | const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key, | ||
1059 | enum GNUNET_SOCIAL_AppPlaceState place_state) | ||
1060 | { | ||
1061 | char *guest_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (guest_pub_key); | ||
1062 | printf ("Guest\t%s\n", guest_pub_str); | ||
1063 | GNUNET_free (guest_pub_str); | ||
1064 | |||
1065 | if ((op_guest_reconnect || op_guest_leave || op_guest_talk | ||
1066 | || op_replay || op_replay_latest | ||
1067 | || op_look_at || op_look_for) | ||
1068 | && 0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key))) | ||
1069 | { | ||
1070 | gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, GNUNET_PSYC_SLAVE_JOIN_NONE, | ||
1071 | slicer_create (), guest_reconnected, NULL); | ||
1072 | plc = GNUNET_SOCIAL_guest_get_place (gst); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /** | ||
1078 | * Callback notifying about an available ego. | ||
1079 | */ | ||
1080 | static void | ||
1081 | app_recv_ego (void *cls, | ||
1082 | struct GNUNET_SOCIAL_Ego *e, | ||
1083 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key, | ||
1084 | const char *name) | ||
1085 | { | ||
1086 | char *s = GNUNET_CRYPTO_ecdsa_public_key_to_string (pub_key); | ||
1087 | printf ("Ego\t%s\t%s\n", s, name); | ||
1088 | GNUNET_free (s); | ||
1089 | |||
1090 | if (0 == memcmp (&ego_pub_key, pub_key, sizeof (*pub_key)) | ||
1091 | || (NULL != opt_ego && 0 == strcmp (opt_ego, name))) | ||
1092 | { | ||
1093 | ego = e; | ||
1094 | } | ||
1095 | |||
1096 | } | ||
1097 | |||
1098 | |||
1099 | |||
1100 | /** | ||
1101 | * Establish application connection to receive available egos and places. | ||
1102 | */ | ||
1103 | static void | ||
1104 | app_connect (void *cls) | ||
1105 | { | ||
1106 | app = GNUNET_SOCIAL_app_connect (cfg, opt_app, | ||
1107 | app_recv_ego, | ||
1108 | app_recv_host, | ||
1109 | app_recv_guest, | ||
1110 | app_connected, | ||
1111 | NULL); | ||
1112 | } | ||
1113 | |||
1114 | |||
1115 | /** | ||
1116 | * Main function run by the scheduler. | ||
1117 | * | ||
1118 | * @param cls closure | ||
1119 | * @param args remaining command-line arguments | ||
1120 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1121 | * @param c configuration | ||
1122 | */ | ||
1123 | static void | ||
1124 | run (void *cls, char *const *args, const char *cfgfile, | ||
1125 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
1126 | { | ||
1127 | cfg = c; | ||
1128 | GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); | ||
1129 | |||
1130 | if (!opt_method) | ||
1131 | opt_method = "message"; | ||
1132 | if (!opt_data) | ||
1133 | opt_data = ""; | ||
1134 | if (!opt_name) | ||
1135 | opt_name = ""; | ||
1136 | |||
1137 | if (! (op_status | ||
1138 | || op_host_enter || op_host_reconnect || op_host_leave | ||
1139 | || op_host_announce || op_host_assign | ||
1140 | || op_guest_enter || op_guest_reconnect | ||
1141 | || op_guest_leave || op_guest_talk | ||
1142 | || op_replay || op_replay_latest | ||
1143 | || op_look_at || op_look_for)) | ||
1144 | { | ||
1145 | op_status = 1; | ||
1146 | fputs("Caution: This tool does not produce correct binary safe PSYC syntax.\n\n", stderr); | ||
1147 | } | ||
1148 | |||
1149 | GNUNET_SCHEDULER_add_shutdown (scheduler_shutdown, NULL); | ||
1150 | if (!opt_follow) | ||
1151 | { | ||
1152 | timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, timeout, NULL); | ||
1153 | } | ||
1154 | |||
1155 | if ((op_host_reconnect || op_host_leave || op_host_announce || op_host_assign | ||
1156 | || op_guest_reconnect || (op_guest_enter && !opt_gns) | ||
1157 | || op_guest_leave || op_guest_talk | ||
1158 | || op_replay || op_replay_latest | ||
1159 | || op_look_at || op_look_for) | ||
1160 | && (!opt_place | ||
1161 | || GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_place, | ||
1162 | strlen (opt_place), | ||
1163 | &place_pub_key))) | ||
1164 | { | ||
1165 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1166 | _("--place missing or invalid.\n")); | ||
1167 | /* FIXME: why does it segfault here? */ | ||
1168 | exit_fail (); | ||
1169 | return; | ||
1170 | } | ||
1171 | |||
1172 | if (opt_ego) | ||
1173 | { | ||
1174 | if (GNUNET_OK != | ||
1175 | GNUNET_CRYPTO_ecdsa_public_key_from_string (opt_ego, | ||
1176 | strlen (opt_ego), | ||
1177 | &ego_pub_key)) | ||
1178 | { | ||
1179 | FPRINTF (stderr, | ||
1180 | _("Public key `%s' malformed\n"), | ||
1181 | opt_ego); | ||
1182 | exit_fail (); | ||
1183 | return; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1187 | GNUNET_SCHEDULER_add_now (app_connect, NULL); | ||
1188 | } | ||
1189 | |||
1190 | |||
1191 | /** | ||
1192 | * The main function to obtain peer information. | ||
1193 | * | ||
1194 | * @param argc number of arguments from the command line | ||
1195 | * @param argv command line arguments | ||
1196 | * @return 0 ok, 1 on error | ||
1197 | */ | ||
1198 | int | ||
1199 | main (int argc, char *const *argv) | ||
1200 | { | ||
1201 | int res; | ||
1202 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1203 | /* | ||
1204 | * gnunet program options in addition to the ones below: | ||
1205 | * | ||
1206 | * -c, --config=FILENAME | ||
1207 | * -l, --logfile=LOGFILE | ||
1208 | * -L, --log=LOGLEVEL | ||
1209 | * -h, --help | ||
1210 | * -v, --version | ||
1211 | */ | ||
1212 | |||
1213 | /* operations */ | ||
1214 | |||
1215 | GNUNET_GETOPT_option_flag ('A', | ||
1216 | "host-assign", | ||
1217 | gettext_noop ("assign --name in state to --data"), | ||
1218 | &op_host_assign), | ||
1219 | |||
1220 | GNUNET_GETOPT_option_flag ('B', | ||
1221 | "guest-leave", | ||
1222 | gettext_noop ("say good-bye and leave somebody else's place"), | ||
1223 | &op_guest_leave), | ||
1224 | |||
1225 | GNUNET_GETOPT_option_flag ('C', | ||
1226 | "host-enter", | ||
1227 | gettext_noop ("create a place"), | ||
1228 | &op_host_enter), | ||
1229 | |||
1230 | GNUNET_GETOPT_option_flag ('D', | ||
1231 | "host-leave", | ||
1232 | gettext_noop ("destroy a place we were hosting"), | ||
1233 | &op_host_leave), | ||
1234 | |||
1235 | GNUNET_GETOPT_option_flag ('E', | ||
1236 | "guest-enter", | ||
1237 | gettext_noop ("enter somebody else's place"), | ||
1238 | &op_guest_enter), | ||
1239 | |||
1240 | |||
1241 | GNUNET_GETOPT_option_flag ('F', | ||
1242 | "look-for", | ||
1243 | gettext_noop ("find state matching name prefix"), | ||
1244 | &op_look_for), | ||
1245 | |||
1246 | GNUNET_GETOPT_option_flag ('H', | ||
1247 | "replay-latest", | ||
1248 | gettext_noop ("replay history of messages up to the given --limit"), | ||
1249 | &op_replay_latest), | ||
1250 | |||
1251 | GNUNET_GETOPT_option_flag ('N', | ||
1252 | "host-reconnect", | ||
1253 | gettext_noop ("reconnect to a previously created place"), | ||
1254 | &op_host_reconnect), | ||
1255 | |||
1256 | GNUNET_GETOPT_option_flag ('P', | ||
1257 | "host-announce", | ||
1258 | gettext_noop ("publish something to a place we are hosting"), | ||
1259 | &op_host_announce), | ||
1260 | |||
1261 | GNUNET_GETOPT_option_flag ('R', | ||
1262 | "guest-reconnect", | ||
1263 | gettext_noop ("reconnect to a previously entered place"), | ||
1264 | &op_guest_reconnect), | ||
1265 | |||
1266 | GNUNET_GETOPT_option_flag ('S', | ||
1267 | "look-at", | ||
1268 | gettext_noop ("search for state matching exact name"), | ||
1269 | &op_look_at), | ||
1270 | |||
1271 | GNUNET_GETOPT_option_flag ('T', | ||
1272 | "guest-talk", | ||
1273 | gettext_noop ("submit something to somebody's place"), | ||
1274 | &op_guest_talk), | ||
1275 | |||
1276 | GNUNET_GETOPT_option_flag ('U', | ||
1277 | "status", | ||
1278 | gettext_noop ("list of egos and subscribed places"), | ||
1279 | &op_status), | ||
1280 | |||
1281 | GNUNET_GETOPT_option_flag ('X', | ||
1282 | "replay", | ||
1283 | gettext_noop ("extract and replay history between message IDs --start and --until"), | ||
1284 | &op_replay), | ||
1285 | |||
1286 | |||
1287 | /* options */ | ||
1288 | |||
1289 | GNUNET_GETOPT_option_string ('a', | ||
1290 | "app", | ||
1291 | "APPLICATION_ID", | ||
1292 | gettext_noop ("application ID to use when connecting"), | ||
1293 | &opt_app), | ||
1294 | |||
1295 | GNUNET_GETOPT_option_string ('d', | ||
1296 | "data", | ||
1297 | "DATA", | ||
1298 | gettext_noop ("message body or state value"), | ||
1299 | &opt_data), | ||
1300 | |||
1301 | GNUNET_GETOPT_option_string ('e', | ||
1302 | "ego", | ||
1303 | "NAME|PUBKEY", | ||
1304 | gettext_noop ("name or public key of ego"), | ||
1305 | &opt_ego), | ||
1306 | |||
1307 | GNUNET_GETOPT_option_flag ('f', | ||
1308 | "follow", | ||
1309 | gettext_noop ("wait for incoming messages"), | ||
1310 | &opt_follow), | ||
1311 | |||
1312 | GNUNET_GETOPT_option_string ('g', | ||
1313 | "gns", | ||
1314 | "GNS_NAME", | ||
1315 | gettext_noop ("GNS name"), | ||
1316 | &opt_gns), | ||
1317 | |||
1318 | GNUNET_GETOPT_option_string ('i', | ||
1319 | "peer", | ||
1320 | "PEER_ID", | ||
1321 | gettext_noop ("peer ID for --guest-enter"), | ||
1322 | &opt_peer), | ||
1323 | |||
1324 | GNUNET_GETOPT_option_string ('k', | ||
1325 | "name", | ||
1326 | "VAR_NAME", | ||
1327 | gettext_noop ("name (key) to query from state"), | ||
1328 | &opt_name), | ||
1329 | |||
1330 | GNUNET_GETOPT_option_string ('m', | ||
1331 | "method", | ||
1332 | "METHOD_NAME", | ||
1333 | gettext_noop ("method name"), | ||
1334 | &opt_method), | ||
1335 | |||
1336 | GNUNET_GETOPT_option_ulong ('n', | ||
1337 | "limit", | ||
1338 | NULL, | ||
1339 | gettext_noop ("number of messages to replay from history"), | ||
1340 | &opt_limit), | ||
1341 | |||
1342 | GNUNET_GETOPT_option_string ('p', | ||
1343 | "place", | ||
1344 | "PUBKEY", | ||
1345 | gettext_noop ("key address of place"), | ||
1346 | &opt_place), | ||
1347 | |||
1348 | GNUNET_GETOPT_option_ulong ('s', | ||
1349 | "start", | ||
1350 | NULL, | ||
1351 | gettext_noop ("start message ID for history replay"), | ||
1352 | &opt_start), | ||
1353 | |||
1354 | GNUNET_GETOPT_option_flag ('w', | ||
1355 | "welcome", | ||
1356 | gettext_noop ("respond to entry requests by admitting all guests"), | ||
1357 | &opt_welcome), | ||
1358 | |||
1359 | GNUNET_GETOPT_option_ulong ('u', | ||
1360 | "until", | ||
1361 | NULL, | ||
1362 | gettext_noop ("end message ID for history replay"), | ||
1363 | &opt_until), | ||
1364 | |||
1365 | GNUNET_GETOPT_option_flag ('y', | ||
1366 | "deny", | ||
1367 | gettext_noop ("respond to entry requests by refusing all guests"), | ||
1368 | &opt_deny), | ||
1369 | |||
1370 | GNUNET_GETOPT_OPTION_END | ||
1371 | }; | ||
1372 | |||
1373 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1374 | return 2; | ||
1375 | |||
1376 | const char *help = | ||
1377 | _ ("gnunet-social - Interact with the social service: enter/leave, send/receive messages, access history and state.\n"); | ||
1378 | const char *usage = | ||
1379 | "gnunet-social [--status]\n" | ||
1380 | "\n" | ||
1381 | "gnunet-social --host-enter --ego <NAME or PUBKEY> [--follow] [--welcome | --deny]\n" | ||
1382 | "gnunet-social --host-reconnect --place <PUBKEY> [--follow] [--welcome | --deny]\n" | ||
1383 | "gnunet-social --host-leave --place <PUBKEY>\n" | ||
1384 | "gnunet-social --host-assign --place <PUBKEY> --name <NAME> --data <VALUE>\n" | ||
1385 | // FIXME: some state ops not implemented yet (no hurry) | ||
1386 | // "gnunet-social --host-augment --place <PUBKEY> --name <NAME> --data <VALUE>\n" | ||
1387 | // "gnunet-social --host-diminish --place <PUBKEY> --name <NAME> --data <VALUE>\n" | ||
1388 | // "gnunet-social --host-set --place <PUBKEY> --name <NAME> --data <VALUE>\n" | ||
1389 | "gnunet-social --host-announce --place <PUBKEY> --method <METHOD_NAME> --data <MESSAGE_BODY>\n" | ||
1390 | "\n" | ||
1391 | "gnunet-social --guest-enter --place <PUBKEY> --peer <PEERID> --ego <NAME or PUBKEY> [--follow]\n" | ||
1392 | "gnunet-social --guest-enter --gns <GNS_NAME> --ego <NAME or PUBKEY> [--follow]\n" | ||
1393 | "gnunet-social --guest-reconnect --place <PUBKEY> [--follow]\n" | ||
1394 | "gnunet-social --guest-leave --place <PUBKEY>\n" | ||
1395 | "gnunet-social --guest-talk --place <PUBKEY> --method <METHOD_NAME> --data <MESSAGE_BODY>\n" | ||
1396 | "\n" | ||
1397 | "gnunet-social --replay --place <PUBKEY> --start <MSGID> --until <MSGID> [--method <METHOD_PREFIX>]\n" | ||
1398 | "gnunet-social --replay-latest --place <PUBKEY> --limit <MSG_LIMIT> [--method <METHOD_PREFIX>]\n" | ||
1399 | "\n" | ||
1400 | "gnunet-social --look-at --place <PUBKEY> --name <FULL_NAME>\n" | ||
1401 | "gnunet-social --look-for --place <PUBKEY> --name <NAME_PREFIX>\n"; | ||
1402 | |||
1403 | res = GNUNET_PROGRAM_run (argc, argv, help, usage, options, &run, NULL); | ||
1404 | |||
1405 | GNUNET_free ((void *) argv); | ||
1406 | |||
1407 | if (GNUNET_OK == res) | ||
1408 | return ret; | ||
1409 | else | ||
1410 | return 1; | ||
1411 | } | ||