Port of the c-toxcore Tox library

Port of the C reference implementation of the Tox chat protocol.
Includes a native DHT bootstrap node, see run/tox_dht_bootstrap.

https://tox.chat/
This commit is contained in:
Emery Hemingway
2019-01-10 06:58:52 +01:00
committed by Norman Feske
parent a09355d77d
commit c042419226
8 changed files with 530 additions and 0 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _TOXCORE__GENODE_LOGGER_H_
#define _TOXCORE__GENODE_LOGGER_H_
/* Libc includes */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Genode includes */
#include <base/log.h>
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

View File

@@ -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)

17
lib/mk/c-toxcore.mk Normal file
View File

@@ -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

1
ports/c-toxcore.hash Normal file
View File

@@ -0,0 +1 @@
a240750d0b89cfddd31bb9f79484e93fc83561a4

13
ports/c-toxcore.port Normal file
View File

@@ -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

144
run/tox_dht_bootstrap.run Normal file
View File

@@ -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 {
<config>
<parent-provides>
<service name="CPU"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="IRQ"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
</parent-provides>
<default caps="100"/>
<default-route>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append_platform_drv_config
append_if [have_spec gpio] config "
<start name=\"[gpio_drv]\" caps=\"140\">
<resource name=\"RAM\" quantum=\"4M\"/>
<provides><service name=\"Gpio\"/></provides>
<config/>
</start>"
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="nic_drv" caps="120">
<binary name="} [nic_drv_binary] {"/>
<resource name="RAM" quantum="16M"/>
<provides> <service name="Nic"/> </provides>
} [nic_drv_config] {
</start>
<start name="report_rom">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Report"/> </provides>
<config verbose="yes"/>
</start>
<start name="tox_dht_bootstrap" caps="500">
<resource name="RAM" quantum="32M"/>
<config>
<report dht="yes"/>
<vfs>
<ram/>
<dir name="dev">
<log/>
<null/>
<inline name="rtc">2000-01-01 00:00</inline>
<inline name="random">01234567890123456789</inline>
<inline name="urandom">01234567890123456789</inline>
</dir>
<dir name="socket"> <lwip dhcp="yes"/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc" socket="/socket"/>
<bootstrap key="257744DBF57BE3E117FE05D145B5F806089428D4DCE4E3D0D50616AA16D9417E" ip="95.31.18.227"/>
<bootstrap key="3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B" ip="194.249.212.109"/>
<bootstrap key="B38255EE4B054924F6D79A5E6E5889EC94B6ADF6FE9906F97A3D01E3D083223A" ip="80.87.193.193"/>
<bootstrap key="2555763C8C460495B14157D234DD56B86300A2395554BCAE4621AC345B8C1B1B" ip="185.14.30.213" port="443"/>
<bootstrap key="02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46" ip="78.46.73.141"/>
<bootstrap key="8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832" ip="85.172.30.117"/>
<bootstrap key="1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F" ip="198.98.51.198"/>
<bootstrap key="E59A0E71ADA20D35BD1B0957059D7EF7E7792B3D680AE25C6F4DBBA09114D165" ip="37.97.185.116"/>
</config>
</start>
</config>
}
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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 <os/reporter.h>
#include <timer_session/connection.h>
#include <libc/component.h>
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<TOX_ADDRESS_SIZE*2> Key;
typedef Genode::String<TOX_MAX_HOSTNAME_LENGTH> 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<Main> _periodic_timeout {
_timer, *this, &Main::run, Genode::Microseconds(1000*1000) };
Genode::Constructible<Timer::Periodic_timeout<Main>> _report_timeout { };
Main(Libc::Env &env) : _env(env) { }
void report(Genode::Duration);
void run(Genode::Duration);
template<typename FUNC>
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);
});
}

View File

@@ -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