mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-23 10:23:26 +01:00
Fix some filetransfer issues
- File transfers now timeout properly - Small refactor related to creating new transfers
This commit is contained in:
parent
327259c4c8
commit
2a787c1097
@ -63,7 +63,7 @@ int avatar_send(Tox *m, uint32_t friendnum)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct FileTransfer *ft = get_new_file_sender(friendnum);
|
||||
struct FileTransfer *ft = new_file_transfer(NULL, friendnum, filenum, FILE_TRANSFER_SEND, TOX_FILE_KIND_AVATAR);
|
||||
|
||||
if (!ft)
|
||||
return -1;
|
||||
@ -75,11 +75,6 @@ int avatar_send(Tox *m, uint32_t friendnum)
|
||||
|
||||
snprintf(ft->file_name, sizeof(ft->file_name), "%s", Avatar.name);
|
||||
ft->file_size = Avatar.size;
|
||||
ft->state = FILE_TRANSFER_PENDING;
|
||||
ft->filenum = filenum;
|
||||
ft->friendnum = friendnum;
|
||||
ft->direction = FILE_TRANSFER_SEND;
|
||||
ft->file_type = TOX_FILE_KIND_AVATAR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -206,4 +201,5 @@ void on_avatar_chunk_request(Tox *m, struct FileTransfer *ft, uint64_t position,
|
||||
fprintf(stderr, "tox_file_send_chunk failed in avatar callback (error %d)\n", err);
|
||||
|
||||
ft->position += send_length;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
}
|
||||
|
27
src/chat.c
27
src/chat.c
@ -373,6 +373,7 @@ static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum,
|
||||
|
||||
ft->position += send_length;
|
||||
ft->bps += send_length;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
}
|
||||
|
||||
static void chat_onFileRecvChunk(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
|
||||
@ -412,6 +413,7 @@ static void chat_onFileRecvChunk(ToxWindow *self, Tox *m, uint32_t friendnum, ui
|
||||
|
||||
ft->bps += length;
|
||||
ft->position += length;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
}
|
||||
|
||||
static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, TOX_FILE_CONTROL control)
|
||||
@ -427,14 +429,16 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint
|
||||
char msg[MAX_STR_SIZE];
|
||||
|
||||
switch (control) {
|
||||
case TOX_FILE_CONTROL_RESUME:
|
||||
case TOX_FILE_CONTROL_RESUME: {
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
|
||||
/* transfer is accepted */
|
||||
if (ft->state == FILE_TRANSFER_PENDING) {
|
||||
ft->state = FILE_TRANSFER_STARTED;
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%d] for '%s' accepted.",
|
||||
ft->index, ft->file_name);
|
||||
char progline[MAX_STR_SIZE];
|
||||
prep_prog_line(progline);
|
||||
init_progress_bar(progline);
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
|
||||
sound_notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2, NULL);
|
||||
ft->line_id = self->chatwin->hst->line_end->id + 2;
|
||||
@ -443,15 +447,16 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TOX_FILE_CONTROL_PAUSE:
|
||||
}
|
||||
case TOX_FILE_CONTROL_PAUSE: {
|
||||
ft->state = FILE_TRANSFER_PAUSED;
|
||||
break;
|
||||
|
||||
case TOX_FILE_CONTROL_CANCEL:
|
||||
}
|
||||
case TOX_FILE_CONTROL_CANCEL: {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' was aborted.", ft->file_name);
|
||||
close_file_transfer(self, m, ft, -1, msg, notif_error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,6 +484,8 @@ static bool chat_resume_broken_ft(ToxWindow *self, Tox *m, uint32_t friendnum, u
|
||||
|
||||
if (memcmp(ft->file_id, file_id, TOX_FILE_ID_LENGTH) == 0) {
|
||||
ft->filenum = filenum;
|
||||
ft->state = FILE_TRANSFER_STARTED;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
resuming = true;
|
||||
break;
|
||||
}
|
||||
@ -493,7 +500,6 @@ static bool chat_resume_broken_ft(ToxWindow *self, Tox *m, uint32_t friendnum, u
|
||||
if (!tox_file_control(m, ft->friendnum, ft->filenum, TOX_FILE_CONTROL_RESUME, NULL))
|
||||
goto on_error;
|
||||
|
||||
ft->state = FILE_TRANSFER_STARTED;
|
||||
return true;
|
||||
|
||||
on_error:
|
||||
@ -512,7 +518,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
|
||||
if (chat_resume_broken_ft(self, m, friendnum, filenum))
|
||||
return;
|
||||
|
||||
struct FileTransfer *ft = get_new_file_receiver(friendnum);
|
||||
struct FileTransfer *ft = new_file_transfer(self, friendnum, filenum, FILE_TRANSFER_RECV, TOX_FILE_KIND_DATA);
|
||||
|
||||
if (!ft) {
|
||||
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
|
||||
@ -570,12 +576,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", ft->index);
|
||||
|
||||
ft->state = FILE_TRANSFER_PENDING;
|
||||
ft->direction = FILE_TRANSFER_RECV;
|
||||
ft->file_size = file_size;
|
||||
ft->friendnum = friendnum;
|
||||
ft->filenum = filenum;
|
||||
ft->file_type = TOX_FILE_KIND_DATA;
|
||||
snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path);
|
||||
snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
|
||||
tox_file_get_file_id(m, friendnum, filenum, ft->file_id, NULL);
|
||||
|
@ -181,7 +181,7 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
|
||||
/* prep progress bar line */
|
||||
char progline[MAX_STR_SIZE];
|
||||
prep_prog_line(progline);
|
||||
init_progress_bar(progline);
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
|
||||
|
||||
ft->line_id = self->chatwin->hst->line_end->id + 2;
|
||||
@ -263,7 +263,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
if (err != TOX_ERR_FILE_SEND_OK)
|
||||
goto on_send_error;
|
||||
|
||||
struct FileTransfer *ft = get_new_file_sender(self->num);
|
||||
struct FileTransfer *ft = new_file_transfer(self, self->num, filenum, FILE_TRANSFER_SEND, TOX_FILE_KIND_DATA);
|
||||
|
||||
if (!ft) {
|
||||
err = TOX_ERR_FILE_SEND_TOO_MANY;
|
||||
@ -271,13 +271,8 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
}
|
||||
|
||||
memcpy(ft->file_name, file_name, namelen + 1);
|
||||
ft->state = FILE_TRANSFER_PENDING;
|
||||
ft->file = file_to_send;
|
||||
ft->file_size = filesize;
|
||||
ft->filenum = filenum;
|
||||
ft->friendnum = self->num;
|
||||
ft->direction = FILE_TRANSFER_SEND;
|
||||
ft->file_type = TOX_FILE_KIND_DATA;
|
||||
tox_file_get_file_id(m, self->num, filenum, ft->file_id, NULL);
|
||||
|
||||
char sizestr[32];
|
||||
|
@ -35,11 +35,52 @@
|
||||
|
||||
extern FriendsList Friends;
|
||||
|
||||
#define NUM_PROG_MARKS 50 /* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */
|
||||
/* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */
|
||||
#define NUM_PROG_MARKS 50
|
||||
|
||||
/* Checks for timed out file transfers and closes them. */
|
||||
#define CHECK_FILE_TIMEOUT_INTERAVAL 5
|
||||
void check_file_transfer_timeouts(Tox *m)
|
||||
{
|
||||
char msg[MAX_STR_SIZE];
|
||||
static uint64_t last_check = 0;
|
||||
|
||||
if (!timed_out(last_check, CHECK_FILE_TIMEOUT_INTERAVAL))
|
||||
return;
|
||||
|
||||
last_check = get_unix_time();
|
||||
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < Friends.max_idx; ++i) {
|
||||
if (!Friends.list[i].active)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MAX_FILES; ++j) {
|
||||
struct FileTransfer *ft_send = &Friends.list[i].file_sender[j];
|
||||
|
||||
if (ft_send->state > FILE_TRANSFER_PAUSED) {
|
||||
if (timed_out(ft_send->last_keep_alive, TIMEOUT_FILESENDER)) {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", ft_send->file_name);
|
||||
close_file_transfer(ft_send->window, m, ft_send, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
|
||||
}
|
||||
}
|
||||
|
||||
struct FileTransfer *ft_recv = &Friends.list[i].file_receiver[j];
|
||||
|
||||
if (ft_recv->state > FILE_TRANSFER_PAUSED) {
|
||||
if (timed_out(ft_recv->last_keep_alive, TIMEOUT_FILESENDER)) {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", ft_recv->file_name);
|
||||
close_file_transfer(ft_recv->window, m, ft_recv, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* creates initial progress line that will be updated during file transfer.
|
||||
Assumes progline is of size MAX_STR_SIZE */
|
||||
void prep_prog_line(char *progline)
|
||||
void init_progress_bar(char *progline)
|
||||
{
|
||||
strcpy(progline, "0.0 B/s [");
|
||||
int i;
|
||||
@ -80,13 +121,13 @@ void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t l
|
||||
line_info_set(self, line_id, msg);
|
||||
}
|
||||
|
||||
static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)
|
||||
static void refresh_progress_helper(ToxWindow *self, Tox *m, struct FileTransfer *ft)
|
||||
{
|
||||
if (ft->state == FILE_TRANSFER_INACTIVE)
|
||||
return;
|
||||
|
||||
/* Timeout must be set to 1 second to show correct bytes per second */
|
||||
if (!timed_out(ft->last_progress, 1))
|
||||
if (!timed_out(ft->last_line_progress, 1))
|
||||
return;
|
||||
|
||||
double remain = ft->file_size - ft->position;
|
||||
@ -94,17 +135,17 @@ static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)
|
||||
print_progress_bar(self, ft->bps, pct_done, ft->line_id);
|
||||
|
||||
ft->bps = 0;
|
||||
ft->last_progress = get_unix_time();
|
||||
ft->last_line_progress = get_unix_time();
|
||||
}
|
||||
|
||||
/* refreshes active file receiver status bars for friendnum */
|
||||
/* refreshes active file transfer status bars. */
|
||||
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_FILES; ++i) {
|
||||
refresh_progress_helper(self, &Friends.list[friendnum].file_receiver[i]);
|
||||
refresh_progress_helper(self, &Friends.list[friendnum].file_sender[i]);
|
||||
refresh_progress_helper(self, m, &Friends.list[friendnum].file_receiver[i]);
|
||||
refresh_progress_helper(self, m, &Friends.list[friendnum].file_sender[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +197,7 @@ struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t
|
||||
/* Returns a pointer to an unused file sender.
|
||||
* Returns NULL if all file senders are in use.
|
||||
*/
|
||||
struct FileTransfer *get_new_file_sender(uint32_t friendnum)
|
||||
static struct FileTransfer *new_file_sender(ToxWindow *window, uint32_t friendnum, uint32_t filenum, uint8_t type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -164,7 +205,15 @@ struct FileTransfer *get_new_file_sender(uint32_t friendnum)
|
||||
struct FileTransfer *ft = &Friends.list[friendnum].file_sender[i];
|
||||
|
||||
if (ft->state == FILE_TRANSFER_INACTIVE) {
|
||||
memset(ft, 0, sizeof(struct FileTransfer));
|
||||
ft->window = window;
|
||||
ft->index = i;
|
||||
ft->friendnum = friendnum;
|
||||
ft->filenum = filenum;
|
||||
ft->file_type = type;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
ft->state = FILE_TRANSFER_PENDING;
|
||||
ft->direction = FILE_TRANSFER_SEND;
|
||||
return ft;
|
||||
}
|
||||
}
|
||||
@ -175,7 +224,7 @@ struct FileTransfer *get_new_file_sender(uint32_t friendnum)
|
||||
/* Returns a pointer to an unused file receiver.
|
||||
* Returns NULL if all file receivers are in use.
|
||||
*/
|
||||
struct FileTransfer *get_new_file_receiver(uint32_t friendnum)
|
||||
static struct FileTransfer *new_file_receiver(ToxWindow *window, uint32_t friendnum, uint32_t filenum, uint8_t type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -183,7 +232,15 @@ struct FileTransfer *get_new_file_receiver(uint32_t friendnum)
|
||||
struct FileTransfer *ft = &Friends.list[friendnum].file_receiver[i];
|
||||
|
||||
if (ft->state == FILE_TRANSFER_INACTIVE) {
|
||||
memset(ft, 0, sizeof(struct FileTransfer));
|
||||
ft->window = window;
|
||||
ft->index = i;
|
||||
ft->friendnum = friendnum;
|
||||
ft->filenum = filenum;
|
||||
ft->file_type = type;
|
||||
ft->last_keep_alive = get_unix_time();
|
||||
ft->state = FILE_TRANSFER_PENDING;
|
||||
ft->direction = FILE_TRANSFER_RECV;
|
||||
return ft;
|
||||
}
|
||||
}
|
||||
@ -191,6 +248,22 @@ struct FileTransfer *get_new_file_receiver(uint32_t friendnum)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initializes an unused file transfer and returns its pointer.
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
struct FileTransfer *new_file_transfer(ToxWindow *window, uint32_t friendnum, uint32_t filenum,
|
||||
FILE_TRANSFER_DIRECTION direction, uint8_t type)
|
||||
{
|
||||
if (direction == FILE_TRANSFER_RECV)
|
||||
return new_file_receiver(window, friendnum, filenum, type);
|
||||
|
||||
if (direction == FILE_TRANSFER_SEND)
|
||||
return new_file_sender(window, friendnum, filenum, type);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Closes file transfer ft.
|
||||
*
|
||||
* Set CTRL to -1 if we don't want to send a control signal.
|
||||
|
@ -38,9 +38,9 @@
|
||||
|
||||
typedef enum FILE_TRANSFER_STATE {
|
||||
FILE_TRANSFER_INACTIVE,
|
||||
FILE_TRANSFER_PAUSED,
|
||||
FILE_TRANSFER_PENDING,
|
||||
FILE_TRANSFER_STARTED,
|
||||
FILE_TRANSFER_PAUSED,
|
||||
} FILE_TRANSFER_STATE;
|
||||
|
||||
typedef enum FILE_TRANSFER_DIRECTION {
|
||||
@ -49,31 +49,36 @@ typedef enum FILE_TRANSFER_DIRECTION {
|
||||
} FILE_TRANSFER_DIRECTION;
|
||||
|
||||
struct FileTransfer {
|
||||
ToxWindow *window;
|
||||
FILE *file;
|
||||
FILE_TRANSFER_STATE state;
|
||||
FILE_TRANSFER_DIRECTION direction;
|
||||
uint8_t file_type;
|
||||
char file_name[TOX_MAX_FILENAME_LENGTH + 1];
|
||||
char file_path[PATH_MAX + 1]; /* Not used by senders */
|
||||
double bps;
|
||||
double bps;
|
||||
uint32_t filenum;
|
||||
uint32_t friendnum;
|
||||
size_t index;
|
||||
uint64_t file_size;
|
||||
uint64_t position;
|
||||
uint64_t last_progress;
|
||||
uint64_t last_line_progress; /* The last time we updated the progress bar */
|
||||
uint64_t last_keep_alive; /* The last time we sent or received data */
|
||||
uint32_t line_id;
|
||||
uint8_t file_id[TOX_FILE_ID_LENGTH];
|
||||
};
|
||||
|
||||
/* Checks for timed out file transfers and closes them. */
|
||||
void check_file_transfer_timeouts(Tox *m);
|
||||
|
||||
/* creates initial progress line that will be updated during file transfer.
|
||||
progline must be at lesat MAX_STR_SIZE bytes */
|
||||
void prep_prog_line(char *progline);
|
||||
void init_progress_bar(char *progline);
|
||||
|
||||
/* prints a progress bar for file transfers */
|
||||
void print_progress_bar(ToxWindow *self, double pct_done, double bps, uint32_t line_id);
|
||||
|
||||
/* refreshes active file transfer status bars for friendnum */
|
||||
/* refreshes active file transfer status bars. */
|
||||
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum);
|
||||
|
||||
/* Returns a pointer to friendnum's FileTransfer struct associated with filenum.
|
||||
@ -88,15 +93,11 @@ struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filen
|
||||
struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t index,
|
||||
FILE_TRANSFER_DIRECTION direction);
|
||||
|
||||
/* Returns a pointer to an unused file sender.
|
||||
* Returns NULL if all file senders are in use.
|
||||
/* Initializes an unused file transfer and returns its pointer.
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
struct FileTransfer *get_new_file_sender(uint32_t friendnum);
|
||||
|
||||
/* Returns a pointer to an unused file receiver.
|
||||
* Returns NULL if all file receivers are in use.
|
||||
*/
|
||||
struct FileTransfer *get_new_file_receiver(uint32_t friendnum);
|
||||
struct FileTransfer *new_file_transfer(ToxWindow *window, uint32_t friendnum, uint32_t filenum,
|
||||
FILE_TRANSFER_DIRECTION direction, uint8_t type);
|
||||
|
||||
/* Closes file transfer ft.
|
||||
*
|
||||
|
@ -780,6 +780,7 @@ static void do_toxic(Tox *m, ToxWindow *prompt)
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
tox_iterate(m);
|
||||
do_bootstrap(m);
|
||||
check_file_transfer_timeouts(m);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user