From a0f94267ad2ea0ecd111c4aac2e8b35aad6ceed3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 30 Sep 2013 09:35:17 -0400 Subject: File sending. --- toxcore/Messenger.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++- toxcore/Messenger.h | 60 ++++++++++++++++++++++ 2 files changed, 200 insertions(+), 1 deletion(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index c8d69494..b21da28b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -928,7 +928,104 @@ 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 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 *, 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 256 + +/* Send a file send request. + * Maximum filename length is 256 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 (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 control request. + * + * return 1 on success + * return 0 on failure + */ +int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t message_id, uint8_t *data, uint16_t length) +{ + if (length > MAX_DATA_SIZE - 2) + return 0; + + uint8_t packet[MAX_DATA_SIZE]; + packet[0] = filenumber; + packet[1] = message_id; + memcpy(packet + 2, data, length); + return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2); +} + + +/* 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; + + uint8_t packet[MAX_DATA_SIZE]; + packet[0] = filenumber; + memcpy(packet + 1, data, length); + return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1); +} + +/**************************************/ + /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ static void LANdiscovery(Messenger *m) @@ -1210,6 +1307,48 @@ 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); + 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 < 2) + break; + + uint8_t filenumber = data[0]; + uint8_t control_type = data[1]; + + if (m->file_filecontrol) + (*m->file_filecontrol)(m, i, filenumber, control_type, data + 2, data_length - 2, m->file_filecontrol_userdata); + + break; + } + + case PACKET_ID_FILE_DATA: { + if (data_length < 2) + break; + + uint8_t filenumber = data[0]; + + if (m->file_filedata) + (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); + + break; + } + default: { break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 0ff14de4..05a5af27 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -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 @@ -157,11 +160,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 *, 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 +450,55 @@ 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 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 *, 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 256 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 control request. + * + * return 1 on success + * return 0 on failure + */ +int file_control(Messenger *m, int friendnumber, 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); + /*********************************/ /* Run this at startup. -- cgit v1.2.3 From 3c7de51ba5dea7192d507f8cc834dfd5a9f64455 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 30 Sep 2013 13:13:49 -0400 Subject: Basic ntox file sending. --- testing/nTox.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/testing/nTox.c b/testing/nTox.c index 6ac663a6..cbf8d028 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -67,6 +67,55 @@ 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 (!file_data(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; + break; + } + } + } +} +int add_filesender(Tox *m, uint16_t friendnum, char *filename) +{ + file_senders[numfilesenders].file = fopen(filename, "r"); + + if (file_senders[numfilesenders].file == 0) + return -1; + + file_senders[numfilesenders].piecelength = fread(file_senders[numfilesenders].nextpiece, 1, 1000, + file_senders[numfilesenders].file); + file_senders[numfilesenders].friendnum = friendnum; + file_senders[numfilesenders].filenumber = numfilesenders; + ++numfilesenders; + return (numfilesenders - 1); +} + /* resolve_addr(): address should represent IPv4 or a hostname with A record @@ -366,6 +415,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 returned %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 +645,15 @@ void print_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *messag new_lines(msg); } +void write_file(Tox *tox, 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"); + fwrite(data, length, 1, pFile); + fclose(pFile); +} + int main(int argc, char *argv[]) { @@ -633,6 +701,7 @@ 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); + callback_file_data(m, write_file, NULL); initscr(); noecho(); @@ -668,6 +737,7 @@ int main(int argc, char *argv[]) } time_t timestamp0 = time(NULL); + while (1) { if (on == 0) { if (tox_isconnected(m)) { @@ -675,6 +745,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 +753,7 @@ int main(int argc, char *argv[]) } } + send_filesenders(m); tox_do(m); c_sleep(1); do_refresh(); -- cgit v1.2.3 From 766cff692f9dc93ef284a214ad4bc6389d6afa76 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 1 Oct 2013 11:44:27 -0400 Subject: File sending now works on bad wireless connections. --- toxcore/Lossless_UDP.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c index 53cdea09..bdf5cd4c 100644 --- a/toxcore/Lossless_UDP.c +++ b/toxcore/Lossless_UDP.c @@ -547,6 +547,8 @@ int discard_packet(Lossless_UDP *ludp, int connection_id) return 0; } +#define MAX_SYNC_RATE 20 + /* return 0 if data could not be put in packet queue. * return 1 if data was put into the queue. */ @@ -564,6 +566,8 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t return 0; if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) { + if (sendqueue(ludp, connection_id) > connection->data_rate/MAX_SYNC_RATE) + return 0; uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length, connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum); @@ -829,7 +833,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) @@ -1084,7 +1088,7 @@ static void do_data(Lossless_UDP *ludp) } } -#define MAX_SYNC_RATE 20 + /* * Automatically adjusts send rates of packets for optimal transmission. -- cgit v1.2.3 From 6dbc8a54969421c5baeb0ec7bb50779c62ae2e44 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 1 Oct 2013 16:48:32 -0400 Subject: Core now takes better care of file transfers. --- toxcore/Messenger.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++-- toxcore/Messenger.h | 18 ++++++++ 2 files changed, 142 insertions(+), 5 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b21da28b..39bcd704 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -606,7 +606,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) @@ -618,8 +618,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) @@ -938,7 +942,6 @@ static void do_allgroupchats(Messenger *m) 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; } @@ -977,6 +980,9 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_ 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; @@ -990,6 +996,35 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_ 1 + sizeof(filesize) + filename_length); } +/* Send a file send request. + * Maximum filename length is 256 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 == 0) + 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 = 1; + m->friendlist[friendnumber].file_sending[i].size = filesize; + m->friendlist[friendnumber].file_sending[i].transferred = 0; + return i; +} + /* Send a file control request. * * return 1 on success @@ -1000,11 +1035,37 @@ int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t mes if (length > MAX_DATA_SIZE - 2) return 0; + if (friend_not_valid(m, friendnumber)) + return 0; + + if (m->friendlist[friendnumber].file_sending[filenumber].status == 0) + return 0; + uint8_t packet[MAX_DATA_SIZE]; packet[0] = filenumber; packet[1] = message_id; memcpy(packet + 2, data, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2); + + if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2)) { + switch (message_id) { + case FILECONTROL_ACCEPT: + m->friendlist[friendnumber].file_receiving[filenumber].status = 3; + break; + + case FILECONTROL_PAUSE: + m->friendlist[friendnumber].file_receiving[filenumber].status = 2; + break; + + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_receiving[filenumber].status = 0; + break; + } + + return 1; + } else { + return 0; + } } @@ -1018,10 +1079,62 @@ int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, if (length > MAX_DATA_SIZE - 1) return 0; + if (friend_not_valid(m, friendnumber)) + return 0; + + if (m->friendlist[friendnumber].file_sending[filenumber].status != 3) + return 0; + uint8_t packet[MAX_DATA_SIZE]; packet[0] = filenumber; memcpy(packet + 1, data, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1); + + 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; + +} +/* 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 != 0) + m->friendlist[friendnumber].file_sending[i].status = 4; + + if (m->friendlist[friendnumber].file_receiving[i].status != 0) + m->friendlist[friendnumber].file_receiving[i].status = 4; + } +} + +static int handle_filecontrol(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t message_id, uint8_t *data, + uint16_t length) +{ + if (m->friendlist[friendnumber].file_sending[filenumber].status == 0) + return -1; + + switch (message_id) { + case FILECONTROL_ACCEPT: + m->friendlist[friendnumber].file_sending[filenumber].status = 3; + return 0; + + case FILECONTROL_PAUSE: + m->friendlist[friendnumber].file_sending[filenumber].status = 2; + return 0; + + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_sending[filenumber].status = 0; + return 0; + } + + return -1; } /**************************************/ @@ -1331,6 +1444,9 @@ void doFriends(Messenger *m) uint8_t filenumber = data[0]; uint8_t control_type = data[1]; + if (handle_filecontrol(m, i, filenumber, control_type, data + 2, data_length - 2) == -1) + break; + if (m->file_filecontrol) (*m->file_filecontrol)(m, i, filenumber, control_type, data + 2, data_length - 2, m->file_filecontrol_userdata); @@ -1343,6 +1459,9 @@ void doFriends(Messenger *m) uint8_t filenumber = data[0]; + if (m->friendlist[i].file_receiving[filenumber].status == 0) + break; + if (m->file_filedata) (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 05a5af27..fbf4d767 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -99,6 +99,22 @@ typedef enum { } USERSTATUS; +struct File_Transfers { + uint64_t size; + uint64_t transferred; + uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused, 3 = transferring, 4 = broken*/ +}; + +/* 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; @@ -120,6 +136,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 { -- cgit v1.2.3 From 6182af8449920a0256b91affe74d873066b17c99 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 1 Oct 2013 18:59:33 -0400 Subject: nTox updated with changes in core, some file sending things fixes. --- testing/nTox.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++------ toxcore/Messenger.c | 36 ++++++++++++++++++++++++++++++-- toxcore/Messenger.h | 16 ++++++++++++++ 3 files changed, 104 insertions(+), 8 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index cbf8d028..92827554 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -103,17 +103,26 @@ void send_filesenders(Tox *m) } int add_filesender(Tox *m, uint16_t friendnum, char *filename) { - file_senders[numfilesenders].file = fopen(filename, "r"); + FILE *tempfile = fopen(filename, "r"); - if (file_senders[numfilesenders].file == 0) + if (tempfile == 0) return -1; + fseek(tempfile, 0, SEEK_END); + uint64_t filesize = ftell(tempfile); + fseek(tempfile, 0, SEEK_SET); + int filenum = new_filesender(m, friendnum, filesize, 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 = numfilesenders; + file_senders[numfilesenders].filenumber = filenum; ++numfilesenders; - return (numfilesenders - 1); + return filenum; } /* @@ -421,7 +430,7 @@ void line_eval(Tox *m, char *line) int friendnum = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { - sprintf(msg, "[t] Sending file %s to friendnum %u returned %i (-1 means failure)", *posi + 1, friendnum, + 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); } @@ -645,11 +654,48 @@ void print_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *messag new_lines(msg); } -void write_file(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) +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, filesize); + new_lines(msg); + + if (file_control(m, friendnumber, 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 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, 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 (file_dataremaining(m, friendnumber, filenumber, 1) == 0) { + file_control(m, friendnumber, filenumber, 3, 0, 0); + char msg[512]; + sprintf(msg, "[t] %u file transfer: %u completed", friendnumber, filenumber); + new_lines(msg); + } + fwrite(data, length, 1, pFile); fclose(pFile); } @@ -702,6 +748,8 @@ int main(int argc, char *argv[]) tox_callback_group_invite(m, print_invite, NULL); tox_callback_group_message(m, print_groupmessage, NULL); callback_file_data(m, write_file, NULL); + callback_file_control(m, file_print_control, NULL); + callback_file_sendrequest(m, file_request_accept, NULL); initscr(); noecho(); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 39bcd704..49be4a0a 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1038,7 +1038,7 @@ int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t mes if (friend_not_valid(m, friendnumber)) return 0; - if (m->friendlist[friendnumber].file_sending[filenumber].status == 0) + if (m->friendlist[friendnumber].file_receiving[filenumber].status == 0) return 0; uint8_t packet[MAX_DATA_SIZE]; @@ -1097,6 +1097,34 @@ int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, 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 == 0) + 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 == 0) + 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. */ @@ -1427,9 +1455,11 @@ void doFriends(Messenger *m) 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 = 1; + m->friendlist[i].file_receiving[filenumber].size = filesize; + 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); @@ -1462,6 +1492,8 @@ void doFriends(Messenger *m) if (m->friendlist[i].file_receiving[filenumber].status == 0) 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); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index fbf4d767..ca99fa18 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -502,6 +502,13 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_ 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 256 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. * * return 1 on success @@ -517,6 +524,15 @@ int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t mes */ 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. -- cgit v1.2.3 From 2467e6d592327884d151f5a93c1bd19214744dc5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 2 Oct 2013 09:42:28 -0400 Subject: Fixed bug. --- toxcore/Messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 49be4a0a..b31e1c81 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1459,7 +1459,7 @@ void doFriends(Messenger *m) //filesize = ntohll(filesize); m->friendlist[i].file_receiving[filenumber].status = 1; 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); -- cgit v1.2.3 From 0fb3c9eeede6da300cd4bb94540af09ee9a3327e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 2 Oct 2013 10:28:08 -0400 Subject: Max length of filenames is now 255 bytes. --- toxcore/Messenger.c | 6 +++--- toxcore/Messenger.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b31e1c81..6035fcb7 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -970,10 +970,10 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_ m->file_filedata_userdata = userdata; } -#define MAX_FILENAME_LENGTH 256 +#define MAX_FILENAME_LENGTH 255 /* Send a file send request. - * Maximum filename length is 256 bytes. + * Maximum filename length is 255 bytes. * return 1 on success * return 0 on failure */ @@ -997,7 +997,7 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_ } /* Send a file send request. - * Maximum filename length is 256 bytes. + * Maximum filename length is 255 bytes. * return file number on success * return -1 on failure */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index ca99fa18..8e635afe 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -495,7 +495,7 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_ void *userdata); /* Send a file send request. - * Maximum filename length is 256 bytes. + * Maximum filename length is 255 bytes. * return 1 on success * return 0 on failure */ @@ -503,7 +503,7 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_ uint16_t filename_length); /* Send a file send request. - * Maximum filename length is 256 bytes. + * Maximum filename length is 255 bytes. * return file number on success * return -1 on failure */ -- cgit v1.2.3 From 6425cf3b53d6e095b4dc97bd08ec39b31fd1e786 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 2 Oct 2013 20:08:14 -0400 Subject: File control packets can now be used by the person sending the file. --- testing/nTox.c | 11 +++-- toxcore/Messenger.c | 137 +++++++++++++++++++++++++++++++++++++--------------- toxcore/Messenger.h | 14 +++--- 3 files changed, 115 insertions(+), 47 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index 92827554..1051155f 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -96,6 +96,10 @@ void send_filesenders(Tox *m) if (file_senders[i].piecelength == 0) { fclose(file_senders[i].file); file_senders[i].file = 0; + file_control(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; } } @@ -661,14 +665,15 @@ void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t sprintf(msg, "[t] %u is sending us: %s of size %llu", friendnumber, filename, filesize); new_lines(msg); - if (file_control(m, friendnumber, filenumber, 0, 0, 0)) { + if (file_control(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 filenumber, uint8_t control_type, uint8_t *data, +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}; @@ -690,7 +695,7 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uin FILE *pFile = fopen(filename, "a"); if (file_dataremaining(m, friendnumber, filenumber, 1) == 0) { - file_control(m, friendnumber, filenumber, 3, 0, 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); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 49be4a0a..6ad3fd00 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -948,10 +948,11 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, /* Set the callback for file control requests. * - * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata) + * 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 *, uint16_t, +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; @@ -1026,13 +1027,15 @@ int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *f } /* 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 filenumber, uint8_t message_id, uint8_t *data, uint16_t length) +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 - 2) + if (length > MAX_DATA_SIZE - 3) return 0; if (friend_not_valid(m, friendnumber)) @@ -1041,26 +1044,46 @@ int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t mes if (m->friendlist[friendnumber].file_receiving[filenumber].status == 0) return 0; + if (send_receive > 1) + return 0; + uint8_t packet[MAX_DATA_SIZE]; - packet[0] = filenumber; - packet[1] = message_id; - memcpy(packet + 2, data, length); + 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 = 3; + break; - if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2)) { - switch (message_id) { - case FILECONTROL_ACCEPT: - m->friendlist[friendnumber].file_receiving[filenumber].status = 3; - break; + case FILECONTROL_PAUSE: + m->friendlist[friendnumber].file_receiving[filenumber].status = 5; + break; - case FILECONTROL_PAUSE: - m->friendlist[friendnumber].file_receiving[filenumber].status = 2; - break; + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_receiving[filenumber].status = 0; + break; + } + else + switch (message_id) { + case FILECONTROL_ACCEPT: + m->friendlist[friendnumber].file_sending[filenumber].status = 3; + break; - case FILECONTROL_KILL: - case FILECONTROL_FINISHED: - m->friendlist[friendnumber].file_receiving[filenumber].status = 0; - break; - } + case FILECONTROL_PAUSE: + m->friendlist[friendnumber].file_sending[filenumber].status = 5; + break; + + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_sending[filenumber].status = 0; + break; + } return 1; } else { @@ -1141,25 +1164,61 @@ static void break_files(Messenger *m, int friendnumber) } } -static int handle_filecontrol(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t message_id, uint8_t *data, +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 (m->friendlist[friendnumber].file_sending[filenumber].status == 0) + if (send_receive > 1) return -1; - switch (message_id) { - case FILECONTROL_ACCEPT: - m->friendlist[friendnumber].file_sending[filenumber].status = 3; - return 0; + if (send_receive == 0) { + if (m->friendlist[friendnumber].file_receiving[filenumber].status == 0) + return -1; - case FILECONTROL_PAUSE: - m->friendlist[friendnumber].file_sending[filenumber].status = 2; - return 0; + switch (message_id) { + case FILECONTROL_ACCEPT: + if (m->friendlist[friendnumber].file_receiving[filenumber].status != 5) { + m->friendlist[friendnumber].file_receiving[filenumber].status = 3; + return 0; + } - case FILECONTROL_KILL: - case FILECONTROL_FINISHED: - m->friendlist[friendnumber].file_sending[filenumber].status = 0; - return 0; + return -1; + + case FILECONTROL_PAUSE: + if (m->friendlist[friendnumber].file_receiving[filenumber].status != 5) { + m->friendlist[friendnumber].file_receiving[filenumber].status = 2; + return 0; + } + + return -1; + + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_receiving[filenumber].status = 0; + return 0; + } + } else { + if (m->friendlist[friendnumber].file_sending[filenumber].status == 0) + return -1; + + switch (message_id) { + case FILECONTROL_ACCEPT: + if (m->friendlist[friendnumber].file_sending[filenumber].status != 5) { + m->friendlist[friendnumber].file_sending[filenumber].status = 3; + return 0; + } + + return -1; + + case FILECONTROL_PAUSE: + m->friendlist[friendnumber].file_sending[filenumber].status = 2; + return 0; + + case FILECONTROL_KILL: + case FILECONTROL_FINISHED: + m->friendlist[friendnumber].file_sending[filenumber].status = 0; + return 0; + } } return -1; @@ -1468,17 +1527,19 @@ void doFriends(Messenger *m) } case PACKET_ID_FILE_CONTROL: { - if (data_length < 2) + if (data_length < 3) break; - uint8_t filenumber = data[0]; - uint8_t control_type = data[1]; + uint8_t send_receive = data[0]; + uint8_t filenumber = data[1]; + uint8_t control_type = data[2]; - if (handle_filecontrol(m, i, filenumber, control_type, data + 2, data_length - 2) == -1) + 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, filenumber, control_type, data + 2, data_length - 2, m->file_filecontrol_userdata); + (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, + m->file_filecontrol_userdata); break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index ca99fa18..8ca93153 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -102,7 +102,7 @@ USERSTATUS; struct File_Transfers { uint64_t size; uint64_t transferred; - uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused, 3 = transferring, 4 = broken*/ + uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused by the other, 3 = transferring, 4 = broken, 5 = paused by us */ }; /* This cannot be bigger than 256 */ @@ -186,7 +186,7 @@ typedef struct Messenger { 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 *, uint16_t, void *); + 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; @@ -480,10 +480,11 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, /* Set the callback for file control requests. * - * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata) + * 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 *, uint16_t, +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. @@ -510,12 +511,13 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_ 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 filenumber, uint8_t message_id, uint8_t *data, - uint16_t length); +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. * -- cgit v1.2.3 From fbd494a8b44d58911a6329761d48a85f71fc1718 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 2 Oct 2013 20:53:24 -0400 Subject: File sending added to public api. --- testing/nTox.c | 20 ++++++------ toxcore/Messenger.h | 3 +- toxcore/tox.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++- toxcore/tox.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 184 insertions(+), 14 deletions(-) diff --git a/testing/nTox.c b/testing/nTox.c index 1051155f..f82c0fba 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -87,8 +87,8 @@ void send_filesenders(Tox *m) continue; while (1) { - if (!file_data(m, file_senders[i].friendnum, file_senders[i].filenumber, file_senders[i].nextpiece, - file_senders[i].piecelength)) + 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); @@ -96,7 +96,7 @@ void send_filesenders(Tox *m) if (file_senders[i].piecelength == 0) { fclose(file_senders[i].file); file_senders[i].file = 0; - file_control(m, file_senders[i].friendnum, 0, file_senders[i].filenumber, 3, 0, 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); @@ -115,7 +115,7 @@ int add_filesender(Tox *m, uint16_t friendnum, char *filename) fseek(tempfile, 0, SEEK_END); uint64_t filesize = ftell(tempfile); fseek(tempfile, 0, SEEK_SET); - int filenum = new_filesender(m, friendnum, filesize, filename, strlen(filename) + 1); + int filenum = tox_new_filesender(m, friendnum, filesize, (uint8_t *)filename, strlen(filename) + 1); if (filenum == -1) return -1; @@ -665,7 +665,7 @@ void file_request_accept(Tox *m, int friendnumber, uint8_t filenumber, uint64_t sprintf(msg, "[t] %u is sending us: %s of size %llu", friendnumber, filename, filesize); new_lines(msg); - if (file_control(m, friendnumber, 1, filenumber, 0, 0, 0)) { + 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 @@ -679,7 +679,7 @@ void file_print_control(Tox *m, int friendnumber, uint8_t send_recieve, uint8_t char msg[512] = {0}; if (control_type == 0) - sprintf(msg, "[t] %u accepted file transfer: %u", friendnumber, filenumber, friendnumber, filenumber); + 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 @@ -694,7 +694,7 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uin sprintf(filename, "%u.%u.bin", friendnumber, filenumber); FILE *pFile = fopen(filename, "a"); - if (file_dataremaining(m, friendnumber, filenumber, 1) == 0) { + 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); @@ -752,9 +752,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); - callback_file_data(m, write_file, NULL); - callback_file_control(m, file_print_control, NULL); - callback_file_sendrequest(m, file_request_accept, 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(); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 40b2fac2..5d31e15b 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -484,8 +484,7 @@ void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, * */ void callback_file_control(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint8_t, uint8_t, uint8_t *, - uint16_t, - void *), void *userdata); + uint16_t, void *), void *userdata); /* Set the callback for file data. * diff --git a/toxcore/tox.c b/toxcore/tox.c index 1d7118be..21e8bf75 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -473,7 +473,90 @@ int tox_group_message_send(void *tox, int groupnumber, uint8_t *message, uint32_ -/******************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(void *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(void *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(void *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(void *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(void *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(void *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(void *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. diff --git a/toxcore/tox.h b/toxcore/tox.h index eabbb1af..b1f18515 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -426,8 +426,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. -- cgit v1.2.3