X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Finclude%2Fgnunet_testing_lib.h;h=479cb07e09c3eb068a0eaa97e8f894e175f3c93b;hb=f9b7adcad3cc030a800cbc9a96709454c45ae06f;hp=3d36207bd7c1ed8d2e5e9ffe4632626c9dc0309e;hpb=ecc8bf638aae207dc1686f77843a2a6126b5df0b;p=oweals%2Fgnunet.git diff --git a/src/include/gnunet_testing_lib.h b/src/include/gnunet_testing_lib.h index 3d36207bd..479cb07e0 100644 --- a/src/include/gnunet_testing_lib.h +++ b/src/include/gnunet_testing_lib.h @@ -4,7 +4,7 @@ GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -49,6 +49,28 @@ extern "C" */ struct GNUNET_TESTING_Daemon; +/** + * Linked list of hostnames to use for starting daemons. + */ +struct GNUNET_TESTING_Host +{ + struct GNUNET_TESTING_Host *next; + char *hostname; +}; + +/** + * Prototype of a function that will be called whenever + * a daemon was started by the testing library. + * + * @param cls closure + * @param id identifier for the daemon, NULL on error + * @param d handle for the daemon + * @param emsg error message (NULL on success) + */ +typedef void (*GNUNET_TESTING_NotifyHostkeyCreated)(void *cls, + const struct GNUNET_PeerIdentity *id, + struct GNUNET_TESTING_Daemon *d, + const char *emsg); /** * Prototype of a function that will be called whenever @@ -83,10 +105,25 @@ enum GNUNET_TESTING_StartPhase SP_COPYING, /** - * Configuration file has been copied, start ARM on target system. + * Configuration file has been copied, generate hostkey. */ SP_COPIED, + /** + * Create the hostkey for the peer. + */ + SP_HOSTKEY_CREATE, + + /** + * Hostkey generated, wait for topology to be finished. + */ + SP_HOSTKEY_CREATED, + + /** + * Topology has been created, now start ARM. + */ + SP_TOPOLOGY_SETUP, + /** * ARM has been started, check that it has properly daemonized and * then try to connect to the CORE service (which should be @@ -131,6 +168,16 @@ enum GNUNET_TESTING_StartPhase typedef void (*GNUNET_TESTING_NotifyCompletion)(void *cls, const char *emsg); +/** + * Prototype of a function that will be called with the + * number of connections created for a particular topology. + * + * @param cls closure + * @param num_connections the number of connections created + */ +typedef void (*GNUNET_TESTING_NotifyConnections)(void *cls, + unsigned int num_connections); + /** * Handle for a GNUnet daemon (technically a set of * daemons; the handle is really for the master ARM @@ -148,6 +195,11 @@ struct GNUNET_TESTING_Daemon */ struct GNUNET_CONFIGURATION_Handle *cfg; + /** + * At what time to give up starting the peer + */ + struct GNUNET_TIME_Absolute max_timeout; + /** * Host to run GNUnet on. */ @@ -169,6 +221,17 @@ struct GNUNET_TESTING_Daemon */ char *cfgfile; + /** + * Callback to inform initiator that the peer's + * hostkey has been created. + */ + GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback; + + /** + * Closure for hostkey creation callback. + */ + void *hostkey_cls; + /** * Function to call when the peer is running. */ @@ -216,12 +279,6 @@ struct GNUNET_TESTING_Daemon */ pid_t pid; - /** - * How many iterations have we been waiting for - * the started process to complete? - */ - unsigned int wait_runs; - /** * In which phase are we during the start of * this process? @@ -248,10 +305,31 @@ struct GNUNET_TESTING_Daemon */ struct GNUNET_HELLO_Message *hello; + /** + * Handle to a pipe for reading the hostkey. + */ + struct GNUNET_DISK_PipeHandle *pipe_stdout; + + /** + * Output from gnunet-peerinfo is read into this buffer. + */ + char hostkeybuf[105]; + + /** + * Current position in 'hostkeybuf' (for reading from gnunet-peerinfo) + */ + unsigned int hostkeybufpos; + /** * Set to GNUNET_YES once the peer is up. */ int running; + + /** + * Used to tell shutdown not to remove configuration for the peer + * (if it's going to be restarted later) + */ + int churn; }; @@ -268,6 +346,7 @@ struct GNUNET_TESTING_PeerGroup; * @param cls closure * @param first peer id for first daemon * @param second peer id for the second daemon + * @param distance distance between the connected peers * @param first_cfg config for the first daemon * @param second_cfg config for the second daemon * @param first_daemon handle for the first daemon @@ -275,13 +354,31 @@ struct GNUNET_TESTING_PeerGroup; * @param emsg error message (NULL on success) */ typedef void (*GNUNET_TESTING_NotifyConnection)(void *cls, - const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg); + const struct GNUNET_PeerIdentity *first, + const struct GNUNET_PeerIdentity *second, + uint32_t distance, + const struct GNUNET_CONFIGURATION_Handle *first_cfg, + const struct GNUNET_CONFIGURATION_Handle *second_cfg, + struct GNUNET_TESTING_Daemon *first_daemon, + struct GNUNET_TESTING_Daemon *second_daemon, + const char *emsg); + +/** + * Prototype of a callback function indicating that two peers + * are currently connected. + * + * @param cls closure + * @param first peer id for first daemon + * @param second peer id for the second daemon + * @param distance distance between the connected peers + * @param emsg error message (NULL on success) + */ +typedef void (*GNUNET_TESTING_NotifyTopology)(void *cls, + const struct GNUNET_PeerIdentity *first, + const struct GNUNET_PeerIdentity *second, + struct GNUNET_TIME_Relative latency, + uint32_t distance, + const char *emsg); /** * Starts a GNUnet daemon. GNUnet must be installed on the target @@ -291,33 +388,92 @@ typedef void (*GNUNET_TESTING_NotifyConnection)(void *cls, * * @param sched scheduler to use * @param cfg configuration to use + * @param timeout how long to wait starting up peers * @param hostname name of the machine where to run GNUnet * (use NULL for localhost). + * @param hostkey_callback function to call once the hostkey has been + * generated for this peer, but it hasn't yet been started + * (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start) + * @param hostkey_cls closure for hostkey callback * @param cb function to call with the result * @param cb_cls closure for cb * @return handle to the daemon (actual start will be completed asynchronously) */ struct GNUNET_TESTING_Daemon * GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, - const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *hostname, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls); + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TIME_Relative timeout, + const char *hostname, + GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback, + void *hostkey_cls, + GNUNET_TESTING_NotifyDaemonRunning cb, + void *cb_cls); + +/** + * Continues GNUnet daemon startup when user wanted to be notified + * once a hostkey was generated (for creating friends files, blacklists, + * etc.). + * + * @param daemon the daemon to finish starting + */ +void +GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon); + +/** + * Restart (stop and start) a GNUnet daemon. + * + * @param d the daemon that should be restarted + * @param cb function called once the daemon is (re)started + * @param cb_cls closure for cb + */ +void +GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d, + GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls); + +/** + * Start a peer that has previously been stopped using the daemon_stop + * call (and files weren't deleted and the allow restart flag) + * + * @param daemon the daemon to start (has been previously stopped) + * @param timeout how long to wait for restart + * @param cb the callback for notification when the peer is running + * @param cb_cls closure for the callback + */ +void +GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyDaemonRunning cb, + void *cb_cls); +/** + * Get a certain testing daemon handle. + * + * @param pg handle to the set of running peers + * @param position the number of the peer to return + */ struct GNUNET_TESTING_Daemon * -GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int position); +GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, + unsigned int position); /** * Stops a GNUnet daemon. * * @param d the daemon that should be stopped + * @param timeout how long to wait for process for shutdown to complete * @param cb function called once the daemon was stopped * @param cb_cls closure for cb + * @param delete_files GNUNET_YES to remove files, GNUNET_NO + * to leave them (i.e. for restarting at a later time, + * or logfile inspection once finished) + * @param allow_restart GNUNET_YES to restart peer later (using this API) + * GNUNET_NO to kill off and clean up for good */ -void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, - GNUNET_TESTING_NotifyCompletion cb, - void * cb_cls); +void +GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyCompletion cb, void *cb_cls, + int delete_files, int allow_restart); /** @@ -365,32 +521,99 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, * @param sched scheduler to use * @param cfg configuration template to use * @param total number of daemons to start + * @param timeout total time allowed for peers to start + * @param hostkey_callback function to call on each peers hostkey generation + * if NULL, peers will be started by this call, if non-null, + * GNUNET_TESTING_daemons_continue_startup must be called after + * successful hostkey generation + * @param hostkey_cls closure for hostkey callback * @param cb function to call on each daemon that was started * @param cb_cls closure for cb * @param connect_callback function to call each time two hosts are connected * @param connect_callback_cls closure for connect_callback - * @param hostnames space-separated list of hostnames to use, - * NULL to use localhost only + * @param hostnames linked list of hosts to use to start peers on (NULL to run on localhost only) + * * @return NULL on error, otherwise handle to control peer group */ struct GNUNET_TESTING_PeerGroup * GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, - const struct GNUNET_CONFIGURATION_Handle *cfg, - unsigned int total, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls, - GNUNET_TESTING_NotifyConnection connect_callback, - void *connect_callback_cls, - const char *hostnames); + const struct GNUNET_CONFIGURATION_Handle *cfg, + unsigned int total, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback, + void *hostkey_cls, + GNUNET_TESTING_NotifyDaemonRunning cb, + void *cb_cls, + GNUNET_TESTING_NotifyConnection + connect_callback, void *connect_callback_cls, + const struct GNUNET_TESTING_Host *hostnames); + +/** + * Function which continues a peer group starting up + * after successfully generating hostkeys for each peer. + * + * @param pg the peer group to continue starting + */ +void +GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg); + +/** + * Restart all peers in the given group. + * + * @param pg the handle to the peer group + * @param callback function to call on completion (or failure) + * @param callback_cls closure for the callback function + */ +void +GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, + GNUNET_TESTING_NotifyCompletion callback, + void *callback_cls); /** * Shutdown all peers started in the given group. * * @param pg handle to the peer group + * @param timeout how long to wait for shutdown + * @param cb callback to notify upon success or failure + * @param cb_cls closure for cb + */ +void +GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyCompletion cb, + void *cb_cls); + + +/** + * Simulate churn by stopping some peers (and possibly + * re-starting others if churn is called multiple times). This + * function can only be used to create leave-join churn (peers "never" + * leave for good). First "voff" random peers that are currently + * online will be taken offline; then "von" random peers that are then + * offline will be put back online. No notifications will be + * generated for any of these operations except for the callback upon + * completion. Note that the implementation is at liberty to keep + * the ARM service itself (but none of the other services or daemons) + * running even though the "peer" is being varied offline. + * + * @param pg handle for the peer group + * @param voff number of peers that should go offline + * @param von number of peers that should come back online; + * must be zero on first call (since "testbed_start" + * always starts all of the peers) + * @param timeout how long to wait for operations to finish before + * giving up + * @param cb function to call at the end + * @param cb_cls closure for cb */ void -GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg); +GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg, + unsigned int voff, + unsigned int von, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyCompletion cb, + void *cb_cls); /** @@ -435,91 +658,156 @@ enum GNUNET_TESTING_Topology GNUNET_TESTING_TOPOLOGY_INTERNAT, /** - * FIXME: implement + * Scale free topology. */ GNUNET_TESTING_TOPOLOGY_SCALE_FREE, + /** + * Straight line topology. + */ + GNUNET_TESTING_TOPOLOGY_LINE, + /** * All peers are disconnected. */ GNUNET_TESTING_TOPOLOGY_NONE }; +/** + * Options for connecting a topology. + */ +enum GNUNET_TESTING_TopologyOption +{ + /** + * Try to connect all peers specified in the topology. + */ + GNUNET_TESTING_TOPOLOGY_OPTION_ALL, + + /** + * Choose a random subset of connections to create. + */ + GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM, + + /** + * Create at least X connections for each peer. + */ + GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM, + + /** + * Using a depth first search, create one connection + * per peer. If any are missed (graph disconnected) + * start over at those peers until all have at least one + * connection. + */ + GNUNET_TESTING_TOPOLOGY_OPTION_DFS, + + /** + * No options specified. + */ + GNUNET_TESTING_TOPOLOGY_OPTION_NONE +}; + + +/** + * Get a topology from a string input. + * + * @param topology where to write the retrieved topology + * @param topology_string The string to attempt to + * get a configuration value from + * @return GNUNET_YES if topology string matched a + * known topology, GNUNET_NO if not + */ +int +GNUNET_TESTING_topology_get(enum GNUNET_TESTING_Topology *topology, char * topology_string); /** - * FIXME: document + * Get connect topology option from string input. + * + * @param topology_option where to write the retrieved topology + * @param topology_string The string to attempt to + * get a configuration value from + * @return GNUNET_YES if topology string matched a + * known topology, GNUNET_NO if not */ int -GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg - /* enum GNUNET_TESTING_Topology topo */); +GNUNET_TESTING_topology_option_get(enum GNUNET_TESTING_TopologyOption *topology_option, + char * topology_string); /** - * Start "count" GNUnet daemons with a particular topology. + * Takes a peer group and creates a topology based on the + * one specified. Creates a topology means generates friend + * files for the peers so they can only connect to those allowed + * by the topology. This will only have an effect once peers + * are started if the FRIENDS_ONLY option is set in the base + * config. Also takes an optional restrict topology which + * disallows direct TCP connections UNLESS they are specified in + * the restricted topology. * - * @param sched scheduler to use - * @param cfg configuration template to use - * @param count number of peers the testbed should have - * @param topology desired topology (enforced via F2F) - * @param cb function to call on each daemon that was started - * @param cb_cls closure for cb - * @param hostname where to run the peers; can be NULL (to run - * everything on localhost). Additional - * hosts can be specified using a NULL-terminated list of - * varargs, hosts will then be used round-robin from that - * list. - * @return handle to control the testbed - */ -struct GNUNET_TESTING_Testbed * -GNUNET_TESTING_testbed_start (struct GNUNET_SCHEDULER_Handle *sched, - const struct GNUNET_CONFIGURATION_Handle *cfg, - unsigned int count, - enum GNUNET_TESTING_Topology topology, - GNUNET_TESTING_NotifyDaemonRunning cb, - void *cb_cls, - const char *hostname, - ...); - - -/** - * Stop all of the daemons started with the start function. + * @param pg the peer group struct representing the running peers + * @param topology which topology to connect the peers in + * @param restrict_topology allow only direct TCP connections in this topology + * @param restrict_transports space delimited list of transports to blacklist + * to create restricted topology * - * @param tb handle for the testbed - * @param cb function to call when done - * @param cb_cls closure for cb + * @return the maximum number of connections were all allowed peers + * connected to each other + */ +int +GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, + enum GNUNET_TESTING_Topology topology, + enum GNUNET_TESTING_Topology restrict_topology, + char *restrict_transports); + +/** + * Iterate over all (running) peers in the peer group, retrieve + * all connections that each currently has. + * + * @param pg the peer group we are concerned with + * @param cb callback for topology information + * @param cls closure for callback */ void -GNUNET_TESTING_testbed_stop (struct GNUNET_TESTING_Testbed *tb, - GNUNET_TESTING_NotifyCompletion cb, - void *cb_cls ); +GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyTopology cb, void *cls); +/** + * There are many ways to connect peers that are supported by this function. + * To connect peers in the same topology that was created via the + * GNUNET_TESTING_create_topology, the topology variable must be set to + * GNUNET_TESTING_TOPOLOGY_NONE. If the topology variable is specified, + * a new instance of that topology will be generated and attempted to be + * connected. This could result in some connections being impossible, + * because some topologies are non-deterministic. + * + * @param pg the peer group struct representing the running peers + * @param topology which topology to connect the peers in + * @param options options for connecting the topology + * @param option_modifier modifier for options that take a parameter + * @return the number of connections that will be attempted, GNUNET_SYSERR on error + */ +int +GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg, + enum GNUNET_TESTING_Topology topology, + enum GNUNET_TESTING_TopologyOption options, + double option_modifier); /** - * Simulate churn in the testbed by stopping some peers (and possibly - * re-starting others if churn is called multiple times). This - * function can only be used to create leave-join churn (peers "never" - * leave for good). First "voff" random peers that are currently - * online will be taken offline; then "von" random peers that are then - * offline will be put back online. No notifications will be - * generated for any of these operations except for the callback upon - * completion. Note that the implementation is at liberty to keep - * the ARM service itself (but none of the other services or daemons) - * running even though the "peer" is being varied offline. + * Start or stop an individual peer from the given group. * - * @param tb handle for the testbed - * @param voff number of peers that should go offline - * @param von number of peers that should come back online; - * must be zero on first call (since "testbed_start" - * always starts all of the peers) + * @param pg handle to the peer group + * @param offset which peer to start or stop + * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it + * @param timeout how long to wait for shutdown * @param cb function to call at the end * @param cb_cls closure for cb */ void -GNUNET_TESTING_testbed_churn (struct GNUNET_TESTING_Testbed *tb, - unsigned int voff, - unsigned int von, - GNUNET_TESTING_NotifyCompletion cb, - void *cb_cls); +GNUNET_TESTING_daemons_vary (struct GNUNET_TESTING_PeerGroup *pg, + unsigned int offset, + int desired_status, + struct GNUNET_TIME_Relative timeout, + GNUNET_TESTING_NotifyCompletion cb, + void *cb_cls); #if 0 /* keep Emacsens' auto-indent happy */