mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-22 21:33:02 +01:00
Fix file transfers breaking when friends go offline
This commit is contained in:
parent
f559bdabfe
commit
32e541bd1c
101
src/chat.c
101
src/chat.c
@ -188,8 +188,8 @@ static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, TOX_MESSAGE_TY
|
|||||||
return recv_action_helper(self, m, num, msg, len, nick, timefrmt);
|
return recv_action_helper(self, m, num, msg, len, nick, timefrmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_resume_file_transfers(Tox *m, uint32_t fnum);
|
static void chat_pause_file_transfers(Tox *m, uint32_t friendnum);
|
||||||
static void chat_stop_file_senders(Tox *m, uint32_t friendnum);
|
static void chat_resume_file_senders(ToxWindow *self, Tox *m, uint32_t fnum);
|
||||||
|
|
||||||
static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status)
|
static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status)
|
||||||
{
|
{
|
||||||
@ -209,7 +209,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_C
|
|||||||
if (connection_status != TOX_CONNECTION_NONE && statusbar->connection == TOX_CONNECTION_NONE) {
|
if (connection_status != TOX_CONNECTION_NONE && statusbar->connection == TOX_CONNECTION_NONE) {
|
||||||
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
|
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
|
||||||
? tox_friend_get_typing(m, num, NULL) : false;
|
? tox_friend_get_typing(m, num, NULL) : false;
|
||||||
chat_resume_file_transfers(m, num);
|
chat_resume_file_senders(self, m, num);
|
||||||
|
|
||||||
msg = "has come online";
|
msg = "has come online";
|
||||||
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
|
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
|
||||||
@ -220,7 +220,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_C
|
|||||||
if (self->chatwin->self_is_typing)
|
if (self->chatwin->self_is_typing)
|
||||||
set_self_typingstatus(self, m, 0);
|
set_self_typingstatus(self, m, 0);
|
||||||
|
|
||||||
chat_stop_file_senders(m, num);
|
chat_pause_file_transfers(m, num);
|
||||||
|
|
||||||
msg = "has gone offline";
|
msg = "has gone offline";
|
||||||
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
|
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
|
||||||
@ -277,17 +277,44 @@ static void chat_onReadReceipt(ToxWindow *self, Tox *m, uint32_t num, uint32_t r
|
|||||||
cqueue_remove(self, m, receipt);
|
cqueue_remove(self, m, receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stops active file senders for this friend. Call when a friend goes offline */
|
/* Stops active file transfers for this friend. Called when a friend goes offline */
|
||||||
static void chat_stop_file_senders(Tox *m, uint32_t friendnum)
|
static void chat_pause_file_transfers(Tox *m, uint32_t friendnum)
|
||||||
{
|
{
|
||||||
// TODO: core purges file transfers when a friend goes offline. Ideally we want to repair/resume
|
ToxicFriend *friend = &Friends.list[friendnum];
|
||||||
kill_all_file_transfers_friend(m, friendnum);
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_FILES; ++i) {
|
||||||
|
if (friend->file_sender[i].state >= FILE_TRANSFER_STARTED)
|
||||||
|
friend->file_sender[i].state = FILE_TRANSFER_PAUSED;
|
||||||
|
|
||||||
|
if (friend->file_receiver[i].state >= FILE_TRANSFER_STARTED)
|
||||||
|
friend->file_receiver[i].state = FILE_TRANSFER_PAUSED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tries to resume broken file transfers. Call when a friend comes online */
|
/* Tries to resume broken file senders. Called when a friend comes online */
|
||||||
static void chat_resume_file_transfers(Tox *m, uint32_t fnum)
|
static void chat_resume_file_senders(ToxWindow *self, Tox *m, uint32_t friendnum)
|
||||||
{
|
{
|
||||||
// TODO
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_FILES; ++i) {
|
||||||
|
struct FileTransfer *ft = &Friends.list[friendnum].file_sender[i];
|
||||||
|
|
||||||
|
if (ft->state != FILE_TRANSFER_PAUSED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TOX_ERR_FILE_SEND err;
|
||||||
|
ft->filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_DATA, ft->file_size, ft->file_id,
|
||||||
|
(uint8_t *) ft->file_name, strlen(ft->file_name), &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_FILE_SEND_OK) {
|
||||||
|
char msg[MAX_STR_SIZE];
|
||||||
|
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", ft->file_name);
|
||||||
|
close_file_transfer(self, m, ft, -1, msg, notif_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
|
static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
|
||||||
@ -428,12 +455,63 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Attempts to resume a broken inbound file transfer.
|
||||||
|
*
|
||||||
|
* Returns true if resume is successful.
|
||||||
|
*/
|
||||||
|
static bool chat_resume_broken_ft(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum)
|
||||||
|
{
|
||||||
|
char msg[MAX_STR_SIZE];
|
||||||
|
uint8_t file_id[TOX_FILE_ID_LENGTH];
|
||||||
|
|
||||||
|
if (!tox_file_get_file_id(m, friendnum, filenum, file_id, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool resuming = false;
|
||||||
|
struct FileTransfer *ft = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_FILES; ++i) {
|
||||||
|
ft = &Friends.list[friendnum].file_receiver[i];
|
||||||
|
|
||||||
|
if (ft->state == FILE_TRANSFER_INACTIVE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (memcmp(ft->file_id, file_id, TOX_FILE_ID_LENGTH) == 0) {
|
||||||
|
ft->filenum = filenum;
|
||||||
|
resuming = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resuming || !ft)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!tox_file_seek(m, ft->friendnum, ft->filenum, ft->position, NULL))
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if (!tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_RESUME, NULL))
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
ft->state = FILE_TRANSFER_STARTED;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", ft->file_name);
|
||||||
|
close_file_transfer(self, m, ft, -1, msg, notif_error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t file_size,
|
static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t file_size,
|
||||||
const char *filename, size_t name_length)
|
const char *filename, size_t name_length)
|
||||||
{
|
{
|
||||||
if (self->num != friendnum)
|
if (self->num != friendnum)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* first check if we need to resume a broken transfer */
|
||||||
|
if (chat_resume_broken_ft(self, m, friendnum, filenum))
|
||||||
|
return;
|
||||||
|
|
||||||
struct FileTransfer *ft = get_new_file_receiver(friendnum);
|
struct FileTransfer *ft = get_new_file_receiver(friendnum);
|
||||||
|
|
||||||
if (!ft) {
|
if (!ft) {
|
||||||
@ -500,6 +578,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
|
|||||||
ft->file_type = TOX_FILE_KIND_DATA;
|
ft->file_type = TOX_FILE_KIND_DATA;
|
||||||
snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path);
|
snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path);
|
||||||
snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
|
snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
|
||||||
|
tox_file_get_file_id(m, friendnum, filenum, ft->file_id, NULL);
|
||||||
|
|
||||||
if (self->active_box != -1)
|
if (self->active_box != -1)
|
||||||
box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box,
|
box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box,
|
||||||
|
@ -278,6 +278,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
|||||||
ft->friendnum = self->num;
|
ft->friendnum = self->num;
|
||||||
ft->direction = FILE_TRANSFER_SEND;
|
ft->direction = FILE_TRANSFER_SEND;
|
||||||
ft->file_type = TOX_FILE_KIND_DATA;
|
ft->file_type = TOX_FILE_KIND_DATA;
|
||||||
|
tox_file_get_file_id(m, self->num, filenum, ft->file_id, NULL);
|
||||||
|
|
||||||
char sizestr[32];
|
char sizestr[32];
|
||||||
bytes_convert_str(sizestr, sizeof(sizestr), filesize);
|
bytes_convert_str(sizestr, sizeof(sizestr), filesize);
|
||||||
|
@ -209,8 +209,6 @@ void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int C
|
|||||||
if (ft->file)
|
if (ft->file)
|
||||||
fclose(ft->file);
|
fclose(ft->file);
|
||||||
|
|
||||||
memset(ft, 0, sizeof(struct FileTransfer));
|
|
||||||
|
|
||||||
if (CTRL >= 0)
|
if (CTRL >= 0)
|
||||||
tox_file_control(m, ft->friendnum, ft->filenum, (TOX_FILE_CONTROL) CTRL, NULL);
|
tox_file_control(m, ft->friendnum, ft->filenum, (TOX_FILE_CONTROL) CTRL, NULL);
|
||||||
|
|
||||||
@ -222,6 +220,8 @@ void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int C
|
|||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", message);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(ft, 0, sizeof(struct FileTransfer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kills all active file transfers for friendnum */
|
/* Kills all active file transfers for friendnum */
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
|
||||||
#define KiB 1024
|
#define KiB 1024
|
||||||
#define MiB 1048576 /* 1024 ^ 2 */
|
#define MiB 1048576 /* 1024^2 */
|
||||||
#define GiB 1073741824 /* 1024 ^ 3 */
|
#define GiB 1073741824 /* 1024^3 */
|
||||||
|
|
||||||
#define MAX_FILES 32
|
#define MAX_FILES 32
|
||||||
#define TIMEOUT_FILESENDER 120
|
#define TIMEOUT_FILESENDER 120
|
||||||
@ -40,7 +40,7 @@ typedef enum FILE_TRANSFER_STATE {
|
|||||||
FILE_TRANSFER_INACTIVE,
|
FILE_TRANSFER_INACTIVE,
|
||||||
FILE_TRANSFER_PENDING,
|
FILE_TRANSFER_PENDING,
|
||||||
FILE_TRANSFER_STARTED,
|
FILE_TRANSFER_STARTED,
|
||||||
FILE_TRANSFER_PAUSED
|
FILE_TRANSFER_PAUSED,
|
||||||
} FILE_TRANSFER_STATE;
|
} FILE_TRANSFER_STATE;
|
||||||
|
|
||||||
typedef enum FILE_TRANSFER_DIRECTION {
|
typedef enum FILE_TRANSFER_DIRECTION {
|
||||||
@ -63,6 +63,7 @@ struct FileTransfer {
|
|||||||
uint64_t position;
|
uint64_t position;
|
||||||
uint64_t last_progress;
|
uint64_t last_progress;
|
||||||
uint32_t line_id;
|
uint32_t line_id;
|
||||||
|
uint8_t file_id[TOX_FILE_ID_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* creates initial progress line that will be updated during file transfer.
|
/* creates initial progress line that will be updated during file transfer.
|
||||||
|
Loading…
Reference in New Issue
Block a user