• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "connection_detector.h"
17 
18 #include <dirent.h>
19 #include <iostream>
20 #include <sstream>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <vector>
24 
25 #include "utils_log.h"
26 
27 namespace OHOS {
28 namespace Storage {
29 namespace DistributedFile {
GetCellByIndex(const std::string & str,int targetIndex)30 std::string ConnectionDetector::GetCellByIndex(const std::string &str, int targetIndex)
31 {
32     size_t begin = 0;
33     size_t end = 0;
34     int count = 0;
35     do {
36         size_t i;
37         for (i = begin; i < str.size(); ++i) {
38             if (str[i] != '\t' && str[i] != ' ') {
39                 break;
40             }
41         }
42         begin = i;
43         for (i = begin; i < str.size(); ++i) {
44             if (!(str[i] != '\t' && str[i] != ' ')) {
45                 break;
46             }
47         }
48         end = i;
49         if (end == str.size()) {
50             break;
51         }
52         ++count;
53         if (count == targetIndex) {
54             break;
55         }
56         begin = end;
57     } while (true);
58     return str.substr(begin, end - begin);
59 }
60 
MatchConnectionStatus(ifstream & inputFile)61 bool ConnectionDetector::MatchConnectionStatus(ifstream &inputFile)
62 {
63     string str;
64     getline(inputFile, str);
65     if (str.find("connection_status") == string::npos) {
66         return false;
67     }
68     while (getline(inputFile, str)) {
69         if (str.empty()) {
70             return false;
71         }
72         auto connectionStatus = GetCellByIndex(str, 2);  // 2 indicates the position of connection status
73         auto tcpStatus = GetCellByIndex(str, 3);  // 3 indicates the position of tcp status
74         // "2"|"3" indicates socket status is connecting|connected;
75         if (connectionStatus == "2" && (tcpStatus == "2" || tcpStatus == "3")) {
76             return true;
77         }
78     }
79     return false;
80 }
81 
MatchConnectionGroup(const std::string & fileName,const string & networkId)82 bool ConnectionDetector::MatchConnectionGroup(const std::string &fileName, const string &networkId)
83 {
84     if (access(fileName.c_str(), F_OK) != 0) {
85         LOGE("Cannot find the status file");
86         return false;
87     }
88     ifstream statusFile(fileName);
89     std::string str;
90     getline(statusFile, str);
91     bool result = false;
92     while (getline(statusFile, str)) {
93         if (str.find(networkId) == 0) {
94             result = MatchConnectionStatus(statusFile);
95             break;
96         }
97     }
98     statusFile.close();
99     return result;
100 }
101 
FilterFunc(const struct dirent * filename)102 static int FilterFunc(const struct dirent *filename)
103 {
104     if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") {
105         return DISMATCH;
106     }
107     return MATCH;
108 }
109 
110 struct NameList {
111     struct dirent **namelist = {nullptr};
112     int direntNum = 0;
113 };
114 
Deleter(struct NameList * arg)115 static void Deleter(struct NameList *arg)
116 {
117     for (int i = 0; i < arg->direntNum; i++) {
118         free((arg->namelist)[i]);
119         (arg->namelist)[i] = nullptr;
120     }
121     free(arg->namelist);
122 }
123 
CheckValidDir(const std::string & path)124 bool ConnectionDetector::CheckValidDir(const std::string &path)
125 {
126     struct stat buf {
127     };
128     auto ret = stat(path.c_str(), &buf);
129     if (ret == -1) {
130         LOGE("stat failed, errno = %{public}d", errno);
131         return false;
132     }
133     if ((buf.st_mode & S_IFMT) != S_IFDIR) {
134         LOGE("It is not a dir.");
135         return false;
136     }
137     return true;
138 }
139 
GetConnectionStatus(const std::string & targetDir,const std::string & networkId)140 bool ConnectionDetector::GetConnectionStatus(const std::string &targetDir, const std::string &networkId)
141 {
142     if (!CheckValidDir(SYS_HMDFS_PATH)) {
143         return false;
144     }
145     unique_ptr<struct NameList, decltype(Deleter) *> pNameList = {new (nothrow) struct NameList, Deleter};
146     if (pNameList == nullptr) {
147         LOGE("Failed to request heap memory.");
148         return false;
149     }
150     int num = scandir(SYS_HMDFS_PATH.c_str(), &(pNameList->namelist), FilterFunc, alphasort);
151     pNameList->direntNum = num;
152     for (int i = 0; i < num; i++) {
153         if ((pNameList->namelist[i])->d_name != targetDir) {
154             continue;
155         }
156         string dest = SYS_HMDFS_PATH + '/' + targetDir;
157         if ((pNameList->namelist[i])->d_type == DT_DIR) {
158             string statusFile = SYS_HMDFS_PATH + '/' + targetDir + '/' + CONNECTION_STATUS_FILE_NAME;
159             if (MatchConnectionGroup(statusFile, networkId)) {
160                 LOGI("Parse connection status success.");
161                 return true;
162             }
163             break;
164         }
165     }
166     return false;
167 }
168 
MocklispHash(const string & str)169 uint64_t ConnectionDetector::MocklispHash(const string &str)
170 {
171     uint64_t res = 0;
172     constexpr int mocklispHashPos = 5;
173     /* Mocklisp hash function. */
174     for (auto ch : str) {
175         res = (res << mocklispHashPos) - res + (uint64_t)ch;
176     }
177     return res;
178 }
179 
RepeatGetConnectionStatus(const std::string & targetDir,const std::string & networkId)180 int32_t ConnectionDetector::RepeatGetConnectionStatus(const std::string &targetDir, const std::string &networkId)
181 {
182     int retryCount = 0;
183     while (retryCount++ < MAX_RETRY - 1 && !GetConnectionStatus(targetDir, networkId)) {
184         usleep(CHECK_SESSION_DELAY_TIME);
185     }
186     return retryCount == MAX_RETRY ? -1 : NO_ERROR;
187 }
188 
GetCurrentUserId()189 int32_t ConnectionDetector::GetCurrentUserId()
190 {
191     std::vector<int32_t> userIds{};
192     auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(userIds);
193     if (ret != NO_ERROR || userIds.empty()) {
194         LOGE("query active os account id failed, ret = %{public}d", ret);
195         return INVALID_USER_ID;
196     }
197     return userIds[0];
198 }
199 
ParseHmdfsPath()200 std::string ConnectionDetector::ParseHmdfsPath()
201 {
202     auto userId = GetCurrentUserId();
203     if (userId == INVALID_USER_ID) {
204         return "";
205     }
206     std::string path = HMDFS_PATH;
207     size_t pos = path.find(CURRENT_USER_ID_FLAG);
208     if (pos == std::string::npos) {
209         return "";
210     }
211     return path.replace(pos, CURRENT_USER_ID_FLAG.length(), std::to_string(userId));
212 }
213 } // namespace DistributedFile
214 } // namespace Storage
215 } // namespace OHOS
216