1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef UPDATER_THREAD_H
17#define UPDATER_THREAD_H
18
19#include <atomic>
20#include <functional>
21#include <thread>
22#include <file_utils.h>
23#include "curl/curl.h"
24
25#include "progress.h"
26
27namespace OHOS {
28namespace UpdateEngine {
29#define ENGINE_CHECK_NO_LOG(retCode, exper) \
30    if (!(retCode)) {                     \
31        exper;                            \
32    }
33
34constexpr uint32_t DOWNLOAD_FINISH_PERCENT = 100;
35constexpr uint32_t DOWNLOAD_PERIOD_PERCENT = 1;
36constexpr int32_t TIMEOUT_FOR_DOWNLOAD = 600;
37#ifndef UPDATER_UT
38constexpr int32_t TIMEOUT_FOR_CONNECT = 10;
39#else
40constexpr int32_t TIMEOUT_FOR_CONNECT = 1;
41#endif
42
43class ProgressThread {
44public:
45    ProgressThread() = default;
46    virtual ~ProgressThread();
47    static bool isNoNet_;
48    static bool isCancel_;
49protected:
50    int32_t StartProgress();
51    void StopProgress();
52    void QuitDownloadThread();
53    void ExecuteThreadFunc();
54
55    virtual bool ProcessThreadExecute() = 0;
56    virtual void ProcessThreadExit() = 0;
57
58private:
59    std::thread *pDealThread_ { nullptr };
60    std::mutex mutex_;
61    std::condition_variable condition_;
62    bool isWake_ = false;
63    bool isExitThread_ = false;
64};
65
66class DownloadThread : public ProgressThread {
67public:
68    using ProgressCallback = std::function<void (const std::string serverUrl, const std::string &fileName,
69        const Progress &progress)>;
70    explicit DownloadThread(ProgressCallback callback) : ProgressThread(), callback_(callback) {}
71    ~DownloadThread() override
72    {
73        ProgressThread::QuitDownloadThread();
74    }
75
76    int32_t StartDownload(const std::string &fileName, const std::string &url);
77    void StopDownload();
78
79    static size_t GetLocalFileLength(const std::string &fileName);
80    static size_t WriteFunc(void *ptr, size_t size, size_t nmemb, const void *stream);
81    static int32_t DownloadProgress(const void *localData,
82        double dlTotal, double dlNow, double ulTotal, double ulNow);
83
84    double GetPackageSize()
85    {
86        packageSize_ = GetLocalFileLength(downloadFileName_);
87        return static_cast<double>(packageSize_);
88    };
89
90protected:
91    bool ProcessThreadExecute() override;
92    void ProcessThreadExit() override;
93    int32_t DownloadCallback(uint32_t percent, UpgradeStatus status, const std::string &error);
94    static FILE* FileOpen(const std::string &fileName, const std::string &mode);
95
96private:
97    Progress downloadProgress_ {};
98    ProgressCallback callback_;
99    CURL *downloadHandle_ { nullptr };
100    FILE *downloadFile_ { nullptr };
101    std::string serverUrl_;
102    std::atomic<bool> exitDownload_ { false };
103    size_t packageSize_ { 1 };
104    std::string downloadFileName_;
105    bool DealAbnormal(uint32_t percent);
106};
107} // namespace UpdateEngine
108} // namespace OHOS
109#endif // UPDATER_THREAD_H
110