Skip to content

Instantly share code, notes, and snippets.

@zoff99
Created May 8, 2022 11:52
Show Gist options
  • Save zoff99/584e5145453281d4f3f2e05afb186969 to your computer and use it in GitHub Desktop.
Save zoff99/584e5145453281d4f3f2e05afb186969 to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <linux/sched.h>
#include <tox/tox.h>
#define CURRENT_LOG_LEVEL 9 // 0 -> error, 1 -> warn, 2 -> info, 9 -> debug
const char *log_filename = "output.log";
FILE *logfile = NULL;
int f_online[3] = { 0, 0, 0};
struct Node1 {
char *ip;
char *key;
uint16_t udp_port;
uint16_t tcp_port;
} nodes1[] = {
{ "tox.plastiras.org", "8E8B63299B3D520FB377FE5100E65E3322F7AE5B20A0ACED2981769FC5B43725", 33445, 443 },
{ NULL, NULL, 0, 0 }
};
struct Node2 {
char *ip;
char *key;
uint16_t udp_port;
uint16_t tcp_port;
} nodes2[] = {
{ "tox.verdict.gg", "1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976", 33445, 33445 },
{ NULL, NULL, 0, 0 }
};
void dbg(int level, const char *fmt, ...)
{
char *level_and_format = NULL;
char *fmt_copy = NULL;
if (fmt == NULL)
{
return;
}
if (strlen(fmt) < 1)
{
return;
}
if (!logfile)
{
return;
}
if ((level < 0) || (level > 9))
{
level = 0;
}
level_and_format = calloc(1, strlen(fmt) + 3 + 1);
if (!level_and_format)
{
// dbg(9, stderr, "free:000a\n");
return;
}
fmt_copy = level_and_format + 2;
strcpy(fmt_copy, fmt);
level_and_format[1] = ':';
if (level == 0)
{
level_and_format[0] = 'E';
}
else if (level == 1)
{
level_and_format[0] = 'W';
}
else if (level == 2)
{
level_and_format[0] = 'I';
}
else
{
level_and_format[0] = 'D';
}
level_and_format[(strlen(fmt) + 2)] = '\0'; // '\0' or '\n'
level_and_format[(strlen(fmt) + 3)] = '\0';
struct timeval tv;
gettimeofday(&tv, NULL);
time_t t3 = time(NULL);
struct tm tm3 = *localtime(&t3);
char *level_and_format_2 = calloc(1, strlen(level_and_format) + 5 + 3 + 3 + 1 + 3 + 3 + 3 + 7 + 1);
level_and_format_2[0] = '\0';
snprintf(level_and_format_2, (strlen(level_and_format) + 5 + 3 + 3 + 1 + 3 + 3 + 3 + 7 + 1),
"%04d-%02d-%02d %02d:%02d:%02d.%06ld:%s",
tm3.tm_year + 1900, tm3.tm_mon + 1, tm3.tm_mday,
tm3.tm_hour, tm3.tm_min, tm3.tm_sec, tv.tv_usec, level_and_format);
if (level <= CURRENT_LOG_LEVEL)
{
va_list ap;
va_start(ap, fmt);
vfprintf(logfile, level_and_format_2, ap);
va_end(ap);
}
// dbg(9, "free:001\n");
if (level_and_format)
{
// dbg(9, "free:001.a\n");
free(level_and_format);
}
if (level_and_format_2)
{
free(level_and_format_2);
}
// dbg(9, "free:002\n");
}
void tox_log_cb__custom1(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data)
{
dbg(9, "C-TOXCORE:1:%d:%s:%d:%s:%s\n", (int)level, file, (int)line, func, message);
}
void tox_log_cb__custom2(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data)
{
dbg(9, "C-TOXCORE:2:%d:%s:%d:%s:%s\n", (int)level, file, (int)line, func, message);
}
static void hex_string_to_bin(const char *hex_string, uint8_t *output) {
size_t len = strlen(hex_string) / 2;
size_t i = len;
if (!output) {
return;
}
const char *pos = hex_string;
for (i = 0; i < len; ++i, pos += 2) {
sscanf(pos, "%2hhx", &output[i]);
}
}
static Tox* tox_init(int num)
{
Tox *tox = NULL;
struct Tox_Options options;
tox_options_default(&options);
// ----- set options ------
options.ipv6_enabled = false;
options.local_discovery_enabled = false;
options.hole_punching_enabled = true;
options.udp_enabled = false;
options.tcp_port = 0; // disable tcp relay function!
// ----- set options ------
if (num == 1)
{
options.log_callback = tox_log_cb__custom1;
}
else
{
options.log_callback = tox_log_cb__custom2;
}
tox = tox_new(&options, NULL);
return tox;
}
static bool tox_connect(Tox *tox, int num) {
dbg(9, "[%d]:bootstrapping ...\n", num);
if (num == 1)
{
for (int i = 0; nodes1[i].ip; i++) {
uint8_t *key = (uint8_t *)calloc(1, 100);
hex_string_to_bin(nodes1[i].key, key);
if (!key) {
return false; // Return because it will most likely fail again
}
tox_bootstrap(tox, nodes1[i].ip, nodes1[i].udp_port, key, NULL);
if (nodes1[i].tcp_port != 0) {
tox_add_tcp_relay(tox, nodes1[i].ip, nodes1[i].tcp_port, key, NULL);
}
free(key);
}
}
else
{
for (int i = 0; nodes2[i].ip; i++) {
uint8_t *key = (uint8_t *)calloc(1, 100);
hex_string_to_bin(nodes2[i].key, key);
if (!key) {
return false; // Return because it will most likely fail again
}
tox_bootstrap(tox, nodes2[i].ip, nodes2[i].udp_port, key, NULL);
if (nodes2[i].tcp_port != 0) {
tox_add_tcp_relay(tox, nodes2[i].ip, nodes2[i].tcp_port, key, NULL);
}
free(key);
}
}
dbg(9, "[%d]:bootstrapping done.\n", num);
return true;
}
static void to_hex(char *out, uint8_t *in, int size) {
while (size--) {
if (*in >> 4 < 0xA) {
*out++ = '0' + (*in >> 4);
} else {
*out++ = 'A' + (*in >> 4) - 0xA;
}
if ((*in & 0xf) < 0xA) {
*out++ = '0' + (*in & 0xF);
} else {
*out++ = 'A' + (*in & 0xF) - 0xA;
}
in++;
}
}
static void self_connection_change_callback(Tox *tox, TOX_CONNECTION status, void *userdata) {
tox;
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
switch (status) {
case TOX_CONNECTION_NONE:
dbg(9, "[%d]:Lost connection to the Tox network.\n", num);
break;
case TOX_CONNECTION_TCP:
dbg(9, "[%d]:Connected using TCP.\n", num);
break;
case TOX_CONNECTION_UDP:
dbg(9, "[%d]:Connected using UDP.\n", num);
break;
}
}
static void friend_connection_status_callback(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
void *userdata)
{
tox;
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
switch (connection_status) {
case TOX_CONNECTION_NONE:
dbg(9, "[%d]:Lost connection to friend %d\n", num, friend_number);
f_online[num] = 0;
break;
case TOX_CONNECTION_TCP:
dbg(9, "[%d]:Connected to friend %d using TCP\n", num, friend_number);
f_online[num] = 1;
break;
case TOX_CONNECTION_UDP:
dbg(9, "[%d]:Connected to friend %d using UDP\n", num, friend_number);
f_online[num] = 2;
break;
}
}
static void friend_request_callback(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
void *userdata) {
tox;
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
TOX_ERR_FRIEND_ADD err;
tox_friend_add_norequest(tox, public_key, &err);
dbg(9, "[%d]:accepting friend request. res=%d\n", num, err);
}
static void group_invite_cb(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
const uint8_t *group_name, size_t group_name_length, void *userdata)
{
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
Tox_Err_Group_Invite_Accept error;
tox_group_invite_accept(tox, friend_number, invite_data, length,
(const uint8_t *)"tt", 2, NULL, 0,
&error);
dbg(9, "[%d]:tox_group_invite_accept:%d\n", num, error);
}
static void group_peer_join_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, void *userdata)
{
tox;
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
dbg(9, "[%d]:Peer %d joined group %d\n", num, peer_id, group_number);
}
static void group_self_join_cb(Tox *tox, uint32_t group_number, void *userdata)
{
tox;
uint8_t* unum = (uint8_t *)userdata;
uint8_t num = *unum;
dbg(9, "[%d]:You joined group %d\n", num, group_number);
}
int main(int argc, char *argv[])
{
logfile = stdout;
// logfile = fopen(log_filename, "wb");
setvbuf(logfile, NULL, _IOLBF, 0);
dbg(9, "--start--\n");
uint8_t num1 = 1;
uint8_t num2 = 2;
f_online[1] = 0;
f_online[2] = 0;
Tox *tox1 = tox_init(1);
Tox *tox2 = tox_init(2);
uint8_t public_key_bin1[TOX_ADDRESS_SIZE];
char public_key_str1[TOX_ADDRESS_SIZE * 2];
tox_self_get_address(tox1, public_key_bin1);
to_hex(public_key_str1, public_key_bin1, TOX_ADDRESS_SIZE);
dbg(9, "[%d]:ID:1: %.*s\n", 1, TOX_ADDRESS_SIZE * 2, public_key_str1);
uint8_t public_key_bin2[TOX_ADDRESS_SIZE];
char public_key_str2[TOX_ADDRESS_SIZE * 2];
tox_self_get_address(tox2, public_key_bin2);
to_hex(public_key_str2, public_key_bin2, TOX_ADDRESS_SIZE);
dbg(9, "[%d]:ID:2: %.*s\n", 2, TOX_ADDRESS_SIZE * 2, public_key_str2);
tox_connect(tox1, 1);
tox_connect(tox2, 2);
tox_iterate(tox1, (void *)&num1);
tox_iterate(tox2, (void *)&num2);
Tox_Err_Friend_Add err1;
tox_friend_add(tox1, public_key_bin2, "1", 1, &err1);
dbg(9, "[%d]:add friend res=%d\n", 1, err1);
// Tox_Err_Friend_Add err2;
// tox_friend_add(tox2, public_key_bin1, "2", 1, &err2);
// dbg(9, "[%d]:add friend res=%d\n", 2, err2);
tox_callback_self_connection_status(tox1, self_connection_change_callback);
tox_callback_friend_connection_status(tox1, friend_connection_status_callback);
tox_callback_friend_request(tox1, friend_request_callback);
tox_callback_group_invite(tox1, group_invite_cb);
tox_callback_group_peer_join(tox1, group_peer_join_cb);
tox_callback_group_self_join(tox1, group_self_join_cb);
/*
tox_callback_friend_message(tox1, friend_message_callback);
tox_callback_group_message(tox1, group_message_callback);
tox_callback_group_peer_exit(tox1, group_peer_exit_cb);
tox_callback_group_join_fail(tox1, group_join_fail_cb);
*/
tox_callback_self_connection_status(tox2, self_connection_change_callback);
tox_callback_friend_connection_status(tox2, friend_connection_status_callback);
tox_callback_friend_request(tox2, friend_request_callback);
tox_callback_group_invite(tox2, group_invite_cb);
tox_callback_group_peer_join(tox2, group_peer_join_cb);
tox_callback_group_self_join(tox2, group_self_join_cb);
/*
tox_callback_friend_message(tox2, friend_message_callback);
tox_callback_group_message(tox2, group_message_callback);
tox_callback_group_peer_exit(tox2, group_peer_exit_cb);
tox_callback_group_join_fail(tox2, group_join_fail_cb);
*/
while (1 == 1) {
tox_iterate(tox1, (void *)&num1);
usleep(tox_iteration_interval(tox1));
tox_iterate(tox2, (void *)&num2);
usleep(tox_iteration_interval(tox2));
if ((f_online[1] > 0) && (f_online[2] > 0))
{
break;
}
}
dbg(9, "[%d]:friends online\n", 0);
// tox1 creates a new private group
Tox_Err_Group_New err_g1;
tox_group_new(tox1, TOX_GROUP_PRIVACY_STATE_PRIVATE, (const uint8_t *)"g1", 2, (const uint8_t *)"peer1", 4, &err_g1);
dbg(9, "[%d]:created group res=%d\n", 1, err_g1);
for (int i=0;i<100;i++) {
tox_iterate(tox1, (void *)&num1);
usleep(tox_iteration_interval(tox1));
tox_iterate(tox2, (void *)&num2);
usleep(tox_iteration_interval(tox2));
}
// tox1 invites tox2 to the new private group
Tox_Err_Group_Invite_Friend err_g2;
tox_group_invite_friend(tox1, 0, 0, &err_g2);
dbg(9, "[%d]:invited friend to group res=%d\n", 1, err_g1);
while (1 == 1) {
tox_iterate(tox1, (void *)&num1);
usleep(tox_iteration_interval(tox1));
tox_iterate(tox2, (void *)&num2);
usleep(tox_iteration_interval(tox2));
}
fclose(logfile);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment