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_host_assign;
59 static int op_guest_enter;
61 /** --guest-reconnect */
62 static int op_guest_reconnect;
65 static int op_guest_leave;
68 static int op_guest_talk;
71 static char *op_replay;
73 /** --replay-latest */
74 static char *op_replay_latest;
77 static int op_look_at;
80 static int op_look_for;
86 static char *opt_app = "cli";
89 static char *opt_place;
98 static char *opt_peer;
101 static int opt_follow;
104 static int opt_welcome;
110 static char *opt_method;
113 // FIXME: should come from STDIN
114 static char *opt_data;
117 static char *opt_name;
120 static uint64_t opt_start;
123 static uint64_t opt_until;
126 static int opt_limit;
134 /** Task handle for timeout termination. */
135 struct GNUNET_SCHEDULER_Task *timeout_task;
137 const struct GNUNET_CONFIGURATION_Handle *cfg;
139 struct GNUNET_CORE_Handle *core;
140 struct GNUNET_PeerIdentity peer, this_peer;
142 struct GNUNET_SOCIAL_App *app;
144 /** public key of connected place */
145 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
147 struct GNUNET_PSYC_Slicer *slicer;
149 struct GNUNET_SOCIAL_Ego *ego;
150 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
152 struct GNUNET_SOCIAL_Host *hst;
153 struct GNUNET_SOCIAL_Guest *gst;
154 struct GNUNET_SOCIAL_Place *plc;
161 * Callback called after the host or guest place disconnected.
164 disconnected (void *cls)
166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnected()\n");
167 GNUNET_SCHEDULER_shutdown ();
172 * Callback called after the application disconnected.
175 app_disconnected (void *cls)
177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "app_disconnected()\n");
182 GNUNET_SOCIAL_host_disconnect (hst, disconnected, NULL);
186 GNUNET_SOCIAL_guest_disconnect (gst, disconnected, NULL);
191 GNUNET_SCHEDULER_shutdown ();
197 * Disconnect from connected GNUnet services.
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect()\n");
203 GNUNET_SOCIAL_app_disconnect (app, app_disconnected, NULL);
208 scheduler_shutdown (void *cls)
215 * Callback called when the program failed to finish the requested operation in time.
220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "timeout()\n");
225 schedule_success (void *cls)
233 schedule_fail (void *cls)
240 * Schedule exit with success result.
245 if (timeout_task != NULL)
247 GNUNET_SCHEDULER_cancel (timeout_task);
250 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, schedule_success, NULL);
255 * Schedule exit with failure result.
260 if (timeout_task != NULL)
262 GNUNET_SCHEDULER_cancel (timeout_task);
265 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, schedule_fail, NULL);
273 * Callback notifying about the host has left and stopped hosting the place.
275 * This also indicates the end of the connection to the service.
280 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
281 "The host has left the place.\n");
287 * Leave a place permanently and stop hosting a place.
292 GNUNET_SOCIAL_host_leave (hst, NULL, host_left, NULL);
299 * Callback notifying about the guest has left the place.
301 * This also indicates the end of the connection to the service.
304 guest_left (void *cls)
306 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
307 "The guest has left the place.\n");
312 * Leave a place permanently as guest.
317 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
318 // FIXME: wrong use of vars
319 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
320 "_message", DATA2ARG ("Leaving."));
321 GNUNET_SOCIAL_guest_leave (gst, env, guest_left, NULL);
322 GNUNET_PSYC_env_destroy (env);
328 /* ANNOUNCE / ASSIGN / TALK */
331 struct TransmitClosure
339 * Callback notifying about available buffer space to write message data
340 * when transmitting messages using host_announce() or guest_talk()
343 notify_data (void *cls, uint16_t *data_size, void *data)
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "Transmit notify data: %u bytes available\n",
349 struct TransmitClosure *tmit = cls;
350 uint16_t size = tmit->size < *data_size ? tmit->size : *data_size;
352 memcpy (data, tmit->data, size);
359 if (op_host_announce || op_host_assign || op_guest_talk)
373 * Host announcement - send a message to the place.
376 host_announce (const char *method, const char *data, size_t data_size)
378 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
379 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
380 "_foo", DATA2ARG ("bar baz"));
382 tmit = (struct TransmitClosure) {};
384 tmit.size = data_size;
386 GNUNET_SOCIAL_host_announce (hst, method, env,
388 GNUNET_SOCIAL_ANNOUNCE_NONE);
389 GNUNET_PSYC_env_destroy (env);
394 * Assign a state var of @a name to the value of @a data.
397 host_assign (const char *name, const char *data, size_t data_size)
399 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
400 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN,
401 name, data, data_size);
403 tmit = (struct TransmitClosure) {};
404 GNUNET_SOCIAL_host_announce (hst, "_assign", env,
406 GNUNET_SOCIAL_ANNOUNCE_NONE);
407 GNUNET_PSYC_env_destroy (env);
412 * Guest talk request to host.
415 guest_talk (const char *method,
416 const char *data, size_t data_size)
418 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
419 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
420 "_foo", DATA2ARG ("bar baz"));
422 tmit = (struct TransmitClosure) {};
424 tmit.size = data_size;
426 GNUNET_SOCIAL_guest_talk (gst, method, env,
428 GNUNET_SOCIAL_TALK_NONE);
429 GNUNET_PSYC_env_destroy (env);
437 * Callback notifying about the end of history replay results.
440 recv_history_replay_result (void *cls, int64_t result,
441 const void *data, uint16_t data_size)
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444 "Received history replay result: %" PRId64 "\n"
446 result, data_size, (const char *) data);
448 if (op_replay || op_replay_latest)
456 * Replay history between a given @a start and @a end message IDs,
457 * optionally filtered by a method @a prefix.
460 history_replay (uint64_t start, uint64_t end, const char *prefix)
462 GNUNET_SOCIAL_place_history_replay (plc, start, end, prefix,
463 GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
465 recv_history_replay_result,
471 * Replay latest @a limit messages.
474 history_replay_latest (uint64_t limit, const char *prefix)
476 GNUNET_SOCIAL_place_history_replay_latest (plc, limit, prefix,
477 GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
479 recv_history_replay_result,
488 * Callback notifying about the end of state var results.
491 look_result (void *cls, int64_t result_code,
492 const void *data, uint16_t data_size)
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "Received look result: %" PRId64 "\n", result_code);
497 if (op_look_at || op_look_for)
505 * Callback notifying about a state var result.
509 const struct GNUNET_MessageHeader *mod,
513 uint32_t full_value_size)
515 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
516 "Received var: %s\n%.*s\n",
517 name, value_size, (const char *) value);
522 * Look for a state var using exact match of the name.
525 look_at (const char *full_name)
527 GNUNET_SOCIAL_place_look_at (plc, full_name, look_var, look_result, NULL);
532 * Look for state vars by name prefix.
535 look_for (const char *name_prefix)
537 GNUNET_SOCIAL_place_look_for (plc, name_prefix, look_var, look_result, NULL);
545 * Callback notifying about the start of a new incoming message.
548 slicer_recv_method (void *cls,
549 const struct GNUNET_PSYC_MessageHeader *msg,
550 const struct GNUNET_PSYC_MessageMethod *meth,
552 const char *method_name)
554 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
555 "Received method for message ID %" PRIu64 ":\n"
557 message_id, method_name, ntohl (meth->flags));
562 * Callback notifying about an incoming modifier.
565 slicer_recv_modifier (void *cls,
566 const struct GNUNET_PSYC_MessageHeader *msg,
567 const struct GNUNET_MessageHeader *pmsg,
569 enum GNUNET_PSYC_Operator oper,
573 uint16_t full_value_size)
575 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
576 "Received modifier for message ID %" PRIu64 ":\n"
577 "%c%s: %.*s (size: %u)\n",
578 message_id, oper, name, value_size, (const char *) value, value_size);
583 * Callback notifying about an incoming data fragment.
586 slicer_recv_data (void *cls,
587 const struct GNUNET_PSYC_MessageHeader *msg,
588 const struct GNUNET_MessageHeader *pmsg,
593 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
594 "Received data for message ID %" PRIu64 ":\n"
596 message_id, data_size, (const char *) data);
601 * Callback notifying about the end of a message.
604 slicer_recv_eom (void *cls,
605 const struct GNUNET_PSYC_MessageHeader *msg,
606 const struct GNUNET_MessageHeader *pmsg,
608 uint8_t is_cancelled)
610 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
611 "Received end of message ID %" PRIu64
613 message_id, is_cancelled);
618 * Create a slicer for receiving message parts.
620 static struct GNUNET_PSYC_Slicer *
623 slicer = GNUNET_PSYC_slicer_create ();
625 /* register slicer to receive incoming messages with any method name */
626 GNUNET_PSYC_slicer_method_add (slicer, "", NULL,
627 slicer_recv_method, slicer_recv_modifier,
628 slicer_recv_data, slicer_recv_eom, NULL);
637 * Callback called when the guest receives an entry decision from the host.
639 * It is called once after using guest_enter() or guest_enter_by_name(),
640 * in case of a reconnection only the local enter callback is called.
643 guest_recv_entry_decision (void *cls,
645 const struct GNUNET_PSYC_Message *entry_msg)
647 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
648 "Guest received entry decision %d\n",
651 if (NULL != entry_msg)
653 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
654 const char *method_name = NULL;
655 const void *data = NULL;
656 uint16_t data_size = 0;
657 struct GNUNET_PSYC_MessageHeader *
658 pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg);
659 GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size);
662 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
664 method_name, data_size, (const char *) data);
667 if (op_guest_enter && !opt_follow)
675 * Callback called after a guest connection is established to the local service.
678 guest_recv_local_enter (void *cls, int result,
679 const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
680 uint64_t max_message_id)
682 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
683 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
684 "Guest entered to local place: %s, max_message_id: %" PRIu64 "\n",
685 pub_str, max_message_id);
686 GNUNET_free (pub_str);
687 GNUNET_assert (0 <= result);
689 if (op_guest_enter && !opt_follow)
697 * Create entry requset message.
699 static struct GNUNET_PSYC_Message *
700 guest_enter_msg_create ()
702 const char *method_name = "_request_enter";
703 struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
704 GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET,
705 "_foo", DATA2ARG ("bar"));
706 void *data = "let me in";
707 uint16_t data_size = strlen (data) + 1;
709 return GNUNET_PSYC_message_create (method_name, env, data, data_size);
714 * Enter a place as guest, using its public key and peer ID.
717 guest_enter (const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
718 const struct GNUNET_PeerIdentity *peer)
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "Entering to place as guest.\n");
725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n");
730 gst = GNUNET_SOCIAL_guest_enter (app, ego, pub_key,
731 GNUNET_PSYC_SLAVE_JOIN_NONE,
732 peer, 0, NULL, guest_enter_msg_create (),
734 guest_recv_local_enter,
735 guest_recv_entry_decision, NULL);
736 plc = GNUNET_SOCIAL_guest_get_place (gst);
741 * Enter a place as guest using its GNS address.
744 guest_enter_by_name (const char *gns_name)
746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
747 "Entering to place by name as guest.\n");
749 gst = GNUNET_SOCIAL_guest_enter_by_name (app, ego, gns_name, NULL,
750 guest_enter_msg_create (), slicer,
751 guest_recv_local_enter,
752 guest_recv_entry_decision, NULL);
753 plc = GNUNET_SOCIAL_guest_get_place (gst);
761 * Callback called when a @a nym wants to enter the place.
763 * The request needs to be replied with an entry decision.
766 host_answer_door (void *cls,
767 struct GNUNET_SOCIAL_Nym *nym,
768 const char *method_name,
769 struct GNUNET_PSYC_Environment *env,
773 const struct GNUNET_CRYPTO_EcdsaPublicKey *
774 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
776 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
778 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
779 "Entry request: %s\n", nym_str);
780 GNUNET_free (nym_str);
784 struct GNUNET_PSYC_Message *
785 resp = GNUNET_PSYC_message_create ("_notice_place_admit", env,
786 DATA2ARG ("Welcome, nym!"));
787 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, resp);
792 struct GNUNET_PSYC_Message *
793 resp = GNUNET_PSYC_message_create ("_notice_place_refuse", NULL,
794 DATA2ARG ("Go away!"));
795 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, resp);
804 * Callback called when a @a nym has left the place.
807 host_farewell (void *cls,
808 const struct GNUNET_SOCIAL_Nym *nym,
809 struct GNUNET_PSYC_Environment *env)
811 const struct GNUNET_CRYPTO_EcdsaPublicKey *
812 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
814 nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
816 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
817 "Farewell: %s\n", nym_str);
818 GNUNET_free (nym_str);
823 * Callback called after the host entered the place.
826 host_entered (void *cls, int result,
827 const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key,
828 uint64_t max_message_id)
830 place_pub_key = *pub_key;
831 char *pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (pub_key);
832 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
833 "Host entered: %s, max_message_id: %" PRIu64 "\n",
834 pub_str, max_message_id);
835 GNUNET_free (pub_str);
837 if (op_host_enter && !opt_follow)
845 * Enter and start hosting a place.
850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "host_enter()\n");
854 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "--ego missing or invalid\n");
859 hst = GNUNET_SOCIAL_host_enter (app, ego,
860 GNUNET_PSYC_CHANNEL_PRIVATE,
861 slicer_create (), host_entered,
862 host_answer_door, host_farewell, NULL);
863 plc = GNUNET_SOCIAL_host_get_place (hst);
867 /* PLACE RECONNECT */
871 * Perform operations common to both host & guest places.
876 static int first_run = GNUNET_YES;
877 if (GNUNET_NO == first_run)
879 first_run = GNUNET_NO;
882 history_replay (opt_start, opt_until, opt_method);
884 else if (op_replay_latest) {
885 history_replay_latest (opt_limit, opt_method);
887 else if (op_look_at) {
890 else if (op_look_for) {
897 * Callback called after reconnecting to a host place.
900 host_reconnected (void *cls, int result,
901 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
902 uint64_t max_message_id)
904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905 "Host reconnected.\n");
910 else if (op_host_announce) {
911 host_announce (opt_method, opt_data, strlen (opt_data));
913 else if (op_host_assign) {
914 host_assign (opt_name, opt_data, strlen (opt_data) + 1);
917 place_reconnected ();
923 * Callback called after reconnecting to a guest place.
926 guest_reconnected (void *cls, int result,
927 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
928 uint64_t max_message_id)
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Guest reconnected.\n");
933 if (op_guest_leave) {
936 else if (op_guest_talk) {
937 guest_talk (opt_method, opt_data, strlen (opt_data));
940 place_reconnected ();
949 * Callback called after the ego and place callbacks.
952 app_connected (void *cls)
954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
955 "App connected: %p\n", cls);
961 else if (op_host_enter)
965 else if (op_guest_enter)
969 guest_enter_by_name (opt_gns);
975 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_peer,
979 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
989 guest_enter (&place_pub_key, &peer);
996 * Callback notifying about a host place available for reconnection.
999 app_recv_host (void *cls,
1000 struct GNUNET_SOCIAL_HostConnection *hconn,
1001 struct GNUNET_SOCIAL_Ego *ego,
1002 const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key,
1003 enum GNUNET_SOCIAL_AppPlaceState place_state)
1005 char *host_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (host_pub_key);
1006 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1007 "Host: %s\n", host_pub_str);
1008 GNUNET_free (host_pub_str);
1010 if ((op_host_reconnect || op_host_leave || op_host_announce || op_host_assign
1011 || op_replay || op_replay_latest
1012 || op_look_at || op_look_for)
1013 && 0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key)))
1015 hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, slicer_create (), host_reconnected,
1016 host_answer_door, host_farewell, NULL);
1017 plc = GNUNET_SOCIAL_host_get_place (hst);
1023 * Callback notifying about a guest place available for reconnection.
1026 app_recv_guest (void *cls,
1027 struct GNUNET_SOCIAL_GuestConnection *gconn,
1028 struct GNUNET_SOCIAL_Ego *ego,
1029 const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key,
1030 enum GNUNET_SOCIAL_AppPlaceState place_state)
1032 char *guest_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (guest_pub_key);
1033 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1034 "Guest: %s\n", guest_pub_str);
1035 GNUNET_free (guest_pub_str);
1037 if ((op_guest_reconnect || op_guest_leave || op_guest_talk
1038 || op_replay || op_replay_latest
1039 || op_look_at || op_look_for)
1040 && 0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key)))
1042 gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, GNUNET_PSYC_SLAVE_JOIN_NONE,
1043 slicer_create (), guest_reconnected, NULL);
1044 plc = GNUNET_SOCIAL_guest_get_place (gst);
1050 * Callback notifying about an available ego.
1053 app_recv_ego (void *cls,
1054 struct GNUNET_SOCIAL_Ego *e,
1055 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
1058 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1060 GNUNET_CRYPTO_ecdsa_public_key_to_string (pub_key), name);
1062 if (0 == memcmp (&ego_pub_key, pub_key, sizeof (*pub_key))
1063 || (NULL != opt_ego && 0 == strcmp (opt_ego, name)))
1073 * Establish application connection to receive available egos and places.
1076 app_connect (void *cls)
1078 GNUNET_CORE_disconnect (core);
1081 app = GNUNET_SOCIAL_app_connect (cfg, opt_app,
1094 core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1096 this_peer = *my_identity;
1097 GNUNET_SCHEDULER_add_now (app_connect, NULL);
1105 * Main function run by the scheduler.
1107 * @param cls closure
1108 * @param args remaining command-line arguments
1109 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1110 * @param cfg configuration
1113 run (void *cls, char *const *args, const char *cfgfile,
1114 const struct GNUNET_CONFIGURATION_Handle *c)
1119 opt_method = "message";
1126 || op_host_enter || op_host_reconnect || op_host_leave
1127 || op_host_announce || op_host_assign
1128 || op_guest_enter || op_guest_reconnect
1129 || op_guest_leave || op_guest_talk
1130 || op_replay || op_replay_latest
1131 || op_look_at || op_look_for))
1136 GNUNET_SCHEDULER_add_shutdown (scheduler_shutdown, NULL);
1139 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, timeout, NULL);
1142 if ((op_host_reconnect || op_host_leave || op_host_announce || op_host_assign
1143 || op_guest_reconnect || (op_guest_enter && !opt_gns)
1144 || op_guest_leave || op_guest_talk
1145 || op_replay || op_replay_latest
1146 || op_look_at || op_look_for)
1148 || GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (opt_place,
1152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1153 _("--place missing or invalid.\n"));
1160 GNUNET_CRYPTO_ecdsa_public_key_from_string (opt_ego,
1165 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
1166 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1171 * The main function to obtain peer information.
1173 * @param argc number of arguments from the command line
1174 * @param argv command line arguments
1175 * @return 0 ok, 1 on error
1178 main (int argc, char *const *argv)
1181 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1183 * gnunet program options in addition to the ones below:
1185 * -c, --config=FILENAME
1186 * -l, --logfile=LOGFILE
1187 * -L, --log=LOGLEVEL
1194 { 'A', "host-assign", NULL,
1195 gettext_noop ("assign --name in state to --data"),
1196 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_assign },
1198 { 'B', "guest-leave", NULL,
1199 gettext_noop ("say good-bye and leave somebody else's place"),
1200 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_leave },
1202 { 'C', "host-enter", NULL,
1203 gettext_noop ("create a place"),
1204 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_enter },
1206 { 'D', "host-leave", NULL,
1207 gettext_noop ("destroy a place we were hosting"),
1208 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_leave },
1210 { 'E', "guest-enter", NULL,
1211 gettext_noop ("enter somebody else's place"),
1212 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_enter },
1214 { 'F', "look-for", NULL,
1215 gettext_noop ("find state matching name prefix"),
1216 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_look_for },
1218 { 'H', "replay-latest", NULL,
1219 gettext_noop ("replay history of messages up to the given --limit"),
1220 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_replay_latest },
1222 { 'N', "host-reconnect", NULL,
1223 gettext_noop ("reconnect to a previously created place"),
1224 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_reconnect },
1226 { 'P', "host-announce", NULL,
1227 gettext_noop ("publish something to a place we are hosting"),
1228 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_host_announce },
1230 { 'R', "guest-reconnect", NULL,
1231 gettext_noop ("reconnect to a previously entered place"),
1232 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_reconnect },
1234 { 'S', "look-at", NULL,
1235 gettext_noop ("search for state matching exact name"),
1236 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_look_at },
1238 { 'T', "guest-talk", NULL,
1239 gettext_noop ("submit something to somebody's place"),
1240 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_guest_talk },
1242 { 'U', "status", NULL,
1243 gettext_noop ("list of egos and subscribed places"),
1244 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_status },
1246 { 'X', "replay", NULL,
1247 gettext_noop ("extract and replay history between message IDs --start and --until"),
1248 GNUNET_NO, &GNUNET_GETOPT_set_one, &op_replay },
1253 { 'a', "app", "APPLICATION_ID",
1254 gettext_noop ("application ID to use when connecting"),
1255 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_app },
1257 { 'd', "data", "DATA",
1258 gettext_noop ("message body or state value"),
1259 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_data },
1261 { 'e', "ego", "NAME|PUBKEY",
1262 gettext_noop ("name or public key of ego"),
1263 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_ego },
1265 { 'f', "follow", NULL,
1266 gettext_noop ("wait for incoming messages"),
1267 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_follow },
1269 { 'g', "gns", "GNS_NAME",
1270 gettext_noop ("GNS name"),
1271 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_gns },
1273 { 'i', "peer", "PEER_ID",
1274 gettext_noop ("peer ID for --guest-enter"),
1275 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_peer },
1277 { 'k', "name", "VAR_NAME",
1278 gettext_noop ("name (key) to query from state"),
1279 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_name },
1281 { 'm', "method", "METHOD_NAME",
1282 gettext_noop ("method name"),
1283 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_method },
1285 { 'n', "limit", NULL,
1286 gettext_noop ("number of messages to replay from history"),
1287 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_limit },
1289 { 'p', "place", "PUBKEY",
1290 gettext_noop ("key address of place"),
1291 GNUNET_YES, &GNUNET_GETOPT_set_string, &opt_place },
1293 { 's', "start", NULL,
1294 gettext_noop ("start message ID for history replay"),
1295 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_start },
1297 { 'w', "welcome", NULL,
1298 gettext_noop ("respond to entry requests by admitting all guests"),
1299 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_welcome },
1301 { 'u', "until", NULL,
1302 gettext_noop ("end message ID for history replay"),
1303 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &opt_until },
1305 { 'y', "deny", NULL,
1306 gettext_noop ("respond to entry requests by refusing all guests"),
1307 GNUNET_NO, &GNUNET_GETOPT_set_one, &opt_deny },
1309 GNUNET_GETOPT_OPTION_END
1312 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1316 _ ("gnunet-social - Interact with the social service: enter/leave, send/receive messages, access history and state.\n");
1318 "gnunet-social [--status]\n"
1320 "gnunet-social --host-enter --ego <NAME or PUBKEY> [--follow] [--welcome | --deny]\n"
1321 "gnunet-social --host-reconnect --place <PUBKEY> [--follow] [--welcome | --deny]\n"
1322 "gnunet-social --host-leave --place <PUBKEY>\n"
1323 "gnunet-social --host-assign --place <PUBKEY> --name <NAME> --data <VALUE>\n"
1324 // FIXME: some state ops not implemented yet (no hurry)
1325 // "gnunet-social --host-augment --place <PUBKEY> --name <NAME> --data <VALUE>\n"
1326 // "gnunet-social --host-diminish --place <PUBKEY> --name <NAME> --data <VALUE>\n"
1327 // "gnunet-social --host-set --place <PUBKEY> --name <NAME> --data <VALUE>\n"
1328 "gnunet-social --host-announce --place <PUBKEY> --method <METHOD_NAME> --data <MESSAGE_BODY>\n"
1330 "gnunet-social --guest-enter --place <PUBKEY> --peer <PEERID> --ego <NAME or PUBKEY> [--follow]\n"
1331 "gnunet-social --guest-enter --gns <GNS_NAME> --ego <NAME or PUBKEY> [--follow]\n"
1332 "gnunet-social --guest-reconnect --place <PUBKEY> [--follow]\n"
1333 "gnunet-social --guest-leave --place <PUBKEY>\n"
1334 "gnunet-social --guest-talk --place <PUBKEY> --method <METHOD_NAME> --data <MESSAGE_BODY>\n"
1336 "gnunet-social --history-replay --place <PUBKEY> --start <MSGID> --until <MSGID> [--method <METHOD_PREFIX>]\n"
1337 "gnunet-social --history-replay-latest --place <PUBKEY> --limit <MSG_LIMIT> [--method <METHOD_PREFIX>]\n"
1339 "gnunet-social --look-at --place <PUBKEY> --name <FULL_NAME>\n"
1340 "gnunet-social --look-for --place <PUBKEY> --name <NAME_PREFIX>\n";
1342 res = GNUNET_PROGRAM_run (argc, argv, help, usage, options, &run, NULL);
1344 GNUNET_free ((void *) argv);
1346 if (GNUNET_OK == res)