mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge remote-tracking branch 'upstream/master' into wait: replace void *tox with Tox *tox in tox.c (which now includes the declarations from tox.h)
This commit is contained in:
commit
40e020b958
|
@ -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
|
||||
|
|
127
testing/nTox.c
127
testing/nTox.c
|
@ -67,6 +67,68 @@ typedef struct {
|
|||
Friend_request pending_requests[256];
|
||||
uint8_t num_requests = 0;
|
||||
|
||||
#define NUM_FILE_SENDERS 256
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
uint16_t friendnum;
|
||||
uint8_t filenumber;
|
||||
uint8_t nextpiece[1024];
|
||||
uint16_t piecelength;
|
||||
} File_Sender;
|
||||
File_Sender file_senders[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;
|
||||
tox_file_sendcontrol(m, file_senders[i].friendnum, 0, file_senders[i].filenumber, 3, 0, 0);
|
||||
char msg[512];
|
||||
sprintf(msg, "[t] %u file transfer: %u completed", file_senders[i].friendnum, file_senders[i].filenumber);
|
||||
new_lines(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int add_filesender(Tox *m, uint16_t friendnum, char *filename)
|
||||
{
|
||||
FILE *tempfile = fopen(filename, "r");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
resolve_addr():
|
||||
address should represent IPv4 or a hostname with A record
|
||||
|
@ -366,6 +428,16 @@ void line_eval(Tox *m, char *line)
|
|||
tox_group_message_send(m, groupnumber, (uint8_t *)*posi + 1, strlen(*posi + 1) + 1));
|
||||
new_lines(msg);
|
||||
}
|
||||
} else if (inpt_command == 't') {
|
||||
char msg[512];
|
||||
char *posi[1];
|
||||
int friendnum = strtoul(line + prompt_offset, posi, 0);
|
||||
|
||||
if (**posi != 0) {
|
||||
sprintf(msg, "[t] Sending file %s to friendnum %u filenumber is %i (-1 means failure)", *posi + 1, friendnum,
|
||||
add_filesender(m, friendnum, *posi + 1));
|
||||
new_lines(msg);
|
||||
}
|
||||
} else if (inpt_command == 'q') { //exit
|
||||
save_data(m);
|
||||
endwin();
|
||||
|
@ -586,6 +658,55 @@ void print_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *messag
|
|||
new_lines(msg);
|
||||
}
|
||||
|
||||
void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename,
|
||||
uint16_t filename_length, void *userdata)
|
||||
{
|
||||
char msg[512];
|
||||
sprintf(msg, "[t] %u is sending us: %s of size %llu", friendnumber, filename, (long long unsigned int)filesize);
|
||||
new_lines(msg);
|
||||
|
||||
if (tox_file_sendcontrol(m, friendnumber, 1, filenumber, 0, 0, 0)) {
|
||||
sprintf(msg, "Accepted file transfer. (saving file as: %u.%u.bin)", friendnumber, filenumber);
|
||||
new_lines(msg);
|
||||
} else
|
||||
new_lines("Could not accept file transfer.");
|
||||
}
|
||||
|
||||
void file_print_control(Tox *m, int friendnumber, uint8_t send_recieve, uint8_t filenumber, uint8_t control_type,
|
||||
uint8_t *data,
|
||||
uint16_t length, void *userdata)
|
||||
{
|
||||
char msg[512] = {0};
|
||||
|
||||
if (control_type == 0)
|
||||
sprintf(msg, "[t] %u accepted file transfer: %u", friendnumber, filenumber);
|
||||
else if (control_type == 3)
|
||||
sprintf(msg, "[t] %u file transfer: %u completed", friendnumber, filenumber);
|
||||
else
|
||||
sprintf(msg, "[t] control %u received", control_type);
|
||||
|
||||
new_lines(msg);
|
||||
}
|
||||
|
||||
void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
char filename[256];
|
||||
sprintf(filename, "%u.%u.bin", friendnumber, filenumber);
|
||||
FILE *pFile = fopen(filename, "a");
|
||||
|
||||
if (tox_file_dataremaining(m, friendnumber, filenumber, 1) == 0) {
|
||||
//file_control(m, friendnumber, 1, filenumber, 3, 0, 0);
|
||||
char msg[512];
|
||||
sprintf(msg, "[t] %u file transfer: %u completed", friendnumber, filenumber);
|
||||
new_lines(msg);
|
||||
}
|
||||
|
||||
if (fwrite(data, length, 1, pFile) != 1)
|
||||
new_lines("Error writing to file");
|
||||
|
||||
fclose(pFile);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -633,6 +754,9 @@ int main(int argc, char *argv[])
|
|||
tox_callback_statusmessage(m, print_statuschange, NULL);
|
||||
tox_callback_group_invite(m, print_invite, NULL);
|
||||
tox_callback_group_message(m, print_groupmessage, NULL);
|
||||
tox_callback_file_data(m, write_file, NULL);
|
||||
tox_callback_file_control(m, file_print_control, NULL);
|
||||
tox_callback_file_sendrequest(m, file_request_accept, NULL);
|
||||
|
||||
initscr();
|
||||
noecho();
|
||||
|
@ -668,6 +792,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
time_t timestamp0 = time(NULL);
|
||||
|
||||
while (1) {
|
||||
if (on == 0) {
|
||||
if (tox_isconnected(m)) {
|
||||
|
@ -675,6 +800,7 @@ int main(int argc, char *argv[])
|
|||
on = 1;
|
||||
} else {
|
||||
time_t timestamp1 = time(NULL);
|
||||
|
||||
if (timestamp0 + 10 < timestamp1) {
|
||||
timestamp0 = timestamp1;
|
||||
tox_bootstrap_from_address(m, argv[argvoffset + 1], ipv6enabled, port, binary_string);
|
||||
|
@ -682,6 +808,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
send_filesenders(m);
|
||||
tox_do(m);
|
||||
c_sleep(1);
|
||||
do_refresh();
|
||||
|
|
292
testing/tox_sync.c
Normal file
292
testing/tox_sync.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../toxcore/tox.h"
|
||||
#include "misc_tools.c"
|
||||
|
||||
#include <unistd.h>
|
||||
#define c_sleep(x) usleep(1000*x)
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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)
|
||||
if (fwrite(data, length, 1, file_recv[filenumber].file) != 1)
|
||||
printf("Error writing data\n");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -561,6 +561,32 @@ int discard_packet(Lossless_UDP *ludp, int connection_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_SYNC_RATE 20
|
||||
#define MIN_SLOTS 16
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id)
|
||||
{
|
||||
if ((unsigned int)connection_id >= ludp->connections.len)
|
||||
return 0;
|
||||
|
||||
Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
|
||||
uint32_t max_slots = (connection->data_rate / MAX_SYNC_RATE) * 1.5;
|
||||
|
||||
if (max_slots > MAX_QUEUE_NUM)
|
||||
max_slots = MAX_QUEUE_NUM;
|
||||
|
||||
if (max_slots < MIN_SLOTS)
|
||||
max_slots = MIN_SLOTS;
|
||||
|
||||
if (sendqueue(ludp, connection_id) > max_slots)
|
||||
return 0;
|
||||
|
||||
return max_slots - sendqueue(ludp, connection_id);
|
||||
}
|
||||
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
* return 1 if data was put into the queue.
|
||||
*/
|
||||
|
@ -577,6 +603,9 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
|
|||
if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM)
|
||||
return 0;
|
||||
|
||||
if (num_free_sendqueue_slots(ludp, connection_id) == 0)
|
||||
return 0;
|
||||
|
||||
if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) {
|
||||
uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length,
|
||||
connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum);
|
||||
|
@ -588,7 +617,6 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
|
|||
return write_packet(ludp, connection_id, data, length);
|
||||
}
|
||||
|
||||
|
||||
uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length;
|
||||
memcpy(connection->sendbuffer[index].data, data, length);
|
||||
connection->sendbuffer[index].size = length;
|
||||
|
@ -843,7 +871,7 @@ static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
|
|||
return;
|
||||
}
|
||||
|
||||
if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 20 || req_packets <= 1) {
|
||||
if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 5 || req_packets <= 10) {
|
||||
connection->data_rate += (connection->data_rate / 8) + 1;
|
||||
|
||||
if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
|
||||
|
@ -1098,7 +1126,7 @@ static void do_data(Lossless_UDP *ludp)
|
|||
}
|
||||
}
|
||||
|
||||
#define MAX_SYNC_RATE 20
|
||||
|
||||
|
||||
/*
|
||||
* Automatically adjusts send rates of packets for optimal transmission.
|
||||
|
|
|
@ -217,6 +217,11 @@ int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data);
|
|||
*/
|
||||
int discard_packet(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id);
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
* return 1 if data was put into the queue.
|
||||
*/
|
||||
|
|
|
@ -221,6 +221,9 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id)
|
|||
if (realloc_friendlist(m, m->numfriends + 1) != 0)
|
||||
return FAERR_NOMEM;
|
||||
|
||||
if (memcmp(client_id, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return FAERR_OWNKEY;
|
||||
|
||||
memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
|
||||
|
||||
uint32_t i;
|
||||
|
@ -607,7 +610,7 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
|
|||
m->friend_connectionstatuschange = function;
|
||||
m->friend_connectionstatuschange_userdata = userdata;
|
||||
}
|
||||
|
||||
static void break_files(Messenger *m, int friendnumber);
|
||||
static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
|
||||
{
|
||||
if (!m->friend_connectionstatuschange)
|
||||
|
@ -619,8 +622,12 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_
|
|||
const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
|
||||
const uint8_t is_online = status == FRIEND_ONLINE;
|
||||
|
||||
if (is_online != was_online)
|
||||
if (is_online != was_online) {
|
||||
if (was_online)
|
||||
break_files(m, friendnumber);
|
||||
|
||||
m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata);
|
||||
}
|
||||
}
|
||||
|
||||
void set_friend_status(Messenger *m, int friendnumber, uint8_t status)
|
||||
|
@ -929,7 +936,312 @@ static void do_allgroupchats(Messenger *m)
|
|||
}
|
||||
}
|
||||
|
||||
/*********************************/
|
||||
/****************FILE SENDING*****************/
|
||||
|
||||
|
||||
/* Set the callback for file send requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
*/
|
||||
void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
|
||||
void *), void *userdata)
|
||||
{
|
||||
m->file_sendrequest = function;
|
||||
m->file_sendrequest_userdata = userdata;
|
||||
}
|
||||
|
||||
/* Set the callback for file control requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void callback_file_control(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint8_t, uint8_t, uint8_t *,
|
||||
uint16_t,
|
||||
void *), void *userdata)
|
||||
{
|
||||
m->file_filecontrol = function;
|
||||
m->file_filecontrol_userdata = userdata;
|
||||
}
|
||||
|
||||
/* Set the callback for file data.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint8_t *, uint16_t length, void *),
|
||||
void *userdata)
|
||||
{
|
||||
m->file_filedata = function;
|
||||
m->file_filedata_userdata = userdata;
|
||||
}
|
||||
|
||||
#define MAX_FILENAME_LENGTH 255
|
||||
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename,
|
||||
uint16_t filename_length)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return 0;
|
||||
|
||||
if (filename_length > MAX_FILENAME_LENGTH)
|
||||
return 0;
|
||||
|
||||
uint8_t packet[MAX_FILENAME_LENGTH + 1 + sizeof(filesize)];
|
||||
packet[0] = filenumber;
|
||||
//TODO:
|
||||
//filesize = htonll(filesize);
|
||||
memcpy(packet + 1, &filesize, sizeof(filesize));
|
||||
memcpy(packet + 1 + sizeof(filesize), filename, filename_length);
|
||||
return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet,
|
||||
1 + sizeof(filesize) + filename_length);
|
||||
}
|
||||
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return file number on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return 0;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
|
||||
if (m->friendlist[friendnumber].file_sending[i].status == FILESTATUS_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_CONCURRENT_FILE_PIPES)
|
||||
return -1;
|
||||
|
||||
if (file_sendrequest(m, friendnumber, i, filesize, filename, filename_length) == 0)
|
||||
return -1;
|
||||
|
||||
m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NOT_ACCEPTED;
|
||||
m->friendlist[friendnumber].file_sending[i].size = filesize;
|
||||
m->friendlist[friendnumber].file_sending[i].transferred = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Send a file control request.
|
||||
* send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||
uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length > MAX_DATA_SIZE - 3)
|
||||
return 0;
|
||||
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return 0;
|
||||
|
||||
if (send_receive == 1) {
|
||||
if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
return 0;
|
||||
} else {
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (send_receive > 1)
|
||||
return 0;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
packet[0] = send_receive;
|
||||
packet[1] = filenumber;
|
||||
packet[2] = message_id;
|
||||
memcpy(packet + 3, data, length);
|
||||
|
||||
if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 3)) {
|
||||
if (send_receive == 1)
|
||||
switch (message_id) {
|
||||
case FILECONTROL_ACCEPT:
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_TRANSFERRING;
|
||||
break;
|
||||
|
||||
case FILECONTROL_PAUSE:
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_PAUSED_BY_US;
|
||||
break;
|
||||
|
||||
case FILECONTROL_KILL:
|
||||
case FILECONTROL_FINISHED:
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_NONE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch (message_id) {
|
||||
case FILECONTROL_ACCEPT:
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_TRANSFERRING;
|
||||
break;
|
||||
|
||||
case FILECONTROL_PAUSE:
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_PAUSED_BY_US;
|
||||
break;
|
||||
|
||||
case FILECONTROL_KILL:
|
||||
case FILECONTROL_FINISHED:
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define MIN_SLOTS_FREE 4
|
||||
/* Send file data.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length > MAX_DATA_SIZE - 1)
|
||||
return 0;
|
||||
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return 0;
|
||||
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING)
|
||||
return 0;
|
||||
|
||||
/* Prevent file sending from filling up the entire buffer preventing messages from being sent. */
|
||||
if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE)
|
||||
return 0;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
packet[0] = filenumber;
|
||||
memcpy(packet + 1, data, length);
|
||||
|
||||
if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1)) {
|
||||
m->friendlist[friendnumber].file_sending[filenumber].transferred += length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Give the number of bytes left to be sent/received.
|
||||
*
|
||||
* send_receive is 0 if we want the sending files, 1 if we want the receiving.
|
||||
*
|
||||
* return number of bytes remaining to be sent/received on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
uint64_t file_dataremaining(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t send_receive)
|
||||
{
|
||||
if (friend_not_valid(m, friendnumber))
|
||||
return 0;
|
||||
|
||||
if (send_receive == 0) {
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE)
|
||||
return 0;
|
||||
|
||||
return m->friendlist[friendnumber].file_sending[filenumber].size -
|
||||
m->friendlist[friendnumber].file_sending[filenumber].transferred;
|
||||
} else {
|
||||
if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
return 0;
|
||||
|
||||
return m->friendlist[friendnumber].file_receiving[filenumber].size -
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].transferred;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run this when the friend disconnects.
|
||||
* Sets all current file transfers to broken.
|
||||
*/
|
||||
static void break_files(Messenger *m, int friendnumber)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
|
||||
if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE)
|
||||
m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_BROKEN;
|
||||
|
||||
if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE)
|
||||
m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_BROKEN;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_filecontrol(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t filenumber,
|
||||
uint8_t message_id, uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
if (send_receive > 1)
|
||||
return -1;
|
||||
|
||||
if (send_receive == 0) {
|
||||
if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
return -1;
|
||||
|
||||
switch (message_id) {
|
||||
case FILECONTROL_ACCEPT:
|
||||
if (m->friendlist[friendnumber].file_receiving[filenumber].status != FILESTATUS_PAUSED_BY_US) {
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_TRANSFERRING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
case FILECONTROL_PAUSE:
|
||||
if (m->friendlist[friendnumber].file_receiving[filenumber].status != FILESTATUS_PAUSED_BY_US) {
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_PAUSED_BY_OTHER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
case FILECONTROL_KILL:
|
||||
case FILECONTROL_FINISHED:
|
||||
m->friendlist[friendnumber].file_receiving[filenumber].status = FILESTATUS_NONE;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE)
|
||||
return -1;
|
||||
|
||||
switch (message_id) {
|
||||
case FILECONTROL_ACCEPT:
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_PAUSED_BY_US) {
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_TRANSFERRING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
case FILECONTROL_PAUSE:
|
||||
if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_PAUSED_BY_US) {
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_PAUSED_BY_OTHER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case FILECONTROL_KILL:
|
||||
case FILECONTROL_FINISHED:
|
||||
m->friendlist[friendnumber].file_sending[filenumber].status = FILESTATUS_NONE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
|
||||
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
|
||||
static void LANdiscovery(Messenger *m)
|
||||
|
@ -1211,6 +1523,61 @@ void doFriends(Messenger *m)
|
|||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_SENDREQUEST: {
|
||||
if (data_length < 1 + sizeof(uint64_t) + 1)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
uint64_t filesize;
|
||||
memcpy(&filesize, data + 1, sizeof(filesize));
|
||||
//TODO:
|
||||
//filesize = ntohll(filesize);
|
||||
m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED;
|
||||
m->friendlist[i].file_receiving[filenumber].size = filesize;
|
||||
m->friendlist[i].file_receiving[filenumber].transferred = 0;
|
||||
|
||||
if (m->file_sendrequest)
|
||||
(*m->file_sendrequest)(m, i, filenumber, filesize, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t),
|
||||
m->file_sendrequest_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_CONTROL: {
|
||||
if (data_length < 3)
|
||||
break;
|
||||
|
||||
uint8_t send_receive = data[0];
|
||||
uint8_t filenumber = data[1];
|
||||
uint8_t control_type = data[2];
|
||||
|
||||
if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1)
|
||||
break;
|
||||
|
||||
if (m->file_filecontrol)
|
||||
(*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3,
|
||||
m->file_filecontrol_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_ID_FILE_DATA: {
|
||||
if (data_length < 2)
|
||||
break;
|
||||
|
||||
uint8_t filenumber = data[0];
|
||||
|
||||
if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE)
|
||||
break;
|
||||
|
||||
m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1);
|
||||
|
||||
if (m->file_filedata)
|
||||
(*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#define PACKET_ID_RECEIPT 65
|
||||
#define PACKET_ID_MESSAGE 64
|
||||
#define PACKET_ID_ACTION 63
|
||||
#define PACKET_ID_FILE_SENDREQUEST 80
|
||||
#define PACKET_ID_FILE_CONTROL 81
|
||||
#define PACKET_ID_FILE_DATA 82
|
||||
#define PACKET_ID_INVITE_GROUPCHAT 144
|
||||
#define PACKET_ID_JOIN_GROUPCHAT 145
|
||||
#define PACKET_ID_ACCEPT_GROUPCHAT 146
|
||||
|
@ -96,6 +99,29 @@ typedef enum {
|
|||
}
|
||||
USERSTATUS;
|
||||
|
||||
struct File_Transfers {
|
||||
uint64_t size;
|
||||
uint64_t transferred;
|
||||
uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused by the other, 3 = transferring, 4 = broken, 5 = paused by us */
|
||||
};
|
||||
enum {
|
||||
FILESTATUS_NONE,
|
||||
FILESTATUS_NOT_ACCEPTED,
|
||||
FILESTATUS_PAUSED_BY_OTHER,
|
||||
FILESTATUS_TRANSFERRING,
|
||||
FILESTATUS_BROKEN,
|
||||
FILESTATUS_PAUSED_BY_US
|
||||
};
|
||||
/* This cannot be bigger than 256 */
|
||||
#define MAX_CONCURRENT_FILE_PIPES 256
|
||||
|
||||
enum {
|
||||
FILECONTROL_ACCEPT,
|
||||
FILECONTROL_PAUSE,
|
||||
FILECONTROL_KILL,
|
||||
FILECONTROL_FINISHED
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
int crypt_connection_id;
|
||||
|
@ -117,6 +143,8 @@ typedef struct {
|
|||
uint32_t friendrequest_nospam; // The nospam number used in the friend request.
|
||||
uint64_t ping_lastrecv;
|
||||
uint64_t ping_lastsent;
|
||||
struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
|
||||
struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
|
||||
} Friend;
|
||||
|
||||
typedef struct Messenger {
|
||||
|
@ -157,11 +185,19 @@ typedef struct Messenger {
|
|||
void *friend_statuschange_userdata;
|
||||
void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void *);
|
||||
void *friend_connectionstatuschange_userdata;
|
||||
|
||||
void (*group_invite)(struct Messenger *m, int, uint8_t *, void *);
|
||||
void *group_invite_userdata;
|
||||
void (*group_message)(struct Messenger *m, int, int, uint8_t *, uint16_t, void *);
|
||||
void *group_message_userdata;
|
||||
|
||||
void (*file_sendrequest)(struct Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t, void *);
|
||||
void *file_sendrequest_userdata;
|
||||
void (*file_filecontrol)(struct Messenger *m, int, uint8_t, uint8_t, uint8_t, uint8_t *, uint16_t, void *);
|
||||
void *file_filecontrol_userdata;
|
||||
void (*file_filedata)(struct Messenger *m, int, uint8_t, uint8_t *, uint16_t length, void *);
|
||||
void *file_filedata_userdata;
|
||||
|
||||
} Messenger;
|
||||
|
||||
/* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
|
||||
|
@ -439,6 +475,72 @@ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_
|
|||
|
||||
int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t length);
|
||||
|
||||
/****************FILE SENDING*****************/
|
||||
|
||||
|
||||
/* Set the callback for file send requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
*/
|
||||
void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
|
||||
void *), void *userdata);
|
||||
|
||||
/* Set the callback for file control requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void callback_file_control(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint8_t, uint8_t, uint8_t *,
|
||||
uint16_t, void *), void *userdata);
|
||||
|
||||
/* Set the callback for file data.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint8_t *, uint16_t length, void *),
|
||||
void *userdata);
|
||||
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename,
|
||||
uint16_t filename_length);
|
||||
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return file number on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length);
|
||||
|
||||
/* Send a file control request.
|
||||
* send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||
uint8_t *data, uint16_t length);
|
||||
|
||||
/* Send file data.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length);
|
||||
|
||||
/* Give the number of bytes left to be sent/received.
|
||||
*
|
||||
* send_receive is 0 if we want the sending files, 1 if we want the receiving.
|
||||
*
|
||||
* return number of bytes remaining to be sent/received on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
uint64_t file_dataremaining(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t send_receive);
|
||||
|
||||
/*********************************/
|
||||
|
||||
/* Run this at startup.
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
|
||||
#include "net_crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_NICK_BYTES 128
|
||||
|
||||
typedef struct {
|
||||
|
@ -130,8 +126,6 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui
|
|||
|
||||
void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, uint8_t *client_id);
|
||||
void chat_bootstrap_nonlazy(Group_Chat *chat, IP_Port ip_port, uint8_t *client_id);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -198,6 +198,17 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
|
||||
{
|
||||
if (crypt_connection_id_not_valid(c, crypt_connection_id))
|
||||
return 0;
|
||||
|
||||
return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number);
|
||||
}
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
* return 1 if data was put into the queue.
|
||||
*/
|
||||
|
@ -579,9 +590,6 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key,
|
|||
* }
|
||||
*/
|
||||
|
||||
/* Connection is accepted. */
|
||||
confirm_connection(c->lossless_udp, connection_id);
|
||||
|
||||
if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
|
||||
|| c->crypto_connections == NULL)
|
||||
return -1;
|
||||
|
@ -721,6 +729,8 @@ static void receive_crypto(Net_Crypto *c)
|
|||
c->crypto_connections[i].shared_key);
|
||||
c->crypto_connections[i].status = CONN_ESTABLISHED;
|
||||
c->crypto_connections[i].timeout = ~0;
|
||||
/* Connection is accepted. */
|
||||
confirm_connection(c->lossless_udp, c->crypto_connections[i].number);
|
||||
} else {
|
||||
/* This should not happen, timeout the connection if it does. */
|
||||
c->crypto_connections[i].status = CONN_TIMED_OUT;
|
||||
|
|
|
@ -121,6 +121,11 @@ void new_nonce(uint8_t *nonce);
|
|||
*/
|
||||
int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data);
|
||||
|
||||
/* returns the number of packet slots left in the sendbuffer.
|
||||
* return 0 if failure.
|
||||
*/
|
||||
uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id);
|
||||
|
||||
/* return 0 if data could not be put in packet queue.
|
||||
* return 1 if data was put into the queue.
|
||||
*/
|
||||
|
|
|
@ -481,7 +481,90 @@ int tox_group_message_send(Tox *tox, int groupnumber, uint8_t *message, uint32_t
|
|||
|
||||
|
||||
|
||||
/******************END OF GROUP CHAT FUNCTIONS************************/
|
||||
/****************FILE SENDING FUNCTIONS*****************/
|
||||
|
||||
|
||||
/* Set the callback for file send requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
*/
|
||||
void tox_callback_file_sendrequest(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint64_t, uint8_t *,
|
||||
uint16_t,
|
||||
void *), void *userdata)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
callback_file_sendrequest(m, function, userdata);
|
||||
}
|
||||
/* Set the callback for file control requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void tox_callback_file_control(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint8_t, uint8_t, uint8_t *,
|
||||
uint16_t, void *), void *userdata)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
callback_file_control(m, function, userdata);
|
||||
}
|
||||
/* Set the callback for file data.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void tox_callback_file_data(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint8_t *, uint16_t length,
|
||||
void *),
|
||||
void *userdata)
|
||||
|
||||
{
|
||||
Messenger *m = tox;
|
||||
callback_file_data(m, function, userdata);
|
||||
}
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return file number on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
int tox_new_filesender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return new_filesender(m, friendnumber, filesize, filename, filename_length);
|
||||
}
|
||||
/* Send a file control request.
|
||||
* send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int tox_file_sendcontrol(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||
uint8_t *data, uint16_t length)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length);
|
||||
}
|
||||
/* Send file data.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int tox_file_senddata(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return file_data(m, friendnumber, filenumber, data, length);
|
||||
}
|
||||
/* Give the number of bytes left to be sent/received.
|
||||
*
|
||||
* send_receive is 0 if we want the sending files, 1 if we want the receiving.
|
||||
*
|
||||
* return number of bytes remaining to be sent/received on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
uint64_t tox_file_dataremaining(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t send_receive)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return file_dataremaining(m, friendnumber, filenumber, send_receive);
|
||||
}
|
||||
|
||||
/***************END OF FILE SENDING FUNCTIONS******************/
|
||||
|
||||
/* Use these functions to bootstrap the client.
|
||||
* Sends a get nodes request to the given node with ip port and public_key.
|
||||
|
|
|
@ -429,8 +429,96 @@ int tox_join_groupchat(Tox *tox, int friendnumber, uint8_t *friend_group_public_
|
|||
int tox_group_message_send(Tox *tox, int groupnumber, uint8_t *message, uint32_t length);
|
||||
|
||||
|
||||
/****************FILE SENDING FUNCTIONS*****************/
|
||||
/* NOTE: This how to will be updated.
|
||||
*
|
||||
* HOW TO SEND FILES CORRECTLY:
|
||||
* 1. Use tox_new_filesender(...) to create a new file sender.
|
||||
* 2. Wait for the callback set with tox_callback_file_control(...) to be called with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT
|
||||
* 3. Send the data with tox_file_senddata(...)
|
||||
* 4. When sending is done, send a tox_file_sendcontrol(...) with send_receive = 0 and message_id = TOX_FILECONTROL_FINISHED
|
||||
*
|
||||
* HOW TO RECEIVE FILES CORRECTLY:
|
||||
* 1. wait for the callback set with tox_callback_file_sendrequest(...)
|
||||
* 2. accept or refuse the connection with tox_file_sendcontrol(...) with send_receive = 1 and message_id = TOX_FILECONTROL_ACCEPT or TOX_FILECONTROL_KILL
|
||||
* 3. save all the data received with the callback set with tox_callback_file_data(...) to a file.
|
||||
* 4. when the callback set with tox_callback_file_control(...) is called with receive_send == 0 and control_type == TOX_FILECONTROL_FINISHED
|
||||
* the file is done transferring.
|
||||
*
|
||||
* tox_file_dataremaining(...) can be used to know how many bytes are left to send/receive.
|
||||
*
|
||||
* More to come...
|
||||
*/
|
||||
|
||||
enum {
|
||||
TOX_FILECONTROL_ACCEPT,
|
||||
TOX_FILECONTROL_PAUSE,
|
||||
TOX_FILECONTROL_KILL,
|
||||
TOX_FILECONTROL_FINISHED
|
||||
};
|
||||
/* Set the callback for file send requests.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
*/
|
||||
void tox_callback_file_sendrequest(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
|
||||
void *), void *userdata);
|
||||
|
||||
/* Set the callback for file control requests.
|
||||
*
|
||||
* receive_send is 1 if the message is for a slot on which we are currently sending a file and 0 if the message
|
||||
* is for a slot on which we are receiving the file
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void tox_callback_file_control(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint8_t, uint8_t, uint8_t *,
|
||||
uint16_t, void *), void *userdata);
|
||||
|
||||
/* Set the callback for file data.
|
||||
*
|
||||
* Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
*
|
||||
*/
|
||||
void tox_callback_file_data(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint8_t *, uint16_t length, void *),
|
||||
void *userdata);
|
||||
|
||||
|
||||
/* Send a file send request.
|
||||
* Maximum filename length is 255 bytes.
|
||||
* return file number on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
int tox_new_filesender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length);
|
||||
|
||||
/* Send a file control request.
|
||||
*
|
||||
* send_receive is 0 if we want the control packet to target a file we are currently sending,
|
||||
* 1 if it targets a file we are currently receiving.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int tox_file_sendcontrol(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
|
||||
uint8_t *data, uint16_t length);
|
||||
|
||||
/* Send file data.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
int tox_file_senddata(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length);
|
||||
|
||||
/* Give the number of bytes left to be sent/received.
|
||||
*
|
||||
* send_receive is 0 if we want the sending files, 1 if we want the receiving.
|
||||
*
|
||||
* return number of bytes remaining to be sent/received on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
uint64_t tox_file_dataremaining(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t send_receive);
|
||||
|
||||
/***************END OF FILE SENDING FUNCTIONS******************/
|
||||
|
||||
/******************END OF GROUP CHAT FUNCTIONS************************/
|
||||
|
||||
/*
|
||||
* Use these two functions to bootstrap the client.
|
||||
|
|
|
@ -20,7 +20,6 @@ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len
|
|||
int load_state(load_state_callback_func load_state_callback, void *outer,
|
||||
uint8_t *data, uint32_t length, uint16_t cookie_inner);
|
||||
|
||||
#define LOGGING
|
||||
#ifdef LOGGING
|
||||
extern char logbuffer[512];
|
||||
void loginit(uint16_t port);
|
||||
|
|
Loading…
Reference in New Issue
Block a user