diff --git a/testing/Makefile.inc b/testing/Makefile.inc index ee68e289..65f9f64c 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc @@ -23,7 +23,8 @@ noinst_PROGRAMS += DHT_test \ Lossless_UDP_testclient \ Lossless_UDP_testserver \ Messenger_test \ - crypto_speed_test + crypto_speed_test \ + tox_sync DHT_test_SOURCES = ../testing/DHT_test.c @@ -99,4 +100,19 @@ crypto_speed_test_LDADD = \ $(NACL_LIBS) \ $(WINSOCK2_LIBS) +tox_sync_SOURCES = \ + ../testing/tox_sync.c + +tox_sync_CFLAGS = \ + $(LIBSODIUM_CFLAGS) \ + $(NACL_CFLAGS) + +tox_sync_LDADD = \ + $(LIBSODIUM_LDFLAGS) \ + $(NACL_LDFLAGS) \ + libtoxcore.la \ + $(LIBSODIUM_LIBS) \ + $(NACL_LIBS) \ + $(WINSOCK2_LIBS) + EXTRA_DIST += $(top_srcdir)/testing/misc_tools.c diff --git a/testing/tox_sync.c b/testing/tox_sync.c new file mode 100644 index 00000000..486e4b3a --- /dev/null +++ b/testing/tox_sync.c @@ -0,0 +1,291 @@ +/* Tox Sync + * + * Proof of concept bittorrent sync like software using tox, syncs two directories. + * + * Command line arguments are the ip, port and public_key of a node (for bootstrapping) and the folder to sync. + * + * EX: ./test 127.0.0.1 33445 CDCFD319CE3460824B33BE58FD86B8941C9585181D8FBD7C79C5721D7C2E9F7C ./sync_folder/ + * + * NOTE: for security purposes, both tox sync instances must manually add each other as friend for it to work. + * + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * 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 . + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../toxcore/tox.h" +#include "misc_tools.c" + +#include +#define c_sleep(x) usleep(1000*x) + +#include +#include + +#define NUM_FILE_SENDERS 256 +typedef struct { + FILE *file; + uint16_t friendnum; + uint8_t filenumber; + uint8_t nextpiece[1024]; + uint16_t piecelength; +} File_t; +File_t file_senders[NUM_FILE_SENDERS]; +File_t file_recv[NUM_FILE_SENDERS]; +uint8_t numfilesenders; + +void send_filesenders(Tox *m) +{ + uint32_t i; + + for (i = 0; i < NUM_FILE_SENDERS; ++i) { + if (file_senders[i].file == 0) + continue; + + while (1) { + if (!tox_file_senddata(m, file_senders[i].friendnum, file_senders[i].filenumber, file_senders[i].nextpiece, + file_senders[i].piecelength)) + break; + + file_senders[i].piecelength = fread(file_senders[i].nextpiece, 1, 1000, file_senders[i].file); + + if (file_senders[i].piecelength == 0) { + fclose(file_senders[i].file); + file_senders[i].file = 0; + + printf("[t] %u file transfer: %u completed %i\n", file_senders[i].friendnum, file_senders[i].filenumber, + tox_file_sendcontrol(m, file_senders[i].friendnum, 0, file_senders[i].filenumber, TOX_FILECONTROL_FINISHED, 0, 0)); + break; + } + } + } +} +int add_filesender(Tox *m, uint16_t friendnum, char *filename) +{ + FILE *tempfile = fopen(filename, "rb"); + + if (tempfile == 0) + return -1; + + fseek(tempfile, 0, SEEK_END); + uint64_t filesize = ftell(tempfile); + fseek(tempfile, 0, SEEK_SET); + int filenum = tox_new_filesender(m, friendnum, filesize, (uint8_t *)filename, strlen(filename) + 1); + + if (filenum == -1) + return -1; + + file_senders[numfilesenders].file = tempfile; + file_senders[numfilesenders].piecelength = fread(file_senders[numfilesenders].nextpiece, 1, 1000, + file_senders[numfilesenders].file); + file_senders[numfilesenders].friendnum = friendnum; + file_senders[numfilesenders].filenumber = filenum; + ++numfilesenders; + return filenum; +} + +void kill_filesender(Tox *m, uint8_t filenum) +{ + uint32_t i; + + for (i = 0; i < NUM_FILE_SENDERS; ++i) + if (file_senders[i].file != 0 && file_senders[i].filenumber == filenum) { + fclose(file_senders[i].file); + file_senders[i].file = 0; + } +} +int not_sending() +{ + uint32_t i; + + for (i = 0; i < NUM_FILE_SENDERS; ++i) + if (file_senders[i].file != 0) + return 0; + + return 1; +} + +static char path[1024]; + +void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, + uint16_t filename_length, void *userdata) +{ + char fullpath[1024]; + uint32_t i; + uint16_t rm = 0; + + for (i = 0; i < strlen((char *)filename); ++i) { + if (filename[i] == '/') + rm = i; + } + + if (path[strlen(path) - 1] == '/') + sprintf(fullpath, "%s%s", path, filename + rm + 1); + else + sprintf(fullpath, "%s/%s", path, filename + rm + 1); + + FILE *tempfile = fopen(fullpath, "rb"); + + if (tempfile != 0) { + fclose(tempfile); + tox_file_sendcontrol(m, friendnumber, 1, filenumber, TOX_FILECONTROL_KILL, 0, 0); + return; + } + + file_recv[filenumber].file = fopen(fullpath, "wb"); + + if (file_recv[filenumber].file == 0) { + tox_file_sendcontrol(m, friendnumber, 1, filenumber, TOX_FILECONTROL_KILL, 0, 0); + return; + } + + if (tox_file_sendcontrol(m, friendnumber, 1, filenumber, TOX_FILECONTROL_ACCEPT, 0, 0)) { + printf("Accepted file transfer. (file: %s)\n", fullpath); + } + +} + +void file_print_control(Tox *m, int friendnumber, uint8_t recieve_send, uint8_t filenumber, uint8_t control_type, + uint8_t *data, + uint16_t length, void *userdata) +{ + if (recieve_send == 1 && (control_type == TOX_FILECONTROL_KILL || control_type == TOX_FILECONTROL_FINISHED)) { + kill_filesender(m, filenumber); + return; + } + + if (recieve_send == 0 && (control_type == TOX_FILECONTROL_KILL || control_type == TOX_FILECONTROL_FINISHED)) { + fclose(file_recv[filenumber].file); + printf("File closed\n"); + file_recv[filenumber].file = 0; + return; + } +} + +void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) +{ + if (file_recv[filenumber].file != 0) + fwrite(data, length, 1, file_recv[filenumber].file); +} + +void print_online(Tox *tox, int friendnumber, uint8_t status, void *userdata) +{ + if (status == 1) + printf("\nOther went online.\n"); + else + printf("\nOther went offline.\n"); +} + +int main(int argc, char *argv[]) +{ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ + int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); + + if (argvoffset < 0) + exit(1); + + /* with optional --ipvx, now it can be 1-4 arguments... */ + if ((argc != argvoffset + 3) && (argc != argvoffset + 5)) { + printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node) folder (to sync)\n", argv[0]); + exit(0); + } + + Tox *tox = tox_new(ipv6enabled); + tox_callback_file_data(tox, write_file, NULL); + tox_callback_file_control(tox, file_print_control, NULL); + tox_callback_file_sendrequest(tox, file_request_accept, NULL); + tox_callback_connectionstatus(tox, print_online, NULL); + + uint16_t port = htons(atoi(argv[argvoffset + 2])); + unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]); + int res = tox_bootstrap_from_address(tox, argv[argvoffset + 1], ipv6enabled, port, binary_string); + + if (!res) { + printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); + exit(1); + } + + uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; + tox_getaddress(tox, address); + uint32_t i; + + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { + printf("%02X", address[i]); + } + + char temp_id[128]; + printf("\nEnter the address of the other id you want to sync with (38 bytes HEX format):\n"); + + if (scanf("%s", temp_id) != 1) { + return 1; + } + + int num = tox_addfriend(tox, hex_string_to_bin(temp_id), (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); + + if (num < 0) { + printf("\nSomething went wrong when adding friend.\n"); + return 1; + } + + memcpy(path, argv[argvoffset + 4], strlen(argv[argvoffset + 4])); + DIR *d; + struct dirent *dir; + uint8_t notconnected = 1; + + while (1) { + if (tox_isconnected(tox) && notconnected) { + printf("\nDHT connected.\n"); + notconnected = 0; + } + + if (not_sending() && tox_get_friend_connectionstatus(tox, num)) { + d = opendir(path); + + if (d) { + while ((dir = readdir(d)) != NULL) { + if (dir->d_type == DT_REG) { + char fullpath[1024]; + + if (path[strlen(path) - 1] == '/') + sprintf(fullpath, "%s%s", path, dir->d_name); + else + sprintf(fullpath, "%s/%s", path, dir->d_name); + + add_filesender(tox, num, fullpath); + } + } + + closedir(d); + + } else { + printf("\nFailed to open directory.\n"); + return 1; + } + } + + send_filesenders(tox); + tox_do(tox); + c_sleep(1); + } + + return 0; +}