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