1/*
2 * Copyright (C) 2024-2024 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#include <arpa/inet.h>
17#include <cstring>
18#include <fcntl.h>
19#include <fstream>
20#include <future>
21#include <list>
22#include <memory>
23#include <netdb.h>
24#include <regex>
25#include <securec.h>
26#include <sys/socket.h>
27#include <thread>
28#include <pthread.h>
29#include <unistd.h>
30
31#include "probe_thread.h"
32#include "dns_config_client.h"
33#include "event_report.h"
34#include "fwmark_client.h"
35#include "netmanager_base_common_utils.h"
36#include "netsys_controller.h"
37#include "net_http_proxy_tracker.h"
38#include "net_mgr_log_wrapper.h"
39#include "net_manager_constants.h"
40
41namespace OHOS {
42namespace NetManagerStandard {
43
44static void NetProbeThread(const std::shared_ptr<ProbeThread> &probeThread)
45{
46    if (probeThread == nullptr) {
47        NETMGR_LOG_E("probeThread is nullptr");
48        return;
49    }
50    ProbeType type = probeThread->GetProbeType();
51    probeThread->SendHttpProbe(type);
52}
53
54ProbeThread::ProbeThread(uint32_t netId, NetBearType bearType, const NetLinkInfo &netLinkInfo,
55    std::shared_ptr<TinyCountDownLatch> latch, std::shared_ptr<TinyCountDownLatch> latchAll,
56    ProbeType probeType, std::string httpUrl, std::string httpsUrl)
57    : netId_(netId), probeType_(probeType), latch_(latch), latchAll_(latchAll), httpProbeUrl_(httpUrl),
58    httpsProbeUrl_(httpsUrl)
59{
60    httpProbe_ = std::make_unique<NetHttpProbe>(netId, bearType, netLinkInfo);
61}
62
63ProbeThread::~ProbeThread()
64{
65    if (thread_.joinable()) {
66        thread_.join();
67    }
68}
69
70void ProbeThread::Start()
71{
72    NETMGR_LOG_D("Start net[%{public}d] monitor in", netId_);
73    isDetecting_ = true;
74    std::shared_ptr<ProbeThread> probeThead = shared_from_this();
75    thread_ = std::thread([probeThead] { return NetProbeThread(probeThead);});
76    std::string threadName = "netDetectThread";
77    pthread_setname_np(thread_.native_handle(), threadName.c_str());
78    thread_.detach();
79}
80
81void ProbeThread::SendHttpProbe(ProbeType probeType)
82{
83    if (httpProbeUrl_.empty() || httpsProbeUrl_.empty()) {
84        NETMGR_LOG_E("Net:[%{public}d] httpProbeUrl is empty", netId_);
85        isDetecting_ = false;
86        latch_->CountDown();
87        latchAll_->CountDown();
88        return;
89    }
90
91    if (httpProbe_ == nullptr) {
92        NETMGR_LOG_E("Net:[%{public}d] httpProbe_ is nullptr", netId_);
93        isDetecting_ = false;
94        latch_->CountDown();
95        latchAll_->CountDown();
96        return;
97    }
98
99    if (httpProbe_->SendProbe(probeType, httpProbeUrl_, httpsProbeUrl_) != NETMANAGER_SUCCESS) {
100        NETMGR_LOG_E("Net:[%{public}d] send probe failed.", netId_);
101        isDetecting_ = false;
102        latch_->CountDown();
103        latchAll_->CountDown();
104        return;
105    }
106
107    if (IsConclusiveResult()) {
108        isDetecting_ = false;
109        while (latch_->GetCount() > 0) {
110            latch_->CountDown();
111        }
112        while (latchAll_->GetCount() > 0) {
113            latchAll_->CountDown();
114        }
115    }
116    isDetecting_ = false;
117    if (latch_->GetCount() > 0) {
118        latch_->CountDown();
119    }
120    if (latchAll_->GetCount() > 0) {
121        latchAll_->CountDown();
122    }
123}
124
125bool ProbeThread::IsConclusiveResult()
126{
127    if (httpProbe_->HasProbeType(probeType_, ProbeType::PROBE_HTTP) &&
128        httpProbe_->GetHttpProbeResult().IsNeedPortal()) {
129        NETMGR_LOG_I("http url detection result: portal");
130        return true;
131    }
132    if (httpProbe_->HasProbeType(probeType_, ProbeType::PROBE_HTTPS) &&
133        httpProbe_->GetHttpsProbeResult().IsSuccessful()) {
134        NETMGR_LOG_I("https url detection result: success");
135        return true;
136    }
137    return false;
138}
139
140void ProbeThread::UpdateGlobalHttpProxy(const HttpProxy &httpProxy)
141{
142    if (httpProbe_) {
143        httpProbe_->UpdateGlobalHttpProxy(httpProxy);
144    }
145}
146
147void ProbeThread::ProbeWithoutGlobalHttpProxy()
148{
149    httpProbe_->ProbeWithoutGlobalHttpProxy();
150}
151
152NetHttpProbeResult ProbeThread::GetHttpProbeResult()
153{
154    return httpProbe_->GetHttpProbeResult();
155}
156
157NetHttpProbeResult ProbeThread::GetHttpsProbeResult()
158{
159    return httpProbe_->GetHttpsProbeResult();
160}
161
162bool ProbeThread::IsDetecting()
163{
164    return isDetecting_.load();
165}
166
167ProbeType ProbeThread::GetProbeType()
168{
169    return probeType_;
170}
171
172}
173}