Merge branch 'file-transfers'

File transfers are now working and in public api.
This commit is contained in:
irungentoo
2013-10-02 20:53:48 -04:00
6 changed files with 753 additions and 7 deletions
+125
View File
@@ -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,53 @@ 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, 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);
}
fwrite(data, length, 1, pFile);
fclose(pFile);
}
int main(int argc, char *argv[])
{
@@ -633,6 +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);
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 +790,7 @@ int main(int argc, char *argv[])
}
time_t timestamp0 = time(NULL);
while (1) {
if (on == 0) {
if (tox_isconnected(m)) {
@@ -675,6 +798,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 +806,7 @@ int main(int argc, char *argv[])
}
}
send_filesenders(m);
tox_do(m);
c_sleep(1);
do_refresh();
+6 -2
View File
@@ -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.
+354 -3
View File
@@ -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)
@@ -928,7 +932,300 @@ 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 == 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.
* 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 (m->friendlist[friendnumber].file_receiving[filenumber].status == 0)
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 = 3;
break;
case FILECONTROL_PAUSE:
m->friendlist[friendnumber].file_receiving[filenumber].status = 5;
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_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 {
return 0;
}
}
/* 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 != 3)
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 == 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.
*/
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 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 == 0)
return -1;
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;
}
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;
}
/**************************************/
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
static void LANdiscovery(Messenger *m)
@@ -1210,6 +1507,60 @@ 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 = 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);
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 == 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);
break;
}
default: {
break;
}
+95
View File
@@ -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,22 @@ 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 */
};
/* 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 +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 {
@@ -157,11 +178,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 +468,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.
+84 -1
View File
@@ -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.
+89 -1
View File
@@ -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.