Added tox_file_send_seek() function to api.

This function can be used to seek an incoming file tranfer right
before accepting it.

It is meant to be used to resume incomplete file tranfers by clients.
This commit is contained in:
irungentoo 2015-03-17 15:05:17 -04:00
parent e072079620
commit ea8d27259f
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
5 changed files with 206 additions and 11 deletions

View File

@ -100,6 +100,9 @@ void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size
return;
}
uint64_t size_recv;
uint64_t sending_pos;
uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
uint8_t filenum;
uint32_t file_accepted;
@ -137,6 +140,15 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui
}
file_size = filesize;
sending_pos = size_recv = 1337;
TOX_ERR_FILE_SEEK err_s;
if (!tox_file_send_seek(tox, friend_number, file_number, 1337, &err_s)) {
ck_abort_msg("tox_file_send_seek error");
}
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_send_seek wrong error");
TOX_ERR_FILE_CONTROL error;
@ -145,6 +157,12 @@ void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, ui
} else {
ck_abort_msg("tox_file_send_control failed. %i", error);
}
if (tox_file_send_seek(tox, friend_number, file_number, 1234, &err_s)) {
ck_abort_msg("tox_file_send_seek no error");
}
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_send_seek wrong error");
}
uint32_t sendf_ok;
@ -160,7 +178,6 @@ void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number,
}
uint8_t sending_num;
uint64_t sending_pos;
_Bool file_sending_done;
void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length,
void *user_data)
@ -173,7 +190,7 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb
}
if (sending_pos != position) {
ck_abort_msg("Bad position");
ck_abort_msg("Bad position %llu", position);
return;
}
@ -199,7 +216,6 @@ void tox_file_request_chunk(Tox *tox, uint32_t friend_number, uint32_t file_numb
}
uint64_t size_recv;
uint8_t num;
_Bool file_recv;
void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
@ -549,7 +565,6 @@ START_TEST(test_few_clients)
ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
while (1) {
tox_iterate(tox1);
tox_iterate(tox2);
@ -559,8 +574,8 @@ START_TEST(test_few_clients)
if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv) {
break;
} else {
ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u", sendf_ok, file_recv, totalf_size == file_size,
size_recv == file_size, sending_pos == size_recv);
ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv,
totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, totalf_size, size_recv, sending_pos);
}
}

View File

@ -1155,7 +1155,7 @@ int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t s
packet[2] = control_type;
if (data_length) {
memcpy(packet, packet + 3, data_length);
memcpy(packet + 3, data, data_length);
}
return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, sizeof(packet), 0);
@ -1247,6 +1247,71 @@ int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber,
return 0;
}
/* Send a seek file control request.
*
* return 0 on success
* return -1 if friend not valid.
* return -2 if friend not online.
* return -3 if file number invalid.
* return -4 if not receiving file.
* return -5 if file status wrong.
* return -6 if position bad.
* return -8 if packet failed to send.
*/
int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position)
{
if (friend_not_valid(m, friendnumber))
return -1;
if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
return -2;
uint32_t temp_filenum;
uint8_t send_receive, file_number;
if (filenumber >= (1 << 16)) {
send_receive = 1;
temp_filenum = (filenumber >> 16) - 1;
} else {
return -4;
}
if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES)
return -3;
file_number = temp_filenum;
struct File_Transfers *ft;
if (send_receive) {
ft = &m->friendlist[friendnumber].file_receiving[file_number];
} else {
ft = &m->friendlist[friendnumber].file_sending[file_number];
}
if (ft->status == FILESTATUS_NONE)
return -3;
if (ft->status != FILESTATUS_NOT_ACCEPTED)
return -5;
if (ft->size && position > ft->size) {
return -6;
}
uint64_t sending_pos = position;
host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos));
if (send_file_control_packet(m, friendnumber, send_receive, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos,
sizeof(sending_pos))) {
ft->transferred = position;
} else {
return -8;
}
return 0;
}
/* return packet number on success.
* return -1 on failure.
*/
@ -1473,7 +1538,7 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv
if (receive_send > 1)
return -1;
if (control_type > FILECONTROL_RESUME_BROKEN)
if (control_type > FILECONTROL_SEEK)
return -1;
uint32_t real_filenumber = filenumber;
@ -1518,8 +1583,26 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv
--m->friendlist[friendnumber].num_sending_files;
}
} else if (control_type == FILECONTROL_RESUME_BROKEN) {
//TODO
} else if (control_type == FILECONTROL_SEEK) {
uint64_t position;
if (length != sizeof(position)) {
return -1;
}
/* seek can only be sent by the receiver to seek before resuming broken tranfers. */
if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
return -1;
}
memcpy(&position, data, sizeof(position));
net_to_host((uint8_t *) &position, sizeof(position));
if (ft->size && position > ft->size) {
return -1;
}
ft->transferred = ft->requested = position;
} else {
return -1;
}

View File

@ -159,7 +159,7 @@ enum {
FILECONTROL_ACCEPT,
FILECONTROL_PAUSE,
FILECONTROL_KILL,
FILECONTROL_RESUME_BROKEN
FILECONTROL_SEEK
};
enum {
@ -648,6 +648,19 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_
*/
int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control);
/* Send a seek file control request.
*
* return 0 on success
* return -1 if friend not valid.
* return -2 if friend not online.
* return -3 if file number invalid.
* return -4 if not receiving file.
* return -5 if file status wrong.
* return -6 if position bad.
* return -8 if packet failed to send.
*/
int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position);
/* Send file data.
*
* return 0 on success

View File

@ -883,6 +883,48 @@ bool tox_file_send_control(Tox *tox, uint32_t friend_number, uint32_t file_numbe
return 0;
}
bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
TOX_ERR_FILE_SEEK *error)
{
Messenger *m = tox;
int ret = file_seek(m, friend_number, file_number, position);
if (ret == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK);
return 1;
}
switch (ret) {
case -1:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND);
return 0;
case -2:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED);
return 0;
case -3:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);
return 0;
case -4:
case -5:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);
return 0;
case -6:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION);
return 0;
case -8:
SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SEND_FAILED);
return 0;
}
/* can't happen */
return 0;
}
void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data)
{
Messenger *m = tox;

View File

@ -1539,6 +1539,48 @@ typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t
void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data);
typedef enum TOX_ERR_FILE_SEEK {
TOX_ERR_FILE_SEEK_OK,
/**
* The friend_number passed did not designate a valid friend.
*/
TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND,
/**
* This client is currently not connected to the friend.
*/
TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED,
/**
* No file transfer with the given file number was found for the given friend.
*/
TOX_ERR_FILE_SEEK_NOT_FOUND,
/**
* File was not in a state where it could be seeked.
*/
TOX_ERR_FILE_SEEK_DENIED,
/**
* Seek position was invalid
*/
TOX_ERR_FILE_SEEK_INVALID_POSITION,
/**
* Packet failed to send.
*/
TOX_ERR_FILE_SEEK_SEND_FAILED
} TOX_ERR_FILE_SEEK;
/**
* Sends a file seek control command to a friend for a given file transfer.
*
* This function can only be called to resume a file transfer right before
* TOX_FILE_CONTROL_RESUME is sent.
*
* @param friend_number The friend number of the friend the file is being
* transferred to.
* @param file_number The friend-specific identifier for the file transfer.
* @param position The position that the file should be seeked to.
*/
bool tox_file_send_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
TOX_ERR_FILE_SEEK *error);
typedef enum TOX_ERR_FILE_GET {
TOX_ERR_FILE_GET_OK,
/**