From b870679f2ce749e2fa934b80c109a06ce6f82647 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 16 Aug 2014 17:20:53 -0400 Subject: [PATCH] allow resuming of broken file transfers (needs testing) --- src/chat.c | 59 ++++++++++++++++++++++++++++++++++++++++++++- src/chat_commands.c | 4 ++- src/dns.c | 3 ++- src/file_senders.c | 4 ++- src/file_senders.h | 1 + src/friendlist.h | 5 +++- 6 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/chat.c b/src/chat.c index 1917a7f..441f543 100644 --- a/src/chat.c +++ b/src/chat.c @@ -176,6 +176,9 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg } +static void chat_resume_file_transfers(Tox *m, int fnum); +static void chat_stop_file_senders(int fnum); + static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) { if (self->num != num) @@ -187,13 +190,15 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_ statusbar->is_online = true; Friends.list[num].is_typing = user_settings_->show_typing_other == SHOW_TYPING_ON ? tox_get_is_typing(m, num) : 0; - + chat_resume_file_transfers(m, num); } else { /* Friend goes offline */ statusbar->is_online = false; Friends.list[num].is_typing = 0; if (self->chatwin->self_is_typing) set_self_typingstatus(self, m, 0); + + chat_stop_file_senders(num); } } @@ -350,6 +355,36 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t "Incoming file: %s", filename ); } +/* Stops active file senders for this friend. Call when a friend goes offline */ +static void chat_stop_file_senders(int fnum) +{ + int i; + + for (i = 0; i < MAX_FILES; ++i) { + if (file_senders[i].active && file_senders[i].friendnum == fnum) + file_senders[i].noconnection = true; + } +} + +/* Tries to resume broken file transfers. Call when a friend comes online */ +static void chat_resume_file_transfers(Tox *m, int fnum) +{ + if (Friends.list[fnum].active_file_receivers == 0) + return; + + int i; + + for (i = 0; i < MAX_FILES; ++i) { + if (Friends.list[fnum].file_receiver[i].active && !Friends.list[fnum].file_receiver[i].paused) { + uint8_t bytes_recv[sizeof(uint64_t)]; + memcpy(bytes_recv, &Friends.list[fnum].file_receiver[i].bytes_recv, sizeof(uint64_t)); + net_to_host(bytes_recv, sizeof(uint64_t)); + int filenum = Friends.list[fnum].file_receiver[i].filenum; + tox_file_send_control(m, fnum, 1, filenum, TOX_FILECONTROL_RESUME_BROKEN, bytes_recv, sizeof(uint64_t)); + } + } +} + /* set CTRL to -1 if we don't want to send a control signal. set msg to NULL if we don't want to display a message */ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL) @@ -363,6 +398,7 @@ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL) fclose(file); memset(&Friends.list[friendnum].file_receiver[filenum], 0, sizeof(struct FileReceiver)); + --Friends.list[friendnum].active_file_receivers; } static void close_all_file_receivers(Tox *m, int friendnum) @@ -453,6 +489,26 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec self->name, "%s", msg); break; + + case TOX_FILECONTROL_RESUME_BROKEN: + if (receive_send == 0) + break; + + FILE *fp = file_senders[i].file; + + if (fp == NULL) + break; + + uint8_t tmp[sizeof(uint64_t)]; + memcpy(tmp, &data, sizeof(uint64_t)); + net_to_host(tmp, sizeof(uint64_t)); + uint64_t datapos; + memcpy(&datapos, tmp, sizeof(uint64_t)); + + fseek(fp, datapos, SEEK_SET); + tox_file_send_control(m, num, 0, filenum, TOX_FILECONTROL_ACCEPT, 0, 0); + file_senders[i].noconnection = false; + break; } if (msg[0]) @@ -475,6 +531,7 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu } Friends.list[num].file_receiver[filenum].bps += length; + Friends.list[num].file_receiver[filenum].bytes_recv += length; double remain = (double) tox_file_data_remaining(m, num, filenum, 1); uint64_t curtime = get_unix_time(); diff --git a/src/chat_commands.c b/src/chat_commands.c index a2a57c2..7881d0f 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -177,13 +177,15 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv if ((Friends.list[self->num].file_receiver[filenum].file = fopen(filename, "a")) == NULL) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Error writing to file."); tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0); + } else { + Friends.list[self->num].file_receiver[filenum].active = true; + ++Friends.list[self->num].active_file_receivers; } } else { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed."); } Friends.list[self->num].file_receiver[filenum].pending = false; - Friends.list[self->num].file_receiver[filenum].active = true; } void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) diff --git a/src/dns.c b/src/dns.c index dff54c9..18346b7 100644 --- a/src/dns.c +++ b/src/dns.c @@ -44,13 +44,14 @@ #define DNS3_KEY_SIZE 32 #define MAX_DNS_REQST_SIZE 255 -#define NUM_DNS3_BACKUP_SERVERS 2 /* must correspond to number of items in dns3_servers array */ #define TOX_DNS3_TXT_PREFIX "v=tox3;id=" extern struct _Winthread Winthread; extern struct _dns3_servers dns3_servers; extern struct arg_opts arg_opts; +#define NUM_DNS3_BACKUP_SERVERS 2 + /* Hardcoded backup in case domain list is not loaded */ static struct dns3_server_backup { const char *name; diff --git a/src/file_senders.c b/src/file_senders.c index cee8d59..68f5a39 100644 --- a/src/file_senders.c +++ b/src/file_senders.c @@ -217,7 +217,9 @@ void do_file_senders(Tox *m) continue; } - send_file_data(self, m, i, friendnum, filenum, filename); + if (file_senders[i].noconnection == false) + send_file_data(self, m, i, friendnum, filenum, filename); + file_senders[i].queue_pos = num_active_file_senders - 1; } } diff --git a/src/file_senders.h b/src/file_senders.h index 47ad152..90c7e1f 100644 --- a/src/file_senders.h +++ b/src/file_senders.h @@ -40,6 +40,7 @@ typedef struct { ToxWindow *toxwin; int32_t friendnum; bool active; + bool noconnection; bool finished; int filenum; char nextpiece[FILE_PIECE_SIZE]; diff --git a/src/friendlist.h b/src/friendlist.h index 9d68230..7f54965 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -35,9 +35,11 @@ struct FileReceiver { FILE *file; bool pending; bool active; + bool paused; uint64_t size; + uint64_t bytes_recv; double bps; - uint64_t last_progress; + uint64_t last_progress; /* unix-time when we last updated progress */ uint32_t line_id; }; @@ -64,6 +66,7 @@ typedef struct { uint8_t status; struct LastOnline last_online; struct FileReceiver file_receiver[MAX_FILES]; + uint8_t active_file_receivers; } ToxicFriend; typedef struct {