1 /*
2 * Copyright (C) 2021-2023 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 #include "dns_config_client.h"
31
32 #include "event_report.h"
33 #include "fwmark_client.h"
34 #include "netmanager_base_common_utils.h"
35 #include "netsys_controller.h"
36 #include "net_mgr_log_wrapper.h"
37 #include "net_monitor.h"
38
39 namespace OHOS {
40 namespace NetManagerStandard {
41 namespace {
42 constexpr int32_t INIT_DETECTION_DELAY_MS = 8 * 1000;
43 constexpr int32_t MAX_FAILED_DETECTION_DELAY_MS = 5 * 60 * 1000;
44 constexpr int32_t SUCCESSED_DETECTION_DELAY_MS = 30 * 1000;
45 constexpr int32_t CAPTIVE_PORTAL_DETECTION_DELAY_MS = 60 * 1000;
46 constexpr int32_t DOUBLE = 2;
47 constexpr int32_t DOMAINIPADDR = 128;
48 constexpr int32_t PORTAL_CONTENT_LENGTH_MIN = 4;
49 constexpr int32_t NET_CONTENT_LENGTH = 6;
50 constexpr uint16_t DEFAULT_PORT = 80;
51 constexpr int32_t MAX_RECIVE_SIZE = 2048;
52 constexpr int32_t DOMAIN_POSITION = 3;
53 constexpr int32_t URLPATH_POSITION = 4;
54 constexpr int32_t SOCKET_TIMEOUT = 2;
55 constexpr int32_t MAX_SEND_RETRY = 4;
56 constexpr uint8_t SOCKET_NOT_READY = 0;
57 constexpr uint8_t SOCKET_READY = 1;
58 constexpr const char *PORTAL_URL_REDIRECT_FIRST_CASE = "Location: ";
59 constexpr const char *PORTAL_URL_REDIRECT_SECOND_CASE = "http";
60 constexpr const char *CONTENT_STR = "Content-Length:";
61 constexpr const char *PORTAL_END_STR = ".com";
62 constexpr const char SPACE_STR = ' ';
63 constexpr const char NEW_LINE_STR = '\n';
64 constexpr const char *URL_CFG_FILE = "/system/etc/netdetectionurl.conf";
65 constexpr const char *DEF_NETDETECT_URL = "http://connectivitycheck.platform.hicloud.com/generate_204";
66 }
NetDetectThread(const std::shared_ptr<NetMonitor> & netMonitor)67 static void NetDetectThread(const std::shared_ptr<NetMonitor> &netMonitor)
68 {
69 if (netMonitor == nullptr) {
70 NETMGR_LOG_E("netMonitor is nullptr");
71 return;
72 }
73 while (netMonitor->IsDetecting()) {
74 netMonitor->Detection();
75 }
76 }
77
NetMonitor(uint32_t netId,const std::weak_ptr<INetMonitorCallback> & callback)78 NetMonitor::NetMonitor(uint32_t netId, const std::weak_ptr<INetMonitorCallback> &callback)
79 : netId_(netId), netMonitorCallback_(callback)
80 {
81 }
82
Start()83 void NetMonitor::Start()
84 {
85 NETMGR_LOG_I("Start net[%{public}d] monitor in", netId_);
86 if (isDetecting_) {
87 NETMGR_LOG_W("Net[%{public}d] monitor is detecting, no need to start", netId_);
88 return;
89 }
90 isDetecting_ = true;
91 std::shared_ptr<NetMonitor> netMonitor = shared_from_this();
92 std::thread t([netMonitor] {return NetDetectThread(netMonitor); });
93 std::string threadName = "netDetect";
94 pthread_setname_np(t.native_handle(), threadName.c_str());
95 t.detach();
96 }
97
Stop()98 void NetMonitor::Stop()
99 {
100 NETMGR_LOG_I("Stop net[%{public}d] monitor in", netId_);
101 isDetecting_ = false;
102 detectionCond_.notify_all();
103 NETMGR_LOG_I("Stop net[%{public}d] monitor out", netId_);
104 }
105
IsDetecting()106 bool NetMonitor::IsDetecting()
107 {
108 return isDetecting_.load();
109 }
110
Detection()111 void NetMonitor::Detection()
112 {
113 NetDetectionStatus result = SendParallelHttpProbes();
114 struct EventInfo eventInfo = {.monitorStatus = static_cast<int32_t>(result)};
115 EventReport::SendMonitorBehaviorEvent(eventInfo);
116 if (isDetecting_) {
117 if (result == CAPTIVE_PORTAL_STATE) {
118 NETMGR_LOG_I("currentNetMonitor[%{public}d] need portal", netId_);
119 detectionDelay_ = CAPTIVE_PORTAL_DETECTION_DELAY_MS;
120 } else if (result == VERIFICATION_STATE) {
121 NETMGR_LOG_I("currentNetMonitor[%{public}d] evaluation success", netId_);
122 detectionDelay_ = SUCCESSED_DETECTION_DELAY_MS;
123 detectionSteps_ = 0;
124 } else {
125 NETMGR_LOG_I("currentNetMonitor[%{public}d] evaluation failed", netId_);
126 detectionDelay_ = static_cast<uint32_t>(INIT_DETECTION_DELAY_MS * DOUBLE * detectionSteps_);
127 if (detectionDelay_ == 0) {
128 detectionDelay_ = INIT_DETECTION_DELAY_MS;
129 } else if (detectionDelay_ >= MAX_FAILED_DETECTION_DELAY_MS) {
130 detectionDelay_ = MAX_FAILED_DETECTION_DELAY_MS;
131 }
132 detectionSteps_++;
133 }
134 auto monitorCallback = netMonitorCallback_.lock();
135 if (monitorCallback) {
136 monitorCallback->OnHandleNetMonitorResult(result, portalUrlRedirect_);
137 }
138 if (isDetecting_) {
139 std::unique_lock<std::mutex> locker(detectionMtx_);
140 detectionCond_.wait_for(locker, std::chrono::milliseconds(detectionDelay_));
141 }
142 }
143 }
144
SendParallelHttpProbes()145 NetDetectionStatus NetMonitor::SendParallelHttpProbes()
146 {
147 std::string url;
148 if (GetDefaultNetDetectionUrlFromCfg(url) != 0) {
149 NETMGR_LOG_I("GetDefaultNetDetectionUrlFromCfg failed, use default url");
150 url = DEF_NETDETECT_URL;
151 }
152 std::string domain;
153 std::string urlPath;
154 if (ParseUrl(url, domain, urlPath)) {
155 NETMGR_LOG_E("Parse net[%{public}d] url:%{public}s error", netId_, url.c_str());
156 return INVALID_DETECTION_STATE;
157 }
158 return SendHttpProbe(domain, urlPath, DEFAULT_PORT);
159 }
160
SendHttpProbe(const std::string & defaultDomain,const std::string & defaultUrl,const uint16_t defaultPort)161 NetDetectionStatus NetMonitor::SendHttpProbe(const std::string &defaultDomain, const std::string &defaultUrl,
162 const uint16_t defaultPort)
163 {
164 int socketType = AF_INET;
165 std::string ipAddr;
166 if (GetIpAddr(defaultDomain, ipAddr, socketType)) {
167 NETMGR_LOG_E("NetMonitor::Error at GetIpAddr");
168 return INVALID_DETECTION_STATE;
169 }
170 int32_t sockFd = socket(socketType, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
171 if (sockFd < 0) {
172 NETMGR_LOG_E("Create net[%{public}d] socket failed,errno[%{public}d]:%{public}s", netId_, errno,
173 strerror(errno));
174 return INVALID_DETECTION_STATE;
175 }
176 if (SetSocketParameter(sockFd)) {
177 close(sockFd);
178 NETMGR_LOG_E("Set net[%{public}d] socket parameter error", netId_);
179 return INVALID_DETECTION_STATE;
180 }
181 if (Connect(sockFd, socketType, defaultPort, ipAddr) < 0) {
182 NETMGR_LOG_E("Connect net[%{public}d] nonblock socket:%{public}d failed", netId_, sockFd);
183 close(sockFd);
184 return INVALID_DETECTION_STATE;
185 }
186 if (Send(sockFd, defaultDomain, defaultUrl) < 0) {
187 NETMGR_LOG_E("Send http probe data to net[%{public}d] socket:%{public}d failed", netId_, sockFd);
188 close(sockFd);
189 return INVALID_DETECTION_STATE;
190 }
191 std::string probeResult;
192 if (Receive(sockFd, probeResult) < 0) {
193 NETMGR_LOG_E("Recevie probe result from net[%{public}d] socket:%{public}d failed", netId_, sockFd);
194 close(sockFd);
195 return INVALID_DETECTION_STATE;
196 }
197 close(sockFd);
198 return dealRecvResult(probeResult);
199 }
200
Connect(int32_t sockFd,int socketType,const uint16_t port,const std::string & ipAddr)201 int32_t NetMonitor::Connect(int32_t sockFd, int socketType, const uint16_t port, const std::string &ipAddr)
202 {
203 int flags = fcntl(sockFd, F_GETFL, 0);
204 if (flags == -1 && errno == EINTR) {
205 flags = fcntl(sockFd, F_GETFL, 0);
206 if (flags == -1) {
207 NETMGR_LOG_E("Make net[%{public}d] socket:%{public}d non block failed,error[%{public}d]: %s", netId_,
208 sockFd, errno, strerror(errno));
209 return -1;
210 }
211 }
212 uint32_t tempFlags = (uint32_t)flags | O_NONBLOCK;
213 int32_t ret = fcntl(sockFd, F_SETFL, tempFlags);
214 if (ret == -1 && errno == EINTR) {
215 ret = fcntl(sockFd, F_SETFL, tempFlags);
216 if (ret == -1) {
217 NETMGR_LOG_E("Make net[%{public}d] socket:%{public}d non block failed,error[%{public}d]: %s", netId_,
218 sockFd, errno, strerror(errno));
219 return -1;
220 }
221 }
222 if (socketType == AF_INET6) {
223 return ConnectIpv6(sockFd, port, ipAddr);
224 } else {
225 return ConnectIpv4(sockFd, port, ipAddr);
226 }
227 }
228
ConnectIpv4(int32_t sockFd,const uint16_t port,const std::string & ipAddr)229 int32_t NetMonitor::ConnectIpv4(int32_t sockFd, const uint16_t port, const std::string &ipAddr)
230 {
231 NETMGR_LOG_D("Net[%{public}d] connect ipv4 ip:[%{public}s] socket:%{public}d in", netId_,
232 CommonUtils::ToAnonymousIp(ipAddr).c_str(), sockFd);
233 sockaddr_in serverAddr;
234 bzero(&serverAddr, sizeof(serverAddr));
235 serverAddr.sin_family = AF_INET;
236 serverAddr.sin_port = htons(port);
237 serverAddr.sin_addr.s_addr = inet_addr(ipAddr.c_str());
238 int32_t ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
239 if (ret < 0) {
240 if (errno != EINPROGRESS) {
241 NETMGR_LOG_E("Connect net[%{public}d] ipv4 ip:%{public}s failed,error[%{public}d]:%{public}s", netId_,
242 CommonUtils::ToAnonymousIp(ipAddr).c_str(), errno, strerror(errno));
243 return -1;
244 }
245 }
246 return 0;
247 }
248
ConnectIpv6(int32_t sockFd,const uint16_t port,const std::string & ipAddr)249 int32_t NetMonitor::ConnectIpv6(int32_t sockFd, const uint16_t port, const std::string &ipAddr)
250 {
251 NETMGR_LOG_D("Net[%{public}d] connect ipv6 ip:[%{public}s] socket:%{public}d in", netId_,
252 CommonUtils::ToAnonymousIp(ipAddr).c_str(), sockFd);
253 sockaddr_in6 serverAddr;
254 bzero(&serverAddr, sizeof(serverAddr));
255 serverAddr.sin6_family = AF_INET6;
256 serverAddr.sin6_port = htons(port);
257 inet_pton(AF_INET6, ipAddr.c_str(), &serverAddr.sin6_addr);
258 int32_t ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
259 if (ret < 0) {
260 if (errno != EINPROGRESS) {
261 NETMGR_LOG_E("Connect net[%{public}d] ipv6 ip:%{public}s failed,error[%{public}d]:%{public}s", netId_,
262 CommonUtils::ToAnonymousIp(ipAddr).c_str(), errno, strerror(errno));
263 return -1;
264 }
265 }
266 return 0;
267 }
268
Wait(int32_t sockFd,uint8_t * canRead,uint8_t * canWrite)269 int32_t NetMonitor::Wait(int32_t sockFd, uint8_t *canRead, uint8_t *canWrite)
270 {
271 fd_set writeFds, readFds;
272 FD_ZERO(&readFds);
273 FD_ZERO(&writeFds);
274 if (canRead) {
275 FD_SET(sockFd, &readFds);
276 }
277 if (canWrite) {
278 FD_SET(sockFd, &writeFds);
279 }
280 struct timeval tval = {tval.tv_sec = 8, tval.tv_usec = 0};
281 int ret = select((sockFd + 1), &readFds, &writeFds, nullptr, &tval);
282 if (ret <= 0) {
283 NETMGR_LOG_E("Select net[%{public}d] failed,errno[%{public}d]:%{public}s", netId_, errno, strerror(errno));
284 return -1;
285 }
286 if (FD_ISSET(sockFd, &readFds) && canRead) {
287 *canRead = SOCKET_READY;
288 }
289 if (FD_ISSET(sockFd, &writeFds) && canWrite) {
290 *canWrite = SOCKET_READY;
291 }
292 return 0;
293 }
294
Send(int32_t sockFd,const std::string & domain,const std::string & url)295 int32_t NetMonitor::Send(int32_t sockFd, const std::string &domain, const std::string &url)
296 {
297 uint8_t canWrite = SOCKET_NOT_READY;
298 int32_t ret = Wait(sockFd, nullptr, &canWrite);
299 if (ret < 0 || canWrite != SOCKET_READY) {
300 NETMGR_LOG_E("Net[%{public}d] socket not ready to send data,ret:%{public}d, canWrite:%{public}d", netId_, ret,
301 canWrite);
302 return -1;
303 }
304 std::string sendData = "GET /" + url + " HTTP/1.1\r\n";
305 sendData.append("Host: " + domain + "\r\n\r\n");
306 const char *writeBuf = sendData.c_str();
307 int32_t bufSize = static_cast<int32_t>(sendData.size());
308 ssize_t written = 0;
309 int32_t retry = 0;
310 while (bufSize > 0) {
311 written = send(sockFd, writeBuf, bufSize, 0);
312 if (written < 0) {
313 if (errno == EAGAIN && retry < MAX_SEND_RETRY) {
314 ++retry;
315 NETMGR_LOG_W("Net[%{public}d] try to resend the data to sokcet:%{public}d for the :%{public}d times",
316 netId_, sockFd, retry);
317 continue;
318 }
319 NETMGR_LOG_E("Net[%{public}d] Send data to socket:%{public}d failed, errno[%{public}d]:%{public}s", netId_,
320 sockFd, errno, strerror(errno));
321 return -1;
322 }
323 if (written == 0) {
324 break;
325 }
326 writeBuf += written;
327 bufSize -= written;
328 }
329 return 0;
330 }
331
Receive(int32_t sockFd,std::string & probResult)332 int32_t NetMonitor::Receive(int32_t sockFd, std::string &probResult)
333 {
334 uint8_t canRead = SOCKET_NOT_READY;
335 int32_t ret = Wait(sockFd, &canRead, nullptr);
336 if (ret < 0 || canRead != SOCKET_READY) {
337 NETMGR_LOG_E("Net[%{public}d] socket not ready to read data, ret:%{public}d, canRead:%{public}d", netId_, ret,
338 canRead);
339 return -1;
340 }
341 char buff[MAX_RECIVE_SIZE] = {0};
342 int32_t recvBytes = recv(sockFd, buff, MAX_RECIVE_SIZE, 0);
343 if (recvBytes <= 0) {
344 NETMGR_LOG_E("Receive net[%{public}d] data from socket failed,errno[%{public}d]:%{public}s", netId_, errno,
345 strerror(errno));
346 return -1;
347 }
348 probResult = std::string(buff, recvBytes);
349 return 0;
350 }
351
SetSocketParameter(int32_t sockFd)352 int32_t NetMonitor::SetSocketParameter(int32_t sockFd)
353 {
354 std::unique_ptr<nmd::FwmarkClient> fwmarkClient = std::make_unique<nmd::FwmarkClient>();
355 if (fwmarkClient->BindSocket(sockFd, netId_) < 0) {
356 NETMGR_LOG_E("Error at bind net[%{public}d] socket", netId_);
357 struct EventInfo eventInfo = {.socketFd = sockFd,
358 .errorType = static_cast<int32_t>(FAULT_BIND_SOCKET_FAILED),
359 .errorMsg =
360 std::string("Bind socket:").append(std::to_string(sockFd)).append(" failed")};
361 EventReport::SendMonitorFaultEvent(eventInfo);
362 return -1;
363 }
364 struct timeval timeout;
365 timeout.tv_sec = SOCKET_TIMEOUT;
366 timeout.tv_usec = 0;
367 if (setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) ||
368 setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout))) {
369 NETMGR_LOG_E("Error at set net[%{public}d] socket timeout,error[%{public}d]:%{public}s", netId_, errno,
370 strerror(errno));
371 return -1;
372 }
373 return 0;
374 }
375
dealRecvResult(const std::string & strResponse)376 NetDetectionStatus NetMonitor::dealRecvResult(const std::string &strResponse)
377 {
378 std::string urlRedirect = "";
379 int32_t retCode = GetUrlRedirectFromResponse(strResponse, urlRedirect);
380 int32_t statusCode = GetStatusCodeFromResponse(strResponse);
381 portalUrlRedirect_ = urlRedirect;
382 NETMGR_LOG_D("statusCode[%{public}d], retCode[%{public}d]", statusCode, retCode);
383 if ((statusCode == OK || (statusCode >= BAD_REQUEST && statusCode <= CLIENT_ERROR_MAX)) &&
384 retCode > PORTAL_CONTENT_LENGTH_MIN) {
385 return CAPTIVE_PORTAL_STATE;
386 } else if (statusCode == NO_CONTENT) {
387 return VERIFICATION_STATE;
388 } else if ((statusCode != NO_CONTENT) && (statusCode >= CREATED) && (statusCode <= URL_REDIRECT_MAX)) {
389 if (retCode > -1) {
390 return CAPTIVE_PORTAL_STATE;
391 }
392 return INVALID_DETECTION_STATE;
393 }
394 return INVALID_DETECTION_STATE;
395 }
396
GetStatusCodeFromResponse(const std::string & strResponse)397 int32_t NetMonitor::GetStatusCodeFromResponse(const std::string &strResponse)
398 {
399 if (strResponse.empty()) {
400 NETMGR_LOG_E("strResponse is empty");
401 return -1;
402 }
403
404 std::string::size_type newLinePos = strResponse.find("\r\n");
405 if (newLinePos == std::string::npos) {
406 NETMGR_LOG_E("StrResponse did not find the response line!");
407 return -1;
408 }
409 std::string statusLine = strResponse.substr(0, newLinePos);
410 std::string::size_type spacePos = statusLine.find(" ");
411 if (spacePos == std::string::npos) {
412 NETMGR_LOG_E("No spaces found in the response line!");
413 return -1;
414 }
415 std::string strStatusCode = statusLine.substr(spacePos + 1, statusLine.length() - 1);
416 std::string::size_type pos = strStatusCode.find(" ");
417 if (pos == std::string::npos) {
418 NETMGR_LOG_E("No other space was found in the response line!");
419 return -1;
420 }
421 strStatusCode.resize(pos);
422 if (strStatusCode.empty()) {
423 NETMGR_LOG_E("String status code is empty!");
424 return -1;
425 }
426
427 int32_t statusCode = std::stoi(strStatusCode);
428 return statusCode;
429 }
430
GetUrlRedirectFromResponse(const std::string & strResponse,std::string & urlRedirect)431 int32_t NetMonitor::GetUrlRedirectFromResponse(const std::string &strResponse, std::string &urlRedirect)
432 {
433 if (strResponse.empty()) {
434 NETMGR_LOG_E("strResponse is empty");
435 return -1;
436 }
437
438 std::string::size_type startPos = strResponse.find(PORTAL_URL_REDIRECT_FIRST_CASE);
439 if (startPos != std::string::npos) {
440 startPos += strlen(PORTAL_URL_REDIRECT_FIRST_CASE);
441 std::string::size_type endPos = strResponse.find(PORTAL_END_STR, startPos);
442 if (endPos != std::string::npos) {
443 urlRedirect = strResponse.substr(startPos, endPos - startPos + strlen(PORTAL_END_STR));
444 }
445 return 0;
446 }
447
448 startPos = strResponse.find(PORTAL_URL_REDIRECT_SECOND_CASE);
449 if (startPos != std::string::npos) {
450 startPos += strlen(PORTAL_URL_REDIRECT_SECOND_CASE);
451 std::string::size_type endPos = strResponse.find(PORTAL_END_STR, startPos);
452 if (endPos != std::string::npos) {
453 urlRedirect = strResponse.substr(startPos, endPos - startPos + strlen(PORTAL_END_STR));
454 }
455 startPos = strResponse.find(CONTENT_STR);
456 return std::atoi(strResponse.substr(startPos + strlen(CONTENT_STR), NET_CONTENT_LENGTH).c_str());
457 }
458 return -1;
459 }
460
GetIpAddr(const std::string domain,std::string & ip_addr,int & socketType)461 int32_t NetMonitor::GetIpAddr(const std::string domain, std::string &ip_addr, int &socketType)
462 {
463 std::vector<AddrInfo> result;
464 AddrInfo hints = {};
465 std::string serverName;
466 if (NetsysController::GetInstance().GetAddrInfo(domain, serverName, hints, netId_, result) < 0) {
467 NETMGR_LOG_E("Get net[%{public}d] address info failed,errno[%{public}d]:%{public}s", netId_, errno,
468 strerror(errno));
469 return -1;
470 }
471 if (result.empty()) {
472 NETMGR_LOG_E("Get net[%{public}d] address info return nullptr result", netId_);
473 return -1;
474 }
475 char ip[DOMAINIPADDR] = {0};
476 for (auto &node : result) {
477 if (node.aiFamily != AF_INET) {
478 continue;
479 }
480 if (!inet_ntop(AF_INET, &node.aiAddr.sin.sin_addr, ip, sizeof(ip))) {
481 continue;
482 }
483 ip_addr = ip;
484 socketType = AF_INET;
485 NETMGR_LOG_D("Get net[%{public}d] monitor ip:%{public}s", netId_, CommonUtils::ToAnonymousIp(ip_addr).c_str());
486 return 0;
487 }
488 if (result[0].aiFamily == AF_INET6) {
489 inet_ntop(AF_INET6, &result[0].aiAddr.sin6.sin6_addr, ip, sizeof(ip));
490 ip_addr = ip;
491 socketType = AF_INET6;
492 }
493 NETMGR_LOG_I("Get net[%{public}d] monitor ip:%{public}s", netId_, CommonUtils::ToAnonymousIp(ip_addr).c_str());
494 return 0;
495 }
496
GetDefaultNetDetectionUrlFromCfg(std::string & strUrl)497 int32_t NetMonitor::GetDefaultNetDetectionUrlFromCfg(std::string &strUrl)
498 {
499 int32_t ret = 0;
500 std::ifstream file(URL_CFG_FILE);
501 if (!file.is_open()) {
502 NETMGR_LOG_E("Open file failed (%{public}s)", strerror(errno));
503 ret = -1;
504 return ret;
505 }
506
507 std::ostringstream oss;
508 oss << file.rdbuf();
509 std::string content = oss.str();
510 auto index = content.find_last_of(SPACE_STR);
511 strUrl = content.substr(index + 1);
512 if (strUrl.empty()) {
513 NETMGR_LOG_E("get netdetectionurl is empty");
514 ret = -1;
515 }
516 strUrl.erase(std::remove(strUrl.begin(), strUrl.end(), NEW_LINE_STR), strUrl.end());
517 NETMGR_LOG_D("GetDefaultNetDetectionUrl is : %{public}s", strUrl.c_str());
518 return ret;
519 }
520
ParseUrl(const std::string & url,std::string & domain,std::string & urlPath)521 int32_t NetMonitor::ParseUrl(const std::string &url, std::string &domain, std::string &urlPath)
522 {
523 std::regex reg_domain_port("/");
524 std::cregex_token_iterator itrBegin(url.c_str(), url.c_str() + url.size(), reg_domain_port, -1);
525 std::cregex_token_iterator itrEnd;
526 int32_t i = 0;
527 for (std::cregex_token_iterator itr = itrBegin; itr != itrEnd; ++itr) {
528 i++;
529 if (i == DOMAIN_POSITION) {
530 domain = *itr;
531 } else if (i == URLPATH_POSITION) {
532 urlPath = *itr;
533 }
534 }
535 return (domain.empty() || urlPath.empty()) ? -1 : 0;
536 }
537 } // namespace NetManagerStandard
538 } // namespace OHOS
539