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 #include "net_monitor.h"
16
17 #include "net_mgr_log_wrapper.h"
18
19 namespace OHOS {
20 namespace NetManagerStandard {
NetMonitor(NetDetectionStateHandler handle)21 NetMonitor::NetMonitor(NetDetectionStateHandler handle)
22 {
23 isExitNetMonitorThread_ = false;
24 isStopNetMonitor_ = true;
25 isExitNetMonitorThread_ = false;
26 netDetectionStatus_ = handle;
27 lastDetectionState_ = INVALID_DETECTION_STATE;
28 }
29
~NetMonitor()30 NetMonitor::~NetMonitor()
31 {
32 ExitNetMonitorThread();
33 }
34
HttpDetection()35 bool NetMonitor::HttpDetection()
36 {
37 NETMGR_LOG_D("HttpDetection in. ifaceName_: %{public}s", ifaceName_.c_str());
38 HttpRequest httpRequest;
39 httpRequest.SetIfaceName(ifaceName_);
40
41 std::string httpMsg(DEFAULT_PORTAL_HTTPS_URL);
42 std::string httpHeader;
43 int32_t ret = httpRequest.HttpGetHeader(httpMsg, httpHeader);
44 std::string urlRedirect;
45 if (ret != 0 || httpHeader.empty()) {
46 netDetectionStatus_(NetDetectionStatus::INVALID_DETECTION_STATE, urlRedirect);
47 lastDetectionState_ = INVALID_DETECTION_STATE;
48 return true;
49 }
50
51 int32_t retCode = GetUrlRedirectFromResponse(httpHeader, urlRedirect);
52 int32_t statusCode = GetStatusCodeFromResponse(httpHeader);
53 NETMGR_LOG_D("ifaceName[%{public}s], statusCode[%{public}d], retCode[%{public}d]", ifaceName_.c_str(), statusCode,
54 retCode);
55 bool isNotPortal = true;
56 if ((statusCode == OK || (statusCode >= BAD_REQUEST && statusCode <= CLIENT_ERROR_MAX)) &&
57 retCode > PORTAL_CONTENT_LENGTH_MIN) {
58 if (retCode > -1) {
59 netDetectionStatus_(NetDetectionStatus::CAPTIVE_PORTAL_STATE, urlRedirect);
60 }
61 lastDetectionState_ = CAPTIVE_PORTAL_STATE;
62 isNotPortal = false;
63 } else if (statusCode == NO_CONTENT) {
64 netDetectionStatus_(NetDetectionStatus::VERIFICATION_STATE, urlRedirect);
65 lastDetectionState_ = VERIFICATION_STATE;
66 isNotPortal = true;
67 } else if (statusCode != NO_CONTENT && statusCode >= CREATED && statusCode <= URL_REDIRECT_MAX) {
68 if (retCode > -1) {
69 netDetectionStatus_(NetDetectionStatus::CAPTIVE_PORTAL_STATE, urlRedirect);
70 }
71 lastDetectionState_ = CAPTIVE_PORTAL_STATE;
72 isNotPortal = false;
73 } else {
74 netDetectionStatus_(NetDetectionStatus::INVALID_DETECTION_STATE, urlRedirect);
75 lastDetectionState_ = INVALID_DETECTION_STATE;
76 isNotPortal = true;
77 }
78
79 NETMGR_LOG_D("statusCode[%{public}d], urlRedirect[%{public}s]", statusCode, urlRedirect.c_str());
80 return isNotPortal;
81 }
82
RunNetMonitorThreadFunc()83 void NetMonitor::RunNetMonitorThreadFunc()
84 {
85 NETMGR_LOG_D("RunNetMonitorThreadFunc in. ifaceName[%{public}s]", ifaceName_.c_str());
86 int32_t timeoutMs = HTTP_DETECTION_WAIT_TIME_MS;
87 for (;;) {
88 while (isStopNetMonitor_ && !isExitNetMonitorThread_) {
89 NETMGR_LOG_D("waiting for signal");
90 std::unique_lock<std::mutex> lock(mutex_);
91 condition_.wait(lock);
92 }
93
94 if (isExitNetMonitorThread_) {
95 NETMGR_LOG_D("break the loop");
96 break;
97 }
98 HttpDetection();
99 if (!isExitNetMonitorThread_) {
100 std::unique_lock<std::mutex> lock(mutex_);
101 conditionTimeout_.wait_for(lock, std::chrono::milliseconds(timeoutMs));
102 }
103 }
104 }
105
InitNetMonitorThread()106 ResultCode NetMonitor::InitNetMonitorThread()
107 {
108 netMonitorThread_ = std::make_unique<std::thread>(&NetMonitor::RunNetMonitorThreadFunc, this);
109 if (netMonitorThread_ == nullptr) {
110 NETMGR_LOG_E("Start NetMonitor thread failed!");
111 return ResultCode::ERR_NET_MONITOR_OPT_FAILED;
112 }
113 return ResultCode::ERR_NET_MONITOR_OPT_SUCCESS;
114 }
115
StopNetMonitorThread()116 void NetMonitor::StopNetMonitorThread()
117 {
118 NETMGR_LOG_D("Enter StopNetMonitorThread");
119 std::unique_lock<std::mutex> lock(mutex_);
120 isStopNetMonitor_ = true;
121 }
122
SignalNetMonitorThread(const std::string & ifaceName)123 void NetMonitor::SignalNetMonitorThread(const std::string &ifaceName)
124 {
125 NETMGR_LOG_D("Enter SignalNetMonitorThread");
126 std::unique_lock<std::mutex> lock(mutex_);
127 ifaceName_ = ifaceName;
128 lastDetectionState_ = INVALID_DETECTION_STATE;
129 isStopNetMonitor_ = false;
130 condition_.notify_one();
131 conditionTimeout_.notify_one();
132 NETMGR_LOG_D("leave SignalNetMonitorThread!");
133 }
134
ExitNetMonitorThread()135 void NetMonitor::ExitNetMonitorThread()
136 {
137 NETMGR_LOG_D("Enter ExitNetMonitorThread");
138 {
139 std::unique_lock<std::mutex> lock(mutex_);
140 isStopNetMonitor_ = false;
141 isExitNetMonitorThread_ = true;
142 condition_.notify_one();
143 conditionTimeout_.notify_one();
144 }
145
146 if (netMonitorThread_ != nullptr) {
147 netMonitorThread_->join();
148 NETMGR_LOG_D("ExitNetMonitorThread OK");
149 }
150 }
151
GetStatusCodeFromResponse(const std::string & strResponse)152 int32_t NetMonitor::GetStatusCodeFromResponse(const std::string &strResponse)
153 {
154 if (strResponse.empty()) {
155 NETMGR_LOG_E("strResponse is empty");
156 return -1;
157 }
158
159 std::string::size_type newLinePos = strResponse.find("\r\n");
160 if (newLinePos == std::string::npos) {
161 NETMGR_LOG_E("StrResponse did not find the response line!");
162 return -1;
163 }
164 std::string statusLine = strResponse.substr(0, newLinePos);
165 std::string::size_type spacePos = statusLine.find(" ");
166 if (spacePos == std::string::npos) {
167 NETMGR_LOG_E("No spaces found in the response line!");
168 return -1;
169 }
170 std::string strStatusCode = statusLine.substr(spacePos + 1, statusLine.length() - 1);
171 std::string::size_type pos = strStatusCode.find(" ");
172 if (pos == std::string::npos) {
173 NETMGR_LOG_E("No other space was found in the response line!");
174 return -1;
175 }
176 strStatusCode = strStatusCode.substr(0, pos);
177 if (strStatusCode.empty()) {
178 NETMGR_LOG_E("String status code is empty!");
179 return -1;
180 }
181
182 int32_t statusCode = std::stoi(strStatusCode);
183 return statusCode;
184 }
185
GetUrlRedirectFromResponse(const std::string & strResponse,std::string & urlRedirect)186 int32_t NetMonitor::GetUrlRedirectFromResponse(const std::string &strResponse, std::string &urlRedirect)
187 {
188 if (strResponse.empty()) {
189 NETMGR_LOG_E("strResponse is empty");
190 return -1;
191 }
192
193 std::string::size_type startPos = strResponse.find(PORTAL_URL_REDIRECT_FIRST_CASE);
194 if (startPos != std::string::npos) {
195 startPos += PORTAL_URL_REDIRECT_FIRST_CASE.length();
196 std::string::size_type endPos = strResponse.find(PORTAL_END_STR);
197 if (endPos != std::string::npos) {
198 urlRedirect = strResponse.substr(startPos, endPos - startPos);
199 }
200 return 0;
201 }
202
203 startPos = strResponse.find(PORTAL_URL_REDIRECT_SECOND_CASE);
204 if (startPos != std::string::npos) {
205 startPos += PORTAL_URL_REDIRECT_SECOND_CASE.length();
206 std::string::size_type endPos = strResponse.find(PORTAL_END_STR);
207 if (endPos != std::string::npos) {
208 urlRedirect = strResponse.substr(startPos, endPos - startPos);
209 }
210 startPos = strResponse.find(CONTENT_STR);
211 return std::atoi(strResponse.substr(startPos + CONTENT_STR.length(), NET_CONTENT_LENGTH).c_str());
212 }
213
214 return -1;
215 }
216 } // namespace NetManagerStandard
217 } // namespace OHOS