• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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