diff --git a/tools/Makefile.am b/tools/Makefile.am index 0e8ec15a404f8a7b999e8fc5a17919562967698f..c7a175f2595f069c5fd8c609fd987d4389df19a7 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -14,7 +14,7 @@ dhtscanner_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIB if ENABLE_C bin_PROGRAMS += dhtcnode -dhtcnode_CFLAGS = -isystem @top_srcdir@/c -isystem @top_srcdir@/include +dhtcnode_CFLAGS = -std=c11 -isystem @top_srcdir@/c -isystem @top_srcdir@/include dhtcnode_SOURCES = dhtcnode.c -dhtcnode_LDFLAGS = -lopendht-c -L@top_builddir@/c/.libs +dhtcnode_LDFLAGS = -lopendht-c -lreadline -L@top_builddir@/c/.libs endif diff --git a/tools/dhtcnode.c b/tools/dhtcnode.c index 21d9da86bc06bb03311c92cef58ac8bc131bf33d..bcd901621febc7f42c0469e9685643aaddb88022 100644 --- a/tools/dhtcnode.c +++ b/tools/dhtcnode.c @@ -1,14 +1,23 @@ #include <opendht_c.h> +#include <getopt.h> +#include <readline/readline.h> +#include <readline/history.h> +#include <arpa/inet.h> + #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> -#include <arpa/inet.h> +#include <stdatomic.h> struct op_context { dht_runner* runner; - int d; + atomic_bool stop; +}; +struct listen_context { + dht_runner* runner; + dht_op_token* token; }; bool dht_value_callback(const dht_value* value, bool expired, void* user_data) @@ -26,16 +35,30 @@ bool dht_get_callback(const dht_value* value, void* user_data) return true; } -void dht_done_callback(bool ok, void* user_data) +void dht_get_done_callback(bool ok, void* user_data) { dht_runner* runner = (dht_runner*)user_data; - printf("Done callback. %s\n", ok ? "Success !" : "Failure :-("); + printf("Get completed: %s\n", ok ? "success !" : "failure :-("); } -void op_context_free(void* user_data) +void dht_put_done_callback(bool ok, void* user_data) { + dht_runner* runner = (dht_runner*)user_data; + printf("Put completed: %s\n", ok ? "success !" : "failure :-("); +} + +void dht_shutdown_callback(void* user_data) +{ + printf("Stopped.\n"); struct op_context* ctx = (struct op_context*)user_data; - printf("op_context_free %d.\n", ctx->d); + atomic_store(&ctx->stop, true); +} + +void listen_context_free(void* user_data) +{ + printf("listen_context_free.\n"); + struct listen_context* ctx = (struct listen_context*)user_data; + dht_op_token_delete(ctx->token); free(ctx); } @@ -60,70 +83,152 @@ char* print_addr(const struct sockaddr* addr) { return s; } -int main() +struct dht_params { + bool help; + bool version; + bool generate_identity; + bool service; + bool peer_discovery; + bool log; + const char* bootstrap; + unsigned network; + in_port_t port; +}; + +static const struct option long_options[] = { + {"help", no_argument , NULL, 'h'}, + {"port", required_argument, NULL, 'p'}, + {"net", required_argument, NULL, 'n'}, + {"bootstrap", required_argument, NULL, 'b'}, + {"identity", no_argument , NULL, 'i'}, + {"verbose", no_argument , NULL, 'v'}, + {"service", no_argument , NULL, 's'}, + {"peer-discovery", no_argument , NULL, 'D'}, + {"no-rate-limit", no_argument , NULL, 'U'}, + {"persist", required_argument, NULL, 'f'}, + {"logfile", required_argument, NULL, 'l'}, + {"syslog", no_argument , NULL, 'L'}, + {NULL, 0 , NULL, 0} +}; + +struct dht_params +parse_args(int argc, char **argv) { + struct dht_params params; + int opt; + while ((opt = getopt_long(argc, argv, "hisvDp:n:b:f:l:", long_options, NULL)) != -1) { + switch (opt) { + case 'p': { + int port_arg = atoi(optarg); + if (port_arg >= 0 && port_arg < 0x10000) + params.port = port_arg; + } + break; + case 'D': + params.peer_discovery = true; + break; + case 'n': + params.network = strtoul(optarg, NULL, 0); + break; + case 'b': + params.bootstrap = (optarg[0] == '=') ? optarg+1 : optarg; + break; + case 'h': + params.help = true; + break; + case 'v': + params.log = true; + break; + case 'i': + params.generate_identity = true; + break; + case 's': + params.service = true; + break; + default: + break; + } + } + return params; +} + +int main(int argc, char **argv) { - dht_identity id = dht_identity_generate("testNode", NULL); - dht_infohash cert_id = dht_certificate_get_id(id.certificate); - printf("Cert ID: %s\n", dht_infohash_print(&cert_id)); - - dht_publickey* pk = dht_certificate_get_publickey(id.certificate); - dht_infohash pk_id = dht_publickey_get_id(pk); - printf("PK ID: %s\n", dht_infohash_print(&pk_id)); - dht_publickey_delete(pk); - - pk = dht_privatekey_get_publickey(id.privatekey); - pk_id = dht_publickey_get_id(pk); - printf("Key ID: %s\n", dht_infohash_print(&pk_id)); - dht_publickey_delete(pk); - dht_identity_delete(&id); - - dht_infohash h; - //dht_infohash_random(&h); - dht_infohash_get_from_string(&h, "bad_actors_test"); - printf("hash: %s\n", dht_infohash_print(&h)); - - // Put data - const char* data_str = "yo, this is some data"; - dht_value* val = dht_value_new_from_string(data_str); - - struct op_context* ctx = malloc(sizeof(struct op_context)); - ctx->runner = runner; - ctx->d = 42; + struct dht_params params = parse_args(argc, argv); dht_runner* runner = dht_runner_new(); dht_runner_config dht_config; dht_runner_config_default(&dht_config); - dht_config.peer_discovery = true; // Look for other peers on the network - dht_config.peer_publish = true; // Publish our own peer info - dht_runner_run_config(runner, 4040, &dht_config); - - - // Get data - //dht_runner_get(runner, &h, dht_get_callback, dht_done_callback, runner); - - // Listen for data - dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, op_context_free, ctx); - dht_runner_bootstrap(runner, "bootstrap.jami.net", NULL); - dht_runner_put(runner, &h, val, dht_done_callback, runner, true); - dht_runner_get(runner, &h, dht_get_callback, dht_done_callback, runner); - dht_value_unref(val); - - //sleep(1); - //sleep(20); - - struct sockaddr** addrs = dht_runner_get_public_address(runner); - for (struct sockaddr** addrIt = addrs; *addrIt; addrIt++) { - struct sockaddr* addr = *addrIt; - char* addr_str = print_addr(addr); - free(addr); - printf("Found public address: %s\n", addr_str); - free(addr_str); + dht_config.peer_discovery = params.peer_discovery; // Look for other peers on the network + dht_config.peer_publish = params.peer_discovery; // Publish our own peer info + dht_config.dht_config.node_config.network = params.network; + dht_config.log = params.log; + dht_runner_run_config(runner, params.port, &dht_config); + + if (params.bootstrap) { + printf("Bootstrap using %s\n", params.bootstrap); + dht_runner_bootstrap(runner, params.bootstrap, NULL); } - free(addrs); - - dht_runner_cancel_listen(runner, &h, token); - dht_op_token_delete(token); + char cmd[64]; + char arg[64]; + char value[256]; + while (true) { + const char* line_read = readline("> "); + if (line_read && *line_read) + add_history(line_read); + if (!line_read) + break; + if (!strcmp(line_read, "\0")) + continue; + + bzero(cmd, sizeof cmd); + bzero(arg, sizeof arg); + bzero(value, sizeof value); + sscanf(line_read, "%64s %64s %256s", cmd, arg, value); + //printf("%s -> %s\n", cmd, arg); + + if (!strcmp(cmd, "la")) { + struct sockaddr** addrs = dht_runner_get_public_address(runner); + if (addrs) { + for (struct sockaddr** addrIt = addrs; *addrIt; addrIt++) { + struct sockaddr* addr = *addrIt; + char* addr_str = print_addr(addr); + free(addr); + printf("Found public address: %s\n", addr_str); + free(addr_str); + } + free(addrs); + } + continue; + } + + dht_infohash key; + dht_infohash_from_hex(&key, arg); + if (dht_infohash_is_zero(&key)) { + dht_infohash_get_from_string(&key, arg); + printf("Using h(%s) = %s\n", arg, dht_infohash_print(&key)); + } + if (!strcmp(cmd, "g")) { + dht_runner_get(runner, &key, dht_get_callback, dht_get_done_callback, runner); + } else if (!strcmp(cmd, "l")) { + struct listen_context* ctx = malloc(sizeof(struct listen_context)); + ctx->runner = runner; + ctx->token = dht_runner_listen(runner, &key, dht_value_callback, listen_context_free, ctx); + } else if (!strcmp(cmd, "p")) { + dht_value* val = dht_value_new_from_string(value); + dht_runner_put(runner, &key, val, dht_put_done_callback, runner, true); + dht_value_unref(val); + } + } + printf("Stopping..\n"); + + struct op_context ctx; + ctx.runner = runner; + atomic_init(&ctx.stop, false); + dht_runner_shutdown(runner, dht_shutdown_callback, &ctx); + while (!atomic_load(&ctx.stop)) { + usleep(250); + } dht_runner_delete(runner); return 0; }