[Network] and [Kernel] add Cancel for downloader (windows)

This commit is contained in:
Vladimir Gorshenkov
2022-01-22 20:04:48 +03:00
parent 920adde65f
commit d997dae36c
11 changed files with 261 additions and 82 deletions

View File

@ -59,8 +59,8 @@ namespace NSNetwork
m_sResponse = L"";
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_func_onComplete = nullptr;
m_func_onProgress = nullptr;
m_bIsExit = nullptr;
}
@ -82,8 +82,8 @@ namespace NSNetwork
m_sResponse = L"";
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_func_onComplete = nullptr;
m_func_onProgress = nullptr;
m_bIsExit = nullptr;
}
@ -105,8 +105,8 @@ namespace NSNetwork
m_sResponse = L"";
m_func_onComplete = NULL;
m_func_onProgress = NULL;
m_func_onComplete = nullptr;
m_func_onProgress = nullptr;
m_bIsExit = nullptr;
}
@ -118,6 +118,7 @@ namespace NSNetwork
NSFile::CFileBinary::Remove(m_sDownloadFilePath);
m_sDownloadFilePath = L"";
}
m_bIsExit = nullptr;
}
virtual int DownloadFile() = 0;

View File

@ -32,7 +32,6 @@
#include "FileTransporter_private.h"
#include <wininet.h>
#pragma comment(lib, "Wininet")
#pragma comment(lib, "Ole32.lib")
@ -90,8 +89,15 @@ namespace NSNetwork
CoInitialize ( NULL );
if ( /*S_OK != _DownloadFile ( m_sFileUrl )*/TRUE )
{
DeleteUrlCacheEntry(m_sDownloadFileUrl.c_str());
HRESULT hrResultAll = DownloadFileAll(m_sDownloadFileUrl, m_sDownloadFilePath);
if(E_ABORT == hrResultAll && m_bIsExit->load())
{
//DeleteUrlCacheEntry(m_sDownloadFileUrl.c_str());
CoUninitialize ();
return hrResultAll;
}
if (S_OK != hrResultAll)
{
hrResultAll = (true == DownloadFilePS(m_sDownloadFileUrl, m_sDownloadFilePath)) ? S_OK : S_FALSE;
@ -369,15 +375,11 @@ namespace NSNetwork
m_pFile = NULL;
}
if(m_func_onProgress)
{
DownloadProgress progress;
progress.func_onProgress = m_func_onProgress;
// Скачиваем файл с возвратом процентов состояния
return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, static_cast<IBindStatusCallback*>(&progress));
}
else
return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, NULL);
DownloadProgress progress;
progress.bIsExit = m_bIsExit;
progress.func_onProgress = m_func_onProgress;
// Скачиваем файл с возвратом процентов состояния
return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, static_cast<IBindStatusCallback*>(&progress));
}
class DownloadProgress : public IBindStatusCallback {
@ -415,6 +417,10 @@ namespace NSNetwork
virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
if(bIsExit && bIsExit->load())
{
return E_ABORT;
}
if(ulProgressMax != 0)
{
int percent = static_cast<int>((100.0 * ulProgress) / ulProgressMax);
@ -424,7 +430,8 @@ namespace NSNetwork
return S_OK;
}
std::function<void(int)> func_onProgress;
std::atomic<bool>* bIsExit = nullptr;
std::function<void(int)> func_onProgress = nullptr;
};
bool DownloadFilePS(const std::wstring& sFileURL, const std::wstring& strFileOutput)

View File

@ -46,9 +46,7 @@
namespace NSNetwork
{
namespace NSFileTransport
{
pid_t pid;
std::atomic<bool>* m_isExit;
{
std::string wget_url_validate(const std::string& url)
{
std::string::size_type pos = 0;
@ -63,8 +61,8 @@ namespace NSNetwork
int download_external(const std::wstring& sUrl, const std::wstring& sOutput, std::function<void(int)> func_onProgress, std::atomic<bool>* isExit)
{
pid_t pid;
int nReturnCode = -1;
m_isExit = isExit;
std::string sUrlA = U_TO_UTF8(sUrl);
//sUrlA =("\"" + sUrlA + "\"");
std::string sOutputA = U_TO_UTF8(sOutput);
@ -134,7 +132,7 @@ namespace NSNetwork
while (1)
{
if(m_isExit->load())
if(isExit && isExit->load())
{
kill(pid, SIGTERM);
//while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
@ -168,7 +166,7 @@ namespace NSNetwork
int waitres;
while (1) // wait for child to complete
{
if(m_isExit->load())
if(isExit && isExit->load())
{
kill(pid, SIGTERM);
return nReturnCode;
@ -222,7 +220,7 @@ namespace NSNetwork
int waitres;
while (1) // wait for child to complete
{
if(m_isExit->load())
if(isExit && isExit->load())
{
kill(pid, SIGTERM);
return nReturnCode;

View File

@ -155,7 +155,7 @@ namespace NSThreads
m_lThreadPriority = 0;
m_bIsNeedDestroy = false;
m_bIsExit = new std::atomic<bool>(false);
m_bIsExit = nullptr;
}
CBaseThread::~CBaseThread()
{
@ -172,7 +172,7 @@ namespace NSThreads
m_bRunThread = TRUE;
m_bIsExit->exchange(false);
m_bIsExit = new std::atomic<bool>(false);
#if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
DWORD dwTemp;
((__native_thread*)m_hThread)->m_thread = CreateThread(NULL, 0, &__ThreadProc, (void*)this, 0, &dwTemp);
@ -197,11 +197,13 @@ namespace NSThreads
m_bRunThread = FALSE;
Join();
RELEASEOBJECT(m_bIsExit);
RELEASEOBJECT(m_hThread);
}
void CBaseThread::StopNoJoin()
{
m_bRunThread = FALSE;
RELEASEOBJECT(m_bIsExit);
RELEASEOBJECT(m_hThread);
}
void CBaseThread::DestroyOnFinish()
@ -241,12 +243,10 @@ namespace NSThreads
m_bIsExit->exchange(true);
#if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
//WaitForSingleObject(((__native_thread*)m_hThread)->m_thread, INFINITE);
#else
//pthread_cancel(((__native_thread*)m_hThread)->m_thread);
//pthread_kill(((__native_thread*)m_hThread)->m_thread, SIGUSR1);
pthread_join(((__native_thread*)m_hThread)->m_thread, 0);
#endif
m_bRunThread = FALSE;
Join();
RELEASEOBJECT(m_bIsExit);
RELEASEOBJECT(m_hThread);
}
}

View File

@ -59,7 +59,7 @@ namespace NSThreads
class KERNEL_DECL CBaseThread
{
protected:
CThreadDescriptor* m_hThread;
CThreadDescriptor* m_hThread;
INT m_bRunThread;
INT m_bSuspend;

View File

@ -1,23 +0,0 @@
QT -= gui
TEMPLATE = app
CONFIG += c++11 console
CONFIG -= app_bundle
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
include(TestDownloader.pri)
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

View File

@ -1,16 +1,14 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-10-03T18:30:31
#
#-------------------------------------------------
QT += core gui
QT -= core
QT -= gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CORE_ROOT_DIR = $$PWD/../../..
CONFIG += c++11
#CONFIG += console
CORE_ROOT_DIR = $$PWD/../../../../core
PWD_ROOT_DIR = $$PWD
include(../../../Common/base.pri)
include($$CORE_ROOT_DIR/Common/base.pri)
core_windows {
QMAKE_LFLAGS += /INCREMENTAL:NO
@ -21,8 +19,9 @@ core_windows {
DEFINES += KERNEL_USE_DYNAMIC_LIBRARY
core_windows {
DEFINES += _RWSTD_NO_SETRLIMIT
DEFINES += _RWSTD_NO_SETRLIMIT
}
#CORE_BUILDS_LIBRARIES_PATH = $$CORE_ROOT_DIR/build/lib/linux_64/debug #linux
CORE_BUILDS_LIBRARIES_PATH = $$CORE_ROOT_DIR/build/lib/win_64/debug #windows
#kernel
@ -36,10 +35,26 @@ LIBS += -L$$CORE_BUILDS_LIBRARIES_PATH -lkernel_network
#BOOST
CONFIG += core_boost_regex
include($$PWD/../../../Common/3dParty/boost/boost.pri)
include($$CORE_ROOT_DIR/Common/3dParty/boost/boost.pri)
core_windows {
LIBS += -lAdvapi32
}
########################################################
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

View File

@ -1,17 +1,11 @@
#include "../../../Common/Network/FileTransporter/include/FileTransporter.h"
#define CHECK_URL L"http://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/updates/editors_update_x64.exe"
typedef NSNetwork::NSFileTransport::CFileDownloader Downloader;
#include <vector>
//int wmain(int argc, wchar_t *argv[]) windows
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
auto check_url = CHECK_URL;
auto downloader = new Downloader(check_url, false);
std::vector<int> vec;
downloader->SetEvent_OnProgress([&](int percent) {
vec.push_back(percent);
});
downloader->SetFilePath(L"/mnt/HDD_DATA/Work/core/Test/Applications/TestDownloader/tmp.exe");
//downloader->SetFilePath(L"C:\\Users\\Vladimir.Gorshenkov\\Downloads\\tmp.exe"); windows
downloader->DownloadSync();
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

View File

@ -0,0 +1,79 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#include <functional>
#define URL L"http://download.onlyoffice.com/install/desktop/editors/windows/onlyoffice/updates/editors_update_x64.exe"
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
downloader = new Downloader(URL, false);
downloader->SetEvent_OnComplete(std::bind(&MainWindow::onLoadUpdateFinished, this, std::placeholders::_1));
downloader->SetEvent_OnProgress(std::bind(&MainWindow::onProgress, this, std::placeholders::_1));
}
MainWindow::~MainWindow()
{
delete downloader;
delete ui;
}
void MainWindow::onProgress(const int percent)
{
qDebug() << "Precent... " << percent;
QMetaObject::invokeMethod(this, "onProgressSlot", Qt::QueuedConnection, Q_ARG(int, percent));
}
void MainWindow::onProgressSlot(int percent)
{
ui->textEdit->setText(QString::number(percent));
ui->progressBar->setValue(percent);
}
void MainWindow::onLoadUpdateFinished(int error)
{
qDebug() << "Loading finished...";
QMetaObject::invokeMethod(this, "onLoadFinishedSlot", Qt::QueuedConnection, Q_ARG(int, error));
}
void MainWindow::onLoadFinishedSlot(int error)
{
if (error == 0) {
ui->textEdit->setText("Loading finished...");
} else {
qDebug() << "Download error: " << error;
ui->textEdit->setText("Download error");
}
const QString path = QString::fromStdWString(downloader->GetFilePath());
if (QDir().exists(path)) QDir().remove(path);
}
void MainWindow::on_buttonStart_clicked()
{
qDebug() << "Start loading...";
ui->progressBar->setValue(0);
// const QString tmp_file = QDir::tempPath() + QDir::separator() + QString("temp.tmp");
const QString tmp_file = QString("C:\\Users\\Vladimir.Gorshenkov\\NewControl\\core\\Test\\Applications\\TestDownloader\\temp.tmp");
ui->textEdit->setText(QString("Start loading: %1 to %2").arg(QString::fromStdWString(URL), tmp_file));
downloader->SetFilePath(tmp_file.toStdWString());
downloader->Start(0);
}
void MainWindow::on_buttonCancel_clicked()
{
qDebug() << "Loading cancel...";
ui->progressBar->setValue(0);
ui->textEdit->setText("Loading cancel...");
const QString path = QString::fromStdWString(downloader->GetFilePath());
downloader->Cancel();
// if (QDir().exists(path)) QDir().remove(path);
qDebug() << "Stop finished";
}

View File

@ -0,0 +1,46 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDir>
#include <QDebug>
#include "../../../../core/Common/Network/FileTransporter/include/FileTransporter.h"
//#define URL L"http://nct.onlyoffice.com/sh/XHh"
typedef std::wstring WString;
typedef NSNetwork::NSFileTransport::CFileDownloader Downloader;
QT_BEGIN_NAMESPACE
namespace Ui {class MainWindow;}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_buttonStart_clicked();
void on_buttonCancel_clicked();
void onProgressSlot(int percent);
void onLoadFinishedSlot(int error);
private:
void onProgress(const int percent);
void onLoadUpdateFinished(int error);
Downloader *downloader;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>616</width>
<height>479</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="buttonStart">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="buttonCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QTextEdit" name="textEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>616</width>
<height>19</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>