2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * CLI tool to interact with the social service.
24 * @author Gabor X Toth
30 #include "gnunet_util_lib.h"
31 #include "gnunet_social_service.h"
32 #include "gnunet_core_service.h"
34 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
36 #define DATA2ARG(data) data, sizeof (data)
38 /* operations corresponding to API calls */
44 static int op_host_enter;
46 /** --host-reconnect */
47 static int op_host_reconnect;
50 static int op_host_leave;
52 /** --host-announce */
53 static int op_host_announce;
56 static int op_guest_enter;
58 /** --guest-reconnect */
59 static int op_guest_reconnect;
62 static int op_guest_leave;
65 static int op_guest_talk;
68 static char *op_replay;
70 /** --replay-latest */
71 static char *op_replay_latest;
74 static int op_look_at;
77 static int op_look_for;
83 static char *opt_app = "cli";
86 static char *opt_place;
95 static char *opt_peer;
98 static int opt_follow;
101 static int opt_welcome;
107 static char *opt_method;
110 // FIXME: should come from STDIN
111 static char *opt_body;
114 static char *opt_name;
117 static uint64_t opt_start;
120 static uint64_t opt_until;
123 static int opt_limit;
131 /** Task handle for timeout termination. */
132 struct GNUNET_SCHEDULER_Task *timeout_task;
134 const struct GNUNET_CONFIGURATION_Handle *cfg;
136 struct GNUNET_CORE_Handle *core;
137 struct GNUNET_PeerIdentity peer, this_peer;
139 struct GNUNET_SOCIAL_App *app;
141 /** public key of connected place */
142 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
144 struct GNUNET_PSYC_Slicer *slicer;
146 struct GNUNET_SOCIAL_Ego *ego;
147 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
149 struct GNUNET_SOCIAL_Host *hst;
150 struct GNUNET_SOCIAL_Guest *gst;
151 struct GNUNET_SOCIAL_Place *plc;
162 GNUNET_SOCIAL_host_disconnect (hst, NULL, NULL);
166 GNUNET_SOCIAL_guest_disconnect (gst, NULL, NULL);
169 GNUNET_SOCIAL_app_disconnect (app);
170 GNUNET_CORE_disconnect (core);
171 GNUNET_SCHEDULER_shutdown ();
175 * Terminate the test case (failure).
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout.\n");
187 schedule_success (void *cls)
195 schedule_fail (void *cls)
204 if (timeout_task != NULL)
206 GNUNET_SCHEDULER_cancel (timeout_task);
209 GNUNET_SCHEDULER_add_now (&schedule_success, NULL);
216 if (timeout_task != NULL)
218 GNUNET_SCHEDULER_cancel (timeout_task);
221 GNUNET_SCHEDULER_add_now (&schedule_fail, NULL);
231 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
232 "The host has left the place.\n");
240 GNUNET_SOCIAL_host_leave (hst, NULL, &host_left, NULL);
247 guest_left (void *cls)
249 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
250 "The guest has left the place.\n");
257 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
258 // method in the middle of vars? FIXME
259 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
260 "_notice_place_leave", DATA2ARG ("Leaving."));
261 GNUNET_SOCIAL_guest_leave (gst, env, &guest_left, NULL);
262 GNUNET_PSYC_env_destroy (env);
268 /* ANNOUNCE / TALK */
271 struct TransmitClosure
279 notify_data (void *cls, uint16_t *data_size, void *data)
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
282 "Transmit notify data: %u bytes available\n",
285 struct TransmitClosure *tmit = cls;
286 uint16_t size = tmit->size < *data_size ? tmit->size : *data_size;
288 memcpy (data, tmit->data, size);
295 if (op_host_announce || op_guest_talk)
309 host_announce (const char *method, const char *data, size_t data_size)
311 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
312 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
313 "_foo", DATA2ARG ("bar baz"));
315 tmit = (struct TransmitClosure) {};
317 tmit.size = data_size;
319 GNUNET_SOCIAL_host_announce (hst, method, env,
321 GNUNET_SOCIAL_ANNOUNCE_NONE);
326 guest_talk (const char *method,
327 const char *data, size_t data_size)
329 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
330 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
331 "_foo", DATA2ARG ("bar baz"));
333 tmit = (struct TransmitClosure) {};
335 tmit.size = data_size;
337 GNUNET_SOCIAL_guest_talk (gst, method, env,
339 GNUNET_SOCIAL_TALK_NONE);
347 recv_history_replay_result (void *cls, int64_t result,
348 const void *data, uint16_t data_size)
350 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
351 "Received history replay result: %" PRId64 "\n"
353 result, data_size, (const char *) data);
355 if (op_replay || op_replay_latest)
363 history_replay (uint64_t start, uint64_t end, const char *prefix)
365 GNUNET_SOCIAL_place_history_replay (plc, start, end, prefix,
366 GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
368 &recv_history_replay_result,
374 history_replay_latest (uint64_t limit, const char *prefix)
376 GNUNET_SOCIAL_place_history_replay_latest (plc, limit, prefix,
377 GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
379 &recv_history_replay_result,
388 look_result (void *cls, int64_t result_code,
389 const void *data, uint16_t data_size)
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
392 "Received look result: %" PRId64 "\n", result_code);
394 if (op_look_at || op_look_for)
403 const struct GNUNET_MessageHeader *mod,
407 uint32_t full_value_size)
409 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
410 "look_at_var: %s\n%.*s\n",
411 name, value_size, (const char *) value);
416 look_at (const char *name)
418 GNUNET_SOCIAL_place_look_at (plc, name, look_var, look_result, NULL);
423 look_for (const char *name)
425 GNUNET_SOCIAL_place_look_for (plc, name, look_var, look_result, NULL);
433 slicer_recv_method (void *cls,
434 const struct GNUNET_PSYC_MessageHeader *msg,
435 const struct GNUNET_PSYC_MessageMethod *meth,
437 const char *method_name)
439 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
440 "Received method for message ID %" PRIu64 ":\n"
442 message_id, method_name, ntohl (meth->flags));
447 slicer_recv_modifier (void *cls,
448 const struct GNUNET_PSYC_MessageHeader *msg,
449 const struct GNUNET_MessageHeader *pmsg,
451 enum GNUNET_PSYC_Operator oper,
455 uint16_t full_value_size)
457 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
458 "Received modifier for message ID %" PRIu64 ":\n"
459 "%c%s: %.*s (size: %u)\n",
460 message_id, oper, name, value_size, (const char *) value, value_size);
465 slicer_recv_data (void *cls,
466 const struct GNUNET_PSYC_MessageHeader *msg,
467 const struct GNUNET_MessageHeader *pmsg,
472 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
473 "Received data for message ID %" PRIu64 ":\n"
475 message_id, data_size, (const char *) data);
480 slicer_recv_eom (void *cls,
481 const struct GNUNET_PSYC_MessageHeader *msg,
482 const struct GNUNET_MessageHeader *pmsg,
484 uint8_t is_cancelled)
486 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
487 "Received end of message ID %" PRIu64
489 message_id, is_cancelled);
493 static struct GNUNET_PSYC_Slicer *
496 slicer = GNUNET_PSYC_slicer_create ();
498 /* register slicer to receive incoming messages with any method name */
499 GNUNET_PSYC_slicer_method_add (slicer, "", NULL,
500 slicer_recv_method, slicer_recv_modifier,
501 slicer_recv_data, slicer_recv_eom, NULL);
510 guest_recv_entry_decision (void *cls,
512 const struct GNUNET_PSYC_Message *entry_msg)
514 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
515 "Guest received entry decision %d\n",
518 if (NULL != entry_msg)
520 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
521 const char *method_name = NULL;
522 const void *data = NULL;
523 uint16_t data_size = 0;
524 struct GNUNET_PSYC_MessageHeader *
525 pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg);
526 GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size);
529 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
531 method_name, data_size, (const char *) data);
534 if (op_guest_enter && !opt_follow)
542 guest_recv_local_enter (void *cls, int result,
543 const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
544 uint64_t max_message_id)
546 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
547 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
548 "Guest entered to local place: %s, max_message_id: %" PRIu64 "\n",
549 pub_str, max_message_id);
550 GNUNET_assert (0 <= result);
552 if (op_guest_enter && !opt_follow)
559 static struct GNUNET_PSYC_Message *
560 guest_enter_msg_create ()
562 const char *method_name = "_request_enter";
563 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
564 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
565 "_foo", DATA2ARG ("bar"));
566 void *data = "let me in";
567 uint16_t data_size = strlen (data) + 1;
569 return GNUNET_PSYC_message_create (method_name, env, data, data_size);
574 guest_enter (const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
575 const struct GNUNET_PeerIdentity *peer)
577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
578 "Entering to place as guest.\n");
582 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n");
587 gst = GNUNET_SOCIAL_guest_enter (app, ego, pub_key,
588 GNUNET_PSYC_SLAVE_JOIN_NONE,
589 peer, 0, NULL, guest_enter_msg_create (),
591 guest_recv_local_enter,
592 guest_recv_entry_decision, NULL);
593 plc = GNUNET_SOCIAL_guest_get_place (gst);
598 guest_enter_by_name (const char *gns_name)
600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
601 "Entering to place by name as guest.\n");
603 gst = GNUNET_SOCIAL_guest_enter_by_name (app, ego, gns_name, NULL,
604 guest_enter_msg_create (), slicer,
605 guest_recv_local_enter,
606 guest_recv_entry_decision, NULL);
607 plc = GNUNET_SOCIAL_guest_get_place (gst);
615 host_answer_door (void *cls,
616 struct GNUNET_SOCIAL_Nym *nym,
617 const char *method_name,
618 struct GNUNET_PSYC_Environment *env,
622 const struct GNUNET_CRYPTO_EcdsaPublicKey *
623 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
625 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
627 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
628 "Entry request: %s\n", nym_str);
629 GNUNET_free (nym_str);
633 struct GNUNET_PSYC_Message *
634 resp = GNUNET_PSYC_message_create ("_notice_place_admit", env,
635 DATA2ARG ("Welcome, nym!"));
636 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, resp);
641 struct GNUNET_PSYC_Message *
642 resp = GNUNET_PSYC_message_create ("_notice_place_refuse", NULL,
643 DATA2ARG ("Go away!"));
644 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, resp);
653 host_farewell (void *cls,
654 const struct GNUNET_SOCIAL_Nym *nym,
655 struct GNUNET_PSYC_Environment *env)
657 const struct GNUNET_CRYPTO_EcdsaPublicKey *
658 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
660 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
662 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
663 "Farewell: %s\n", nym_str);
664 GNUNET_free (nym_str);
669 host_entered (void *cls, int result,
670 const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
671 uint64_t max_message_id)
673 place_pub_key = *pub_key;
674 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
675 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
676 "Host entered: %s, max_message_id: %" PRIu64 "\n",
677 pub_str, max_message_id);
679 if (op_host_enter && !opt_follow)
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "host_enter()\n");
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n");
698 hst = GNUNET_SOCIAL_host_enter (app, ego,
699 GNUNET_PSYC_CHANNEL_PRIVATE,
700 slicer_create (), host_entered,
701 host_answer_door, host_farewell, NULL);
702 plc = GNUNET_SOCIAL_host_get_place (hst);
706 /* PLACE RECONNECT */
713 history_replay (opt_start, opt_until, opt_method);
715 else if (op_replay_latest) {
716 history_replay_latest (opt_limit, opt_method);
718 else if (op_look_at) {
721 else if (op_look_for) {
728 host_reconnected (void *cls, int result,
729 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
730 uint64_t max_message_id)
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733 "Host reconnected.\n");
738 else if (op_host_announce) {
739 host_announce (opt_method, opt_body, strlen (opt_body));
742 place_reconnected ();
748 guest_reconnected (void *cls, int result,
749 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
750 uint64_t max_message_id)
752 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
753 "Guest reconnected.\n");
755 if (op_guest_leave) {
758 else if (op_guest_talk) {
759 guest_talk (opt_method, opt_body, strlen (opt_body));
762 place_reconnected ();
771 app_connected (void *cls)
773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
774 "App connected: %p\n", cls);
780 else if (op_host_enter)
784 else if (op_guest_enter)
788 guest_enter_by_name (opt_gns);
794 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_peer,
798 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
808 guest_enter (&place_pub_key, &peer);
815 app_recv_host (void *cls,
816 struct GNUNET_SOCIAL_HostConnection *hconn,
817 struct GNUNET_SOCIAL_Ego *ego,
818 const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key,
819 enum GNUNET_SOCIAL_AppPlaceState place_state)
821 char *host_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (host_pub_key);
822 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
823 "Host: %s\n", host_pub_str);
824 GNUNET_free (host_pub_str);
826 if ((op_host_reconnect || op_host_leave || op_host_announce
827 || op_replay || op_replay_latest
828 || op_look_at || op_look_for)
829 && 0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key)))
831 hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, slicer_create (), host_reconnected,
832 host_answer_door, host_farewell, NULL);
833 plc = GNUNET_SOCIAL_host_get_place (hst);
839 app_recv_guest (void *cls,
840 struct GNUNET_SOCIAL_GuestConnection *gconn,
841 struct GNUNET_SOCIAL_Ego *ego,
842 const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key,
843 enum GNUNET_SOCIAL_AppPlaceState place_state)
845 char *guest_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (guest_pub_key);
846 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
847 "Guest: %s\n", guest_pub_str);
848 GNUNET_free (guest_pub_str);
850 if ((op_guest_reconnect || op_guest_leave || op_guest_talk
851 || op_replay || op_replay_latest
852 || op_look_at || op_look_for)
853 && 0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key)))
855 gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, GNUNET_PSYC_SLAVE_JOIN_NONE,
856 slicer_create (), guest_reconnected, NULL);
857 plc = GNUNET_SOCIAL_guest_get_place (gst);
863 app_recv_ego (void *cls,
864 struct GNUNET_SOCIAL_Ego *e,
865 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
868 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
870 GNUNET_CRYPTO_ecdsa_public_key_to_string (pub_key), name);
872 if (0 == memcmp (&ego_pub_key, pub_key, sizeof (*pub_key))
873 || (NULL != opt_ego && 0 == strcmp (opt_ego, name)))
884 app = GNUNET_SOCIAL_app_connect (cfg, opt_app,
897 core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
899 this_peer = *my_identity;
908 * Main function run by the scheduler.
911 * @param args remaining command-line arguments
912 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
913 * @param cfg configuration
916 run (void *cls, char *const *args, const char *cfgfile,
917 const struct GNUNET_CONFIGURATION_Handle *c)
922 opt_method = "message";
929 || op_host_enter || op_host_reconnect || op_host_leave || op_host_announce
930 || op_guest_enter || op_guest_reconnect || op_guest_leave || op_guest_talk
931 || op_replay || op_replay_latest
932 || op_look_at || op_look_for))
939 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout, NULL);
942 if ((op_host_reconnect || op_host_leave || op_host_announce
943 || op_guest_reconnect || (op_guest_enter && !opt_gns)
944 || op_guest_leave || op_guest_talk
945 || op_replay || op_replay_latest
946 || op_look_at || op_look_for)
948 || GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_place,
952 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
953 _("--place missing or invalid.\n"));
960 GNUNET_CRYPTO_ecdsa_public_key_from_string (opt_ego,
965 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
966 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
971 * The main function to obtain peer information.
973 * @param argc number of arguments from the command line
974 * @param argv command line arguments
975 * @return 0 ok, 1 on error
978 main (int argc, char *const *argv)
981 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
983 * gnunet program options in addition to the ones below:
985 * -c, --config=FILENAME
986 * -l, --logfile=LOGFILE
994 { 'B', "guest-leave", NULL,
995 gettext_noop ("say good-bye and leave somebody else's place"),
996 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_leave },
998 { 'C', "host-enter", NULL,
999 gettext_noop ("create a place"),
1000 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_enter },
1002 { 'D', "host-leave", NULL,
1003 gettext_noop ("destroy a place we were hosting"),
1004 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_leave },
1006 { 'E', "guest-enter", NULL,
1007 gettext_noop ("enter somebody else's place"),
1008 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_enter },
1010 { 'F', "look-for", NULL,
1011 gettext_noop ("find state matching name prefix"),
1012 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_look_for },
1014 { 'H', "replay-latest", NULL,
1015 gettext_noop ("replay history of messages up to the given --limit"),
1016 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_replay_latest },
1018 { 'N', "host-reconnect", NULL,
1019 gettext_noop ("reconnect to a previously created place"),
1020 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_reconnect },
1022 { 'P', "host-announce", NULL,
1023 gettext_noop ("publish something to a place we are hosting"),
1024 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_announce },
1026 { 'R', "guest-reconnect", NULL,
1027 gettext_noop ("reconnect to a previously entered place"),
1028 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_reconnect },
1030 { 'S', "look-at", NULL,
1031 gettext_noop ("search for state matching exact name"),
1032 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_look_at },
1034 { 'T', "guest-talk", NULL,
1035 gettext_noop ("submit something to somebody's place"),
1036 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_talk },
1038 { 'U', "status", NULL,
1039 gettext_noop ("list of egos and subscribed places"),
1040 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_status },
1042 { 'X', "replay", NULL,
1043 gettext_noop ("extract and replay history between message IDs --start and --until"),
1044 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_replay },
1049 { 'a', "app", "APPLICATION_ID",
1050 gettext_noop ("application ID to use when connecting"),
1051 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_app },
1053 { 'b', "body", "MESSAGE_BODY",
1054 gettext_noop ("message body to transmit"),
1055 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_body },
1057 { 'e', "ego", "NAME|PUBKEY",
1058 gettext_noop ("name or public key of ego"),
1059 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_ego },
1061 { 'f', "follow", NULL,
1062 gettext_noop ("wait for incoming messages"),
1063 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_follow },
1065 { 'g', "gns", "GNS_NAME",
1066 gettext_noop ("GNS name"),
1067 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_gns },
1069 { 'i', "peer", "PEER_ID",
1070 gettext_noop ("peer ID for --guest-enter"),
1071 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_peer },
1073 { 'k', "name", "VAR_NAME",
1074 gettext_noop ("state variable name (key) to query"),
1075 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_name },
1077 { 'm', "method", "METHOD_NAME",
1078 gettext_noop ("method name"),
1079 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_method },
1081 { 'n', "limit", NULL,
1082 gettext_noop ("number of messages to replay from history"),
1083 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_limit },
1085 { 'p', "place", "PUBKEY",
1086 gettext_noop ("key address of place"),
1087 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_place },
1089 { 's', "start", NULL,
1090 gettext_noop ("start message ID for history replay"),
1091 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_start },
1093 { 'w', "welcome", NULL,
1094 gettext_noop ("respond to entry requests by admitting all guests"),
1095 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_welcome },
1097 { 'u', "until", NULL,
1098 gettext_noop ("end message ID for history replay"),
1099 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_until },
1101 { 'y', "deny", NULL,
1102 gettext_noop ("respond to entry requests by refusing all guests"),
1103 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_deny },
1105 GNUNET_GETOPT_OPTION_END
1108 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1112 _ ("gnunet-social - Interact with the social service: enter/leave, send/receive messages, access history and state.\n");
1114 "gnunet-social [--status]\n"
1116 "gnunet-social --host-enter --ego <NAME or PUBKEY> [--follow] [--welcome | --deny]\n"
1117 "gnunet-social --host-reconnect --place <PUBKEY> [--follow] [--welcome | --deny]\n"
1118 "gnunet-social --host-leave --place <PUBKEY>\n"
1119 "gnunet-social --host-announce --place <PUBKEY> --method <METHOD_NAME> --body <MESSAGE_BODY>\n"
1121 "gnunet-social --guest-enter --place <PUBKEY> --peer <PEERID> --ego <NAME or PUBKEY> [--follow]\n"
1122 "gnunet-social --guest-enter --gns <GNS_NAME> --ego <NAME or PUBKEY> [--follow]\n"
1123 "gnunet-social --guest-reconnect --place <PUBKEY> [--follow]\n"
1124 "gnunet-social --guest-leave --place <PUBKEY>\n"
1125 "gnunet-social --guest-talk --place <PUBKEY> --method <METHOD_NAME> --body <MESSAGE_BODY>\n"
1127 "gnunet-social --history-replay --place <PUBKEY> --start <MSGID> --until <MSGID> [--method <METHOD_PREFIX>]\n"
1128 "gnunet-social --history-replay-latest --place <PUBKEY> --limit <MSG_LIMIT> [--method <METHOD_PREFIX>]\n"
1130 "gnunet-social --look-at --place <PUBKEY> --name <FULL_NAME>\n"
1131 "gnunet-social --look-for --place <PUBKEY> --name <NAME_PREFIX>\n";
1133 res = GNUNET_PROGRAM_run (argc, argv, help, usage, options, &run, NULL);
1135 GNUNET_free ((void *) argv);
1137 if (GNUNET_OK == res)