• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 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 "sta_network_check.h"
17 #include "wifi_logger.h"
18 
19 DEFINE_WIFILOG_LABEL("StaNetworkCheck");
20 
21 namespace OHOS {
22 namespace Wifi {
23 constexpr int NET_ERR_OK = 200;
24 constexpr int NET_ERR_CREATED = 201;
25 constexpr int NET_ERR_NO_CONTENT = 204;
26 constexpr int NET_ERR_BAD_REQUEST = 400;
27 
28 constexpr int NET_ERR_REDIRECT_CLASS_MAX = 399;
29 constexpr int NET_ERR_REQUEST_ERROR_CLASS_MAX = 499;
30 
StaNetworkCheck(NetStateHandler handle)31 StaNetworkCheck::StaNetworkCheck(NetStateHandler handle)
32 {
33     WIFI_LOGI("StaNetworkCheck constructor\n");
34     pDealNetCheckThread = nullptr;
35     netStateHandler = handle;
36     lastNetState = NETWORK_STATE_UNKNOWN;
37     isStopNetCheck = true;
38     isExitNetCheckThread = false;
39     isExited = true;
40 }
41 
~StaNetworkCheck()42 StaNetworkCheck::~StaNetworkCheck()
43 {
44     WIFI_LOGI("StaNetworkCheck::~StaNetworkCheck enter\n");
45     ExitNetCheckThread();
46     WIFI_LOGI("StaNetworkCheck::~StaNetworkCheck complete\n");
47 }
48 
HttpDetection()49 bool StaNetworkCheck::HttpDetection()
50 {
51     WIFI_LOGI("Enter httpDetection");
52     if (netStateHandler == nullptr) {
53         WIFI_LOGE("Handler func is null, ignore net detect of this time.");
54         return false;
55     }
56     /* Detect portal hotspot and send message to InterfaceSeervice if result is yes. */
57     HttpRequest httpRequest;
58     std::string httpReturn;
59     std::string httpMsg(DEFAULT_PORTAL_HTTPS_URL);
60     const std::string genStr("generate_204");
61     const std::string contStr("Content-Length:");
62 
63     if (httpRequest.HttpGet(httpMsg, httpReturn) == 0) {
64         size_t retCode = httpReturn.find("HTTP/");
65         int codeNum = 0;
66         if (retCode >= 0) {
67             constexpr int NET_ERROR_POS = 8;
68             constexpr int NET_ERROR_LEN = 5;
69             codeNum = std::atoi(httpReturn.substr(retCode + NET_ERROR_POS, NET_ERROR_LEN).c_str());
70         }
71 
72         size_t contLenStr = httpReturn.find(contStr);
73         int contLenNum = 0;
74         if (contLenStr > 0) {
75             constexpr int NET_CONTENT_LENGTH = 6;
76             contLenNum = std::atoi(httpReturn.substr(contLenStr + contStr.length(), NET_CONTENT_LENGTH).c_str());
77         }
78 
79         constexpr int PORTAL_CONTENT_LENGTH_MIN = 4;
80         if (codeNum == NET_ERR_NO_CONTENT) {
81             WIFI_LOGE("This network is normal!");
82             if ((lastNetState.load() != NETWORK_STATE_WORKING) && (isExitNetCheckThread == false) &&
83                 (isStopNetCheck == false)) {
84                 netStateHandler(StaNetState::NETWORK_STATE_WORKING, "");
85             }
86             lastNetState = NETWORK_STATE_WORKING;
87             return true;
88         } else if (codeNum != NET_ERR_NO_CONTENT &&
89             (codeNum >= NET_ERR_CREATED && codeNum <= NET_ERR_REDIRECT_CLASS_MAX)) {
90             /* Callback result to InterfaceService. */
91             WIFI_LOGI("This network is portal AP, need certification!");
92             std::string urlTmp;
93             const std::string locStr("Location: ");
94             size_t startStr = httpReturn.find(locStr);
95             if (startStr > 0) {
96                 startStr += locStr.length();
97                 size_t endstr = httpReturn.find(genStr, startStr);
98                 if (endstr > 0) {
99                     endstr += genStr.length();
100                     urlTmp = httpReturn.substr(startStr, endstr-startStr);
101                 }
102                 netStateHandler(StaNetState::NETWORK_CHECK_PORTAL, urlTmp);
103             }
104             return false;
105         } else if ((codeNum == NET_ERR_OK ||
106             (codeNum >= NET_ERR_BAD_REQUEST && codeNum <= NET_ERR_REQUEST_ERROR_CLASS_MAX)) &&
107             contLenNum > PORTAL_CONTENT_LENGTH_MIN) {
108             WIFI_LOGI("This network is portal AP, need certification!");
109             std::string urlTmp;
110             const std::string locStr("http");
111             size_t startStr = httpReturn.find(locStr);
112             if (startStr > 0) {
113                 size_t endstr = httpReturn.find(genStr, startStr);
114                 if (endstr > 0) {
115                     endstr += genStr.length();
116                     urlTmp = httpReturn.substr(startStr, endstr-startStr);
117                 }
118                 netStateHandler(StaNetState::NETWORK_CHECK_PORTAL, urlTmp);
119             }
120             return false;
121         } else {
122             WIFI_LOGE("http msg error[%s]!", httpReturn.c_str());
123             netStateHandler(StaNetState::NETWORK_STATE_NOWORKING, "");
124             lastNetState = NETWORK_STATE_NOWORKING;
125             return true;
126         }
127     }
128     WIFI_LOGE("This network can't online!");
129     if ((lastNetState.load() != NETWORK_STATE_NOWORKING) && (isExitNetCheckThread == false) && (isStopNetCheck == false)) {
130         netStateHandler(StaNetState::NETWORK_STATE_NOWORKING, "");
131     }
132     lastNetState = NETWORK_STATE_NOWORKING;
133     return true;
134 }
135 
RunNetCheckThreadFunc()136 void StaNetworkCheck::RunNetCheckThreadFunc()
137 {
138     WIFI_LOGI("enter RunNetCheckThreadFunc!\n");
139     int timeoutMs = 3000;
140     isExited = false;
141     for (;;) {
142         while (isStopNetCheck && !isExitNetCheckThread) {
143             LOGI("waiting for signal.\n");
144             std::unique_lock<std::mutex> lck(mMutex);
145             mCondition.wait(lck);
146         }
147         if (isExitNetCheckThread) {
148             WIFI_LOGI("break the loop\n");
149             isExited = true;
150             break;
151         }
152         if (!HttpDetection()) {
153             isStopNetCheck = true;
154         }
155         if (!isExitNetCheckThread) {
156             std::unique_lock<std::mutex> lck(mMutex);
157             if (mCondition_timeout.wait_for(lck, std::chrono::milliseconds(timeoutMs)) == std::cv_status::timeout) {
158                 LOGI("mCondition_timeout timeout.\n");
159             } else {
160                 LOGI("Wake up, break the loop.\n");
161                 isExited = true;
162                 break;
163             }
164         }
165     }
166 }
167 
InitNetCheckThread()168 ErrCode StaNetworkCheck::InitNetCheckThread()
169 {
170     pDealNetCheckThread = new (std::nothrow) std::thread(&StaNetworkCheck::RunNetCheckThreadFunc, this);
171     if (pDealNetCheckThread == nullptr) {
172         WIFI_LOGE("In StaNetworkCheck start NetCheck thread failed!\n");
173         return ErrCode::WIFI_OPT_FAILED;
174     }
175     return ErrCode::WIFI_OPT_SUCCESS;
176 }
177 
StopNetCheckThread()178 void StaNetworkCheck::StopNetCheckThread()
179 {
180     WIFI_LOGI("enter StopNetCheckThread!\n");
181     isStopNetCheck = true;
182 }
183 
SignalNetCheckThread()184 void StaNetworkCheck::SignalNetCheckThread()
185 {
186     WIFI_LOGI("enter SignalNetCheckThread!\n");
187     lastNetState = NETWORK_STATE_UNKNOWN;
188     isStopNetCheck = false;
189     mCondition.notify_one();
190 }
191 
ExitNetCheckThread()192 void StaNetworkCheck::ExitNetCheckThread()
193 {
194     isStopNetCheck = false;
195     isExitNetCheckThread = true;
196     while (!isExited) {
197         isExitNetCheckThread = true;
198         mCondition.notify_one();
199         mCondition_timeout.notify_one();
200         std::this_thread::sleep_for(std::chrono::milliseconds(1)); // sleep 1 ms
201     }
202     if (pDealNetCheckThread != nullptr) {
203         if (pDealNetCheckThread->joinable()) {
204             LOGI("Exit net check join()");
205             pDealNetCheckThread->join();
206         }
207         delete pDealNetCheckThread;
208         pDealNetCheckThread = nullptr;
209         LOGI("Exit net check done");
210     }
211 }
212 }  // namespace Wifi
213 }  // namespace OHOS
214