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