diff --git a/include/toxcore/toxcore/genode_logger.h b/include/toxcore/toxcore/genode_logger.h new file mode 100644 index 0000000..690f722 --- /dev/null +++ b/include/toxcore/toxcore/genode_logger.h @@ -0,0 +1,72 @@ +/* + * Text logging abstraction. + */ + +/* + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox 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 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + */ + +#ifndef _TOXCORE__GENODE_LOGGER_H_ +#define _TOXCORE__GENODE_LOGGER_H_ + + +/* Libc includes */ +#include +#include +#include +#include + +/* Genode includes */ +#include + + +namespace Toxcore { + +/* Toxcore includes */ +extern "C" { +#include "toxcore/logger.h" +} + + static void logger_genode_handler(void *context, Logger_Level level, + const char *file, int line, const char *func, + const char *message, void *userdata) + { + (void)context; + (void)userdata; + + switch (level) { + case LOGGER_LEVEL_ERROR: + Genode::error(file, ":", line, "(", func, "): ", message);\ + break; + case LOGGER_LEVEL_WARNING: + Genode::warning(file, ":", line, "(", func, "): ", message); + break; + default: + Genode::log(file, ":", line, "(", func, "): ", message); + break; + } + } + + Logger *new_genode_logger() + { + Logger *l = logger_new(); + logger_callback_log(l, logger_genode_handler, nullptr, nullptr); + return l; + } + +} + +#endif diff --git a/lib/import/import-c-toxcore.mk b/lib/import/import-c-toxcore.mk new file mode 100644 index 0000000..3af463d --- /dev/null +++ b/lib/import/import-c-toxcore.mk @@ -0,0 +1,4 @@ +TOXCORE_PORT_DIR := $(call select_from_ports,c-toxcore) + +INC_DIR += $(TOXCORE_PORT_DIR)/include +INC_DIR += $(call select_from_repositories,include/toxcore) diff --git a/lib/mk/c-toxcore.mk b/lib/mk/c-toxcore.mk new file mode 100644 index 0000000..6d33d3f --- /dev/null +++ b/lib/mk/c-toxcore.mk @@ -0,0 +1,17 @@ +include $(REP_DIR)/lib/import/import-c-toxcore.mk + +TOXCORE_SRC_DIR = $(TOXCORE_PORT_DIR)/src/lib/c-toxcore + +CC_C_OPT += -std=c99 -D_XOPEN_SOURCE + +INC_DIR += $(TOXCORE_SRC_DIR)/toxcore + +TOXCORE_SRC_C := $(notdir $(wildcard $(TOXCORE_SRC_DIR)/toxcore/*.c)) + +SRC_C += $(filter-out $(TOXCORE_SRC_FILTER),$(TOXCORE_SRC_C)) + +LIBS := libsodium libc + +vpath %.c $(TOXCORE_SRC_DIR)/toxcore + +SHARED_LIB = yes diff --git a/ports/c-toxcore.hash b/ports/c-toxcore.hash new file mode 100644 index 0000000..04b931d --- /dev/null +++ b/ports/c-toxcore.hash @@ -0,0 +1 @@ +a240750d0b89cfddd31bb9f79484e93fc83561a4 diff --git a/ports/c-toxcore.port b/ports/c-toxcore.port new file mode 100644 index 0000000..2b59db2 --- /dev/null +++ b/ports/c-toxcore.port @@ -0,0 +1,13 @@ +LICENSE := GPLv3 +VERSION := 0.2.8 +DOWNLOADS := c-toxcore.archive + +OWNER := TokTok +REPO := c-toxcore +REV := 3f35a84968f100e1e6d3c9df467fd3c82a9ebb13 +URL(c-toxcore) := https://github.com/$(OWNER)/$(REPO)/archive/$(REV).tar.gz +SHA(c-toxcore) := ff67bf686f5322c3b5a08d0562d5e6fd20e26cf9f4aebba78b948c8f365dae8e +DIR(c-toxcore) := src/lib/c-toxcore + +DIRS := include/toxcore +DIR_CONTENT(include/toxcore) = src/lib/c-toxcore/toxcore/*.h diff --git a/run/tox_dht_bootstrap.run b/run/tox_dht_bootstrap.run new file mode 100644 index 0000000..f9cccdb --- /dev/null +++ b/run/tox_dht_bootstrap.run @@ -0,0 +1,144 @@ +# +# \brief Test of Tox DHT bootstrap daemon +# \author Emery Hemingway +# + +if {[have_spec odroid_xu] || [have_spec linux] || + [expr [have_spec imx53] && [have_spec trustzone]]} { + puts "Run script does not support this platform." + exit 0 +} + +set build_components { + app/tox_dht_bootstrap + drivers/nic + lib/vfs/import + lib/vfs/lwip + server/report_rom +} + +proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv } + if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv } + return gpio_drv } + +lappend_if [have_spec gpio] build_components drivers/gpio + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +lappend_if [expr {[nic_drv_binary] == "nic_drv"}] build_components drivers/nic +lappend_if [expr {[nic_drv_binary] == "usb_drv"}] build_components drivers/usb + +build $build_components + +create_boot_directory + +import_from_depot \ + genodelabs/src/[base_src] \ + genodelabs/src/init \ + +append config { + + + + + + + + + + + + + + + + + } + +append_platform_drv_config + +append_if [have_spec gpio] config " + + + + + " + +append config { + + + + + + + + + } [nic_drv_config] { + + + + + + + + + + + + + + + + + + 2000-01-01 00:00 + 01234567890123456789 + 01234567890123456789 + + + + + + + + + + + + + + + +} + +install_config $config + +# generic modules +set boot_modules { + libc.lib.so + libm.lib.so + libsodium.lib.so + posix.lib.so + c-toxcore.lib.so + tox_dht_bootstrap + vfs.lib.so + vfs_lwip.lib.so + report_rom +} + +# platform-specific modules +append_platform_drv_boot_modules + +lappend boot_modules [nic_drv_binary] + +lappend_if [have_spec gpio] boot_modules [gpio_drv] + +build_boot_image $boot_modules + +append_if [have_spec x86] qemu_args " -net nic,model=e1000 " +append_if [have_spec lan9118] qemu_args " -net nic,model=lan9118 " +append qemu_args " -net user -net dump,file=[run_dir].pcap" +append qemu_args " -nographic" + +run_genode_until forever diff --git a/src/app/tox_dht_bootstrap/component.cc b/src/app/tox_dht_bootstrap/component.cc new file mode 100644 index 0000000..cbffbb6 --- /dev/null +++ b/src/app/tox_dht_bootstrap/component.cc @@ -0,0 +1,272 @@ +/* + * A simple DHT boostrap node for tox. + */ + +/* + * Copyright © 2018 Genode Labs GmbH + * + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox 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 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + */ + +extern "C" { +#include "toxcore/tox.h" +#include "toxcore/DHT.h" +#include "toxcore/LAN_discovery.h" +#include "toxcore/friend_requests.h" +#include "toxcore/logger.h" +#include "toxcore/mono_time.h" +#include "toxcore/tox.h" +#include "toxcore/util.h" +} +#include "toxcore/genode_logger.h" + +/* Genode includes */ +#include +#include +#include + + +namespace Tox_dht_bootstrap { + +struct Main; + +enum { + IPV6_ENABLE = false, + PORT = 33445 +}; + + +typedef Genode::String<65> Key_string; + + +static bool non_zero(Client_data const &peer) +{ + for (int i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) + if (peer.public_key[i]) return true; + return false; +} + + +static Key_string encode_key(uint8_t const *bin) +{ + static const char alphabet[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + }; + + char buf[CRYPTO_PUBLIC_KEY_SIZE*2]; + for (int i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) { + buf[(i<<1)] = alphabet[bin[i]>>4]; + buf[(i<<1)|1] = alphabet[bin[i]&0xf]; + } + + return Key_string(Genode::Cstring(buf, CRYPTO_PUBLIC_KEY_SIZE*2)); +} + +static uint8_t *hex_string_to_bin(const char *hex_string) +{ + if (strlen(hex_string) % 2 != 0) { + return nullptr; + } + + size_t len = strlen(hex_string) / 2; + uint8_t *ret = (uint8_t *)malloc(len); + + const char *pos = hex_string; + size_t i; + + for (i = 0; i < len; ++i, pos += 2) { + unsigned int val; + sscanf(pos, "%02x", &val); + ret[i] = val; + } + + return ret; +} + + +void bootstrap_from_config(DHT *dht, Genode::Xml_node const &config) +{ + typedef Genode::String Key; + typedef Genode::String Host; + + auto const bs_fn = [&] (Genode::Xml_node const &node) { + Key key; + Host host; + uint16_t port = PORT; + + try { + node.attribute("ip").value(&host); + node.attribute("key").value(&key); + port = node.attribute_value("port", port); + } + catch (...) { + Genode::error("Invalid bootstrap node ", node); + return; + } + + uint8_t *bootstrap_key = hex_string_to_bin(key.string()); + int res = dht_bootstrap_from_address( + dht, host.string(), IPV6_ENABLE, net_htons(port), bootstrap_key); + free(bootstrap_key); + if (!res) + Genode::error("Failed to connect to ", node); + }; + + config.for_each_sub_node("bootstrap", bs_fn); +} + +} + + +struct Tox_dht_bootstrap::Main +{ + Main(const Main&); + Main &operator=(const Main&); + + Libc::Env &_env; + + Timer::Connection _timer { _env, "periodic-timeout" }; + + Genode::Expanding_reporter _reporter { _env, "dht_state", "dht_state" }; + + Logger *logger = Toxcore::new_genode_logger(); + + Mono_Time *_mono_time = mono_time_new(); + + uint64_t last_LANdiscovery = 0; + + int is_waiting_for_dht_connection = 1; + + DHT *init_dht() + { + /* Initialize networking - + Bind to ip 0.0.0.0 / [::] : PORT */ + IP ip; + ip_init(&ip, IPV6_ENABLE); + + DHT *dht = new_dht(logger, _mono_time, new_networking(logger, ip, PORT), true); + Onion *onion = new_onion(_mono_time, dht); + Onion_Announce *onion_a = new_onion_announce(_mono_time, dht); + + if (!(onion && onion_a)) { + Genode::error("Something failed to initialize"); + exit(1); + } + + Genode::log("Listening on UDP port ", net_ntohs(net_port(dht_get_net(dht)))); + + _env.config([&] (Genode::Xml_node const &config) { + bootstrap_from_config(dht, config); }); + + lan_discovery_init(dht); + + _env.config([&] (Genode::Xml_node const &config) { + config.for_each_sub_node("report", [&] (Genode::Xml_node const &node) { + if (node.attribute_value("dht", false)) { + _report_timeout.construct(_timer, *this, &Main::report, Genode::Microseconds(4*1000*1000)); + } + }); + }); + + return dht; + } + + DHT *_dht = init_dht(); + + Timer::Periodic_timeout
_periodic_timeout { + _timer, *this, &Main::run, Genode::Microseconds(1000*1000) }; + + Genode::Constructible> _report_timeout { }; + + Main(Libc::Env &env) : _env(env) { } + + + void report(Genode::Duration); + void run(Genode::Duration); + + template + void for_each_close_peer(FUNC const &func) + { + for (uint32_t i = 0; i < LCLIENT_LIST; i += LCLIENT_NODES) { + for (uint32_t j = 0; j < LCLIENT_NODES; ++j) { + Client_data const *peer = dht_get_close_client(_dht, i+j); + if (!non_zero(*peer)) break; + func((Client_data const &)*peer); + } + } + } +}; + + +void Tox_dht_bootstrap::Main::report(Genode::Duration) +{ + mono_time_update(_mono_time); + + Libc::with_libc([&] () { + _reporter.generate([&] (Genode::Xml_generator &gen) { + uint64_t now = mono_time_get(_mono_time); + gen.attribute("timestamp", now); + gen.node("base", [&] () { + gen.attribute("public", encode_key(dht_get_self_public_key(_dht))); + //gen.attribute("secret", encode_key(dht_get_self_secret_key(_dht))); + }); + + for_each_close_peer([&] (Client_data const &peer) { + gen.node("close", [&] () { + gen.attribute("public", encode_key(peer.public_key)); + + char ip_buf[IP_NTOA_LEN]; + ip_ntoa(&peer.assoc4.ip_port.ip, ip_buf, sizeof(ip_buf)); + gen.attribute("ip", (char const *)ip_buf); + gen.attribute("port", peer.assoc4.ip_port.port); + gen.attribute("timestamp", now - peer.assoc4.timestamp); + gen.attribute("last_pinged", now - peer.assoc4.last_pinged); + }); + }); + }); + }); +} + + +void Tox_dht_bootstrap::Main::run(Genode::Duration) +{ + Libc::with_libc([&] () { + mono_time_update(_mono_time); + + if (is_waiting_for_dht_connection && dht_isconnected(_dht)) { + Genode::log("Connected to other bootstrap node successfully.\n"); + is_waiting_for_dht_connection = 0; + } + + do_dht(_dht); + + if (mono_time_is_timeout(_mono_time, last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { + lan_discovery_send(net_htons(PORT), _dht); + last_LANdiscovery = mono_time_get(_mono_time); + } + + networking_poll(dht_get_net(_dht), nullptr); + }); +} + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] () { + static Tox_dht_bootstrap::Main inst(env); + }); +} diff --git a/src/app/tox_dht_bootstrap/target.mk b/src/app/tox_dht_bootstrap/target.mk new file mode 100644 index 0000000..6b45b60 --- /dev/null +++ b/src/app/tox_dht_bootstrap/target.mk @@ -0,0 +1,7 @@ +TARGET = tox_dht_bootstrap +LIBS += c-toxcore libc +SRC_CC += component.cc + +TOX_PORT := $(call select_from_ports,c-toxcore) + +INC_DIR += $(TOX_PORT)/src/lib/toxcore/other