2
0
mirror of https://github.com/ars3niy/tdlib-purple synced 2025-08-30 13:37:45 +00:00

Finished downloads using PurpleXfer

This commit is contained in:
Arseniy Lartsev
2020-08-15 12:05:50 +02:00
parent 8c7783d30b
commit 42894f2e64
6 changed files with 159 additions and 10 deletions

View File

@@ -133,6 +133,7 @@ static void nop(PurpleXfer *xfer)
static void cancelDownload(PurpleXfer *xfer) static void cancelDownload(PurpleXfer *xfer)
{ {
std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(xfer->data)); std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(xfer->data));
xfer->data = NULL;
if (!data) return; if (!data) return;
int32_t fileId; int32_t fileId;
@@ -212,7 +213,7 @@ static void updateDownloadProgress(const td::td_api::file &file, PurpleXfer *xfe
if (downloadReq->tempFd >= 0) if (downloadReq->tempFd >= 0)
close(downloadReq->tempFd); close(downloadReq->tempFd);
downloadReq->tempFd = -1; downloadReq->tempFd = -1;
//!!!! if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED)
purple_xfer_start(xfer, -1, NULL, 0); purple_xfer_start(xfer, -1, NULL, 0);
} }
@@ -244,6 +245,7 @@ void finishInlineDownloadProgress(DownloadRequest &downloadReq, TdAccountData& a
if (account.getFileTransfer(downloadReq.fileId, download, chatId)) { if (account.getFileTransfer(downloadReq.fileId, download, chatId)) {
std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(download->data)); std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(download->data));
download->data = NULL;
purple_xfer_set_bytes_sent(download, downloadReq.fileSize); purple_xfer_set_bytes_sent(download, downloadReq.fileSize);
purple_xfer_set_completed(download, TRUE); purple_xfer_set_completed(download, TRUE);
purple_xfer_end(download); purple_xfer_end(download);
@@ -291,6 +293,8 @@ static void standardDownloadResponse(TdAccountData *account, uint64_t requestId,
if (account->getFileTransfer(request->fileId, download, chatId)) { if (account->getFileTransfer(request->fileId, download, chatId)) {
std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(download->data)); std::unique_ptr<DownloadData> data(static_cast<DownloadData *>(download->data));
download->data = NULL;
gchar *content = NULL; gchar *content = NULL;
gsize fileSize = 0; gsize fileSize = 0;
GError *error = NULL; GError *error = NULL;
@@ -306,12 +310,18 @@ static void standardDownloadResponse(TdAccountData *account, uint64_t requestId,
purple_xfer_end(download); purple_xfer_end(download);
} }
purple_xfer_unref(download); purple_xfer_unref(download);
// !!!! account->removeFileTransfer(request->fileId); account->removeFileTransfer(request->fileId);
} else { } else {
if (error) { if (error) {
purple_xfer_error(PURPLE_XFER_RECEIVE, account->purpleAccount, download->who, error->message); // Unlikely error message not worth translating
std::string message = formatMessage("Failed to read {}: {}", {path, std::string(error->message)});
purple_debug_misc(config::pluginId, "%s\n", message.c_str());
purple_xfer_error(PURPLE_XFER_RECEIVE, account->purpleAccount, download->who, message.c_str());
g_error_free(error); g_error_free(error);
} }
if (path.empty())
purple_debug_warning(config::pluginId, "Incomplete file in download response for %s\n",
purple_xfer_get_local_filename(download));
purple_xfer_cancel_remote(download); purple_xfer_cancel_remote(download);
} }
@@ -345,7 +355,7 @@ static void startStandardDownload(PurpleXfer *xfer)
data->account->addPendingRequest<DownloadRequest>(requestId, std::move(request)); data->account->addPendingRequest<DownloadRequest>(requestId, std::move(request));
// Start immediately, because standardDownloadResponse will call purple_xfer_write_file, which // Start immediately, because standardDownloadResponse will call purple_xfer_write_file, which
// will fail if purple_xfer_start hasn't been called // will fail if purple_xfer_start hasn't been called
// !!!! purple_xfer_start(xfer, -1, NULL, 0); purple_xfer_start(xfer, -1, NULL, 0);
} }
} }

View File

@@ -907,11 +907,13 @@ TEST_F(FileTransferTest, SendFileToNonContact_TurboCancel)
)); ));
} }
TEST_F(FileTransferTest, ReceiveDocument_StandardTransfer) TEST_F(FileTransferTest, ReceiveDocument_StandardTransfer_TinyFile)
{ {
const int64_t messageId = 1; const int64_t messageId = 1;
const int32_t date = 10001; const int32_t date = 10001;
const int32_t fileId = 1234; const int32_t fileId = 1234;
uint8_t data[] = {1, 2, 3, 4, 5};
const char *outputFileName = ".test_download";
setUiName("spectrum"); // No longer pidgin - now downloads will use libpurple transfers setUiName("spectrum"); // No longer pidgin - now downloads will use libpurple transfers
loginWithOneContact(); loginWithOneContact();
@@ -943,9 +945,117 @@ TEST_F(FileTransferTest, ReceiveDocument_StandardTransfer)
XferRequestEvent(PURPLE_XFER_RECEIVE, "doc.file.name") XferRequestEvent(PURPLE_XFER_RECEIVE, "doc.file.name")
); );
purple_xfer_request_accepted(prpl.getLastXfer(), ".test_download"); purple_xfer_request_accepted(prpl.getLastXfer(), outputFileName);
prpl.verifyEvents( prpl.verifyEvents(
XferAcceptedEvent(".test_download"), XferAcceptedEvent(outputFileName),
XferLocalCancelEvent(".test_download") XferStartEvent(outputFileName)
); );
tgl.verifyRequest(downloadFile(fileId, 1, 0, 0, true));
char *tdlibFileName = NULL;
int fd = g_file_open_tmp("tdlib_test_XXXXXX", &tdlibFileName, NULL);
ASSERT_TRUE(fd >= 0);
ASSERT_EQ((ssize_t)sizeof(data), write(fd, data, sizeof(data)));
::close(fd);
tgl.reply(make_object<file>(
fileId, 10000, 10000,
make_object<localFile>(tdlibFileName, true, true, false, true, 0, 10000, 10000),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
));
tgl.update(make_object<file>(
fileId, 10000, 10000,
make_object<localFile>(tdlibFileName, true, true, false, true, 0, 10000, 10000),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
));
prpl.verifyEvents(
XferWriteFileEvent(outputFileName, data, sizeof(data)),
XferCompletedEvent(outputFileName, TRUE, sizeof(data)),
XferEndEvent(outputFileName)
);
remove(tdlibFileName);
g_free(tdlibFileName);
}
TEST_F(FileTransferTest, ReceiveDocument_StandardTransfer_Progress)
{
const int64_t messageId = 1;
const int32_t date = 10001;
const int32_t fileId = 1234;
uint8_t data[] = {1, 2, 3, 4, 5};
const char *outputFileName = ".test_download";
setUiName("spectrum"); // No longer pidgin - now downloads will use libpurple transfers
loginWithOneContact();
tgl.update(make_object<updateNewMessage>(makeMessage(
messageId,
userIds[0],
chatIds[0],
false,
date,
make_object<messageDocument>(
make_object<document>(
"doc.file.name", "mime/type", nullptr, nullptr,
make_object<file>(
fileId, 10000, 10000,
make_object<localFile>("", true, true, false, false, 0, 0, 0),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
)
),
make_object<formattedText>("document", std::vector<object_ptr<textEntity>>())
)
)));
tgl.verifyRequest(viewMessages(
chatIds[0],
std::vector<int64_t>(1, messageId),
true
));
prpl.verifyEvents(
XferRequestEvent(PURPLE_XFER_RECEIVE, "doc.file.name")
);
purple_xfer_request_accepted(prpl.getLastXfer(), outputFileName);
prpl.verifyEvents(
XferAcceptedEvent(outputFileName),
XferStartEvent(outputFileName)
);
tgl.verifyRequest(downloadFile(fileId, 1, 0, 0, true));
char *tdlibFileName = NULL;
int fd = g_file_open_tmp("tdlib_test_XXXXXX", &tdlibFileName, NULL);
ASSERT_TRUE(fd >= 0);
ASSERT_EQ((ssize_t)sizeof(data), write(fd, data, sizeof(data)));
::close(fd);
tgl.update(make_object<updateFile>(make_object<file>(
fileId, 10000, 10000,
make_object<localFile>(tdlibFileName, true, true, true, false, 0, 0, 2000),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
)));
prpl.verifyEvents(XferProgressEvent(outputFileName, 2000));
tgl.reply(make_object<file>(
fileId, 10000, 10000,
make_object<localFile>(tdlibFileName, true, true, false, true, 0, 10000, 10000),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
));
tgl.update(make_object<file>(
fileId, 10000, 10000,
make_object<localFile>(tdlibFileName, true, true, false, true, 0, 10000, 10000),
make_object<remoteFile>("beh", "bleh", false, true, 10000)
));
prpl.verifyEvents(
XferWriteFileEvent(outputFileName, data, sizeof(data)),
XferCompletedEvent(outputFileName, TRUE, sizeof(data)),
XferEndEvent(outputFileName)
);
remove(tdlibFileName);
g_free(tdlibFileName);
} }

View File

@@ -184,7 +184,7 @@ void checkFile(const char *filename, void *content, unsigned size)
gchar *actualContent; gchar *actualContent;
gsize actualSize; gsize actualSize;
ASSERT_TRUE(g_file_get_contents(filename, &actualContent, &actualSize, NULL)) << filename << " does not exist"; ASSERT_TRUE(g_file_get_contents(filename, &actualContent, &actualSize, NULL)) << filename << " does not exist";
ASSERT_EQ(actualSize, size); ASSERT_EQ(actualSize, size) << "Wrong file size for " << filename;
ASSERT_EQ(0, memcmp(content, actualContent, size)); ASSERT_EQ(0, memcmp(content, actualContent, size)) << "Wrong content for " << filename;
g_free(actualContent); g_free(actualContent);
} }

View File

@@ -1052,6 +1052,14 @@ size_t purple_xfer_get_size(const PurpleXfer *xfer)
gboolean gboolean
purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size) purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size)
{ {
if (xfer->status != PURPLE_XFER_STATUS_STARTED) {
purple_debug_misc("purple_xfer_write_file", "write_file requires a transfer in progress\n");
purple_xfer_cancel_local(xfer);
return FALSE;
}
EXPECT_LE(xfer->bytes_sent + size, xfer->size);
xfer->bytes_sent += size;
EVENT(XferWriteFileEvent, xfer->local_filename, buffer, size);
return TRUE; return TRUE;
} }

View File

@@ -276,6 +276,12 @@ static void compare(const XferRequestEvent &actual, const XferRequestEvent &expe
COMPARE(filename); COMPARE(filename);
} }
static void compare(const XferWriteFileEvent &actual, const XferWriteFileEvent &expected)
{
COMPARE(filename);
COMPARE(data);
}
static void compare(const RoomlistInProgressEvent &actual, const RoomlistInProgressEvent &expected) static void compare(const RoomlistInProgressEvent &actual, const RoomlistInProgressEvent &expected)
{ {
COMPARE(list); COMPARE(list);
@@ -345,6 +351,7 @@ static void compareEvents(const PurpleEvent &actual, const PurpleEvent &expected
C(XferLocalCancel) C(XferLocalCancel)
C(XferRemoteCancel) C(XferRemoteCancel)
C(XferRequest) C(XferRequest)
C(XferWriteFile)
C(RoomlistInProgress) C(RoomlistInProgress)
C(RoomlistAddRoom) C(RoomlistAddRoom)
default: default:
@@ -491,6 +498,7 @@ std::string PurpleEvent::toString() const
C(XferLocalCancel) C(XferLocalCancel)
C(XferRemoteCancel) C(XferRemoteCancel)
C(XferRequest) C(XferRequest)
C(XferWriteFile)
C(SetUserPhoto) C(SetUserPhoto)
C(RoomlistInProgress) C(RoomlistInProgress)
C(RoomlistAddRoom) C(RoomlistAddRoom)

View File

@@ -97,6 +97,7 @@ enum class PurpleEventType: uint8_t {
XferLocalCancel, XferLocalCancel,
XferRemoteCancel, XferRemoteCancel,
XferRequest, XferRequest,
XferWriteFile,
SetUserPhoto, SetUserPhoto,
RoomlistInProgress, RoomlistInProgress,
RoomlistAddRoom RoomlistAddRoom
@@ -507,6 +508,18 @@ struct XferRequestEvent: PurpleEvent {
filename(filename ? filename : "") {} filename(filename ? filename : "") {}
}; };
struct XferWriteFileEvent: PurpleEvent {
std::string filename;
std::vector<uint8_t> data;
XferWriteFileEvent(const char *filename, const uint8_t *content, unsigned size)
: PurpleEvent(PurpleEventType::XferWriteFile), filename(filename)
{
data.resize(size);
memmove(data.data(), content, size);
}
};
struct SetUserPhotoEvent: PurpleEvent { struct SetUserPhotoEvent: PurpleEvent {
PurpleAccount *account; PurpleAccount *account;
std::string username; std::string username;