1 /*
2  * Copyright (C) 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 "wifi_hid2d_service_utils.h"
17 #include <regex>
18 #include <shared_mutex>
19 #include "dhcp_define.h"
20 #include "wifi_logger.h"
21 #include "wifi_common_util.h"
22 
23 namespace OHOS {
24 namespace Wifi {
25 DEFINE_WIFILOG_P2P_LABEL("Hid2dIpPool");
26 std::list<std::string> IpPool::ipList;
27 std::map<std::string, std::string> IpPool::mapGcMacToAllocIp;
28 const std::string PATTERN_IP = "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
29 std::shared_mutex g_ipPoolMutex;
30 static std::mutex g_sharedLinkMutex;
31 std::map<int, int> SharedLinkManager::sharedLinkCountMap;
32 int SharedLinkManager::firstGroupUid = -1;
33 #define DEFAULT_UID 0
34 
InitIpPool(const std::string & serverIp)35 bool IpPool::InitIpPool(const std::string& serverIp)
36 {
37     WIFI_LOGI("Init ip pool");
38 
39     std::unique_lock<std::shared_mutex> guard(g_ipPoolMutex);
40     if (!ipList.empty()) {
41         return true;
42     }
43 
44     std::string hostIp = serverIp.empty() ? DHCP::IP_V4_DEFAULT : serverIp;
45     if (!IsValidIp(hostIp)) {
46         return false;
47     }
48 
49     std::string serverIpHead = hostIp.substr(0, hostIp.find_last_of("\\."));
50     ipList.clear();
51     mapGcMacToAllocIp.clear();
52     for (int i = HID2D_IPPOOL_START; i <= HID2D_IPPOOL_END; ++i) {
53         ipList.emplace_back(serverIpHead + "." + std::to_string(i));
54     }
55     return true;
56 }
57 
GetIp(const std::string & gcMac)58 std::string IpPool::GetIp(const std::string& gcMac)
59 {
60     WIFI_LOGI("Get ip, gcMac: %{public}s", MacAnonymize(gcMac).c_str());
61 
62     std::unique_lock<std::shared_mutex> guard(g_ipPoolMutex);
63     std::string ip = "";
64     if (ipList.empty()) {
65         WIFI_LOGE("Alloc ip failed!");
66         return ip;
67     }
68     ip = ipList.front();
69     ipList.pop_front();
70     mapGcMacToAllocIp[gcMac] = ip;
71     return ip;
72 }
73 
ReleaseIp(const std::string & gcMac)74 void IpPool::ReleaseIp(const std::string& gcMac)
75 {
76     WIFI_LOGI("Release ip, gcMac: %{public}s", MacAnonymize(gcMac).c_str());
77 
78     std::unique_lock<std::shared_mutex> guard(g_ipPoolMutex);
79     auto iter = mapGcMacToAllocIp.find(gcMac);
80     if (iter == mapGcMacToAllocIp.end()) {
81         return;
82     }
83 
84     if (std::find(ipList.begin(), ipList.end(), iter->second) != ipList.end()) {
85         return;
86     }
87     if (IsValidIp(iter->second)) {
88         ipList.emplace_back(iter->second);
89         mapGcMacToAllocIp.erase(iter);
90     }
91 }
92 
ReleaseIpPool()93 void IpPool::ReleaseIpPool()
94 {
95     WIFI_LOGI("Release ip pool");
96 
97     std::unique_lock<std::shared_mutex> guard(g_ipPoolMutex);
98     mapGcMacToAllocIp.clear();
99     ipList.clear();
100 }
101 
IsValidIp(const std::string & ip)102 bool IpPool::IsValidIp(const std::string& ip)
103 {
104     if (ip.empty()) {
105         return false;
106     }
107     return std::regex_match(ip, std::regex(PATTERN_IP));
108 }
109 
SetGroupUid(int callingUid)110 void SharedLinkManager::SetGroupUid(int callingUid)
111 {
112     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
113     WIFI_LOGI("Set Group UID: %{public}d -> %{public}d", firstGroupUid, callingUid);
114     if (firstGroupUid != -1) {
115         return;
116     }
117     firstGroupUid = callingUid;
118 }
119 
GetGroupUid(int & callingUid)120 void SharedLinkManager::GetGroupUid(int &callingUid)
121 {
122     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
123     WIFI_LOGI("Get Group UID: %{public}d", firstGroupUid);
124     callingUid = firstGroupUid;
125 }
126 
IncreaseSharedLink()127 void SharedLinkManager::IncreaseSharedLink()
128 {
129     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
130     WIFI_LOGI("IncreaseSharedLink, current GO UID: %{public}d", firstGroupUid);
131     if (!sharedLinkCountMap.empty()) {
132         WIFI_LOGE("IncreaseSharedLink, Current count is not zeros");
133         sharedLinkCountMap.clear();
134     }
135     if (firstGroupUid == -1) {
136         firstGroupUid = DEFAULT_UID;
137     }
138     sharedLinkCountMap[firstGroupUid]++;
139 }
140 
IncreaseSharedLink(int callingUid)141 void SharedLinkManager::IncreaseSharedLink(int callingUid)
142 {
143     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
144     sharedLinkCountMap[callingUid]++;
145     WIFI_LOGI("CallingUid %{public}d increase shared link to %{public}d", callingUid,
146         sharedLinkCountMap[callingUid]);
147 }
148 
DecreaseSharedLink(int callingUid)149 void SharedLinkManager::DecreaseSharedLink(int callingUid)
150 {
151     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
152     if (sharedLinkCountMap.find(callingUid) == sharedLinkCountMap.end()) {
153         WIFI_LOGE("CallingUid %{public}d decrease error for not found!", callingUid);
154         return;
155     }
156     if (sharedLinkCountMap[callingUid] == 0) {
157         WIFI_LOGE("CallingUid %{public}d decrease error for sharedLinkCount == 0!", callingUid);
158         return;
159     }
160     sharedLinkCountMap[callingUid]--;
161     WIFI_LOGI("CallingUid %{public}d decrease shared link to %{public}d", callingUid,
162         sharedLinkCountMap[callingUid]);
163 }
164 
ClearSharedLinkCount()165 void SharedLinkManager::ClearSharedLinkCount()
166 {
167     WIFI_LOGI("ClearSharedLinkCount");
168     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
169     firstGroupUid = -1;
170     sharedLinkCountMap.clear();
171 }
172 
GetSharedLinkCount()173 int SharedLinkManager::GetSharedLinkCount()
174 {
175     std::unique_lock<std::mutex> lock(g_sharedLinkMutex);
176     int sharedLinkCount = 0;
177     for (auto iter : sharedLinkCountMap) {
178         sharedLinkCount += iter.second;
179     }
180     WIFI_LOGI("Get sharedLinkCount: %{public}d", sharedLinkCount);
181     return sharedLinkCount;
182 }
183 }  // namespace Wifi
184 }  // namespace OHOS