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 #include "lnn_physical_subnet_manager.h"
16 
17 #include <stddef.h>
18 #include <string.h>
19 
20 #include "lnn_log.h"
21 #include "lnn_network_manager.h"
22 #include "softbus_adapter_thread.h"
23 #include "softbus_def.h"
24 #include "softbus_errcode.h"
25 
26 #define MAX_SUPPORTED_PHYSICAL_SUBNET 6
27 
28 static SoftBusMutex g_physicalSubnetsLock;
29 static LnnPhysicalSubnet *g_physicalSubnets[MAX_SUPPORTED_PHYSICAL_SUBNET];
30 
31 #define CALL_WITH_LOCK(RET, LOCK, ACTION)                                    \
32     do {                                                                     \
33         ret = SoftBusMutexLock(LOCK);                                        \
34         if (ret != SOFTBUS_OK) {                                             \
35             LNN_LOGE(LNN_BUILDER, "lock mutex failed"); \
36             break;                                                           \
37         }                                                                    \
38         (RET) = (ACTION);                                                    \
39         SoftBusMutexUnlock(LOCK);                                            \
40     } while (false)
41 
42 #define CALL_VOID_FUNC_WITH_LOCK(LOCK, ACTION)                               \
43     do {                                                                     \
44         if (SoftBusMutexLock(LOCK) != 0) {                                   \
45             LNN_LOGE(LNN_BUILDER, "lock mutex failed"); \
46             break;                                                           \
47         }                                                                    \
48         (ACTION);                                                            \
49         SoftBusMutexUnlock(LOCK);                                            \
50     } while (false)
51 
LnnInitPhysicalSubnetManager(void)52 int32_t LnnInitPhysicalSubnetManager(void)
53 {
54     LNN_LOGI(LNN_BUILDER, "g_physicalSubnetsLock init");
55     int32_t ret = SoftBusMutexInit(&g_physicalSubnetsLock, NULL);
56     LNN_LOGI(LNN_BUILDER, "g_physicalSubnetsLock init succ");
57     return ret;
58 }
59 
ClearSubnetManager(void)60 static void ClearSubnetManager(void)
61 {
62     for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
63         if (g_physicalSubnets[i] != NULL) {
64             if (g_physicalSubnets[i]->destroy != NULL) {
65                 g_physicalSubnets[i]->destroy(g_physicalSubnets[i]);
66             }
67             g_physicalSubnets[i] = NULL;
68         }
69     }
70 }
71 
LnnDeinitPhysicalSubnetManager(void)72 void LnnDeinitPhysicalSubnetManager(void)
73 {
74     LNN_LOGI(LNN_BUILDER, "g_physicalSubnetsLock deinit");
75     CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, ClearSubnetManager());
76     LNN_LOGI(LNN_BUILDER, "g_physicalSubnetsLock deinit succ");
77     if (SoftBusMutexDestroy(&g_physicalSubnetsLock) != SOFTBUS_OK) {
78         LNN_LOGE(LNN_BUILDER, "destroy mutex failed");
79     }
80 }
81 
DoRegistSubnet(LnnPhysicalSubnet * subnet)82 static int32_t DoRegistSubnet(LnnPhysicalSubnet *subnet)
83 {
84     for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
85         if (g_physicalSubnets[i] != NULL) {
86             continue;
87         }
88         g_physicalSubnets[i] = subnet;
89         if (g_physicalSubnets[i]->onNetifStatusChanged != NULL) {
90             g_physicalSubnets[i]->onNetifStatusChanged(g_physicalSubnets[i], NULL);
91         }
92         return SOFTBUS_OK;
93     }
94     LNN_LOGE(LNN_BUILDER, "subnet list is full");
95     return SOFTBUS_ERR;
96 }
97 
LnnRegistPhysicalSubnet(LnnPhysicalSubnet * subnet)98 int32_t LnnRegistPhysicalSubnet(LnnPhysicalSubnet *subnet)
99 {
100     if (subnet == NULL || subnet->protocol == NULL) {
101         LNN_LOGE(LNN_BUILDER, "protocol of subnet is required");
102         return SOFTBUS_ERR;
103     }
104     int32_t ret = SOFTBUS_OK;
105     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock start, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
106     CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoRegistSubnet(subnet));
107     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock end, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
108     return ret;
109 }
110 
DoUnregistSubnetByType(ProtocolType type)111 static int32_t DoUnregistSubnetByType(ProtocolType type)
112 {
113     for (uint8_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
114         if (g_physicalSubnets[i] != NULL && g_physicalSubnets[i]->protocol->id == type) {
115             if (g_physicalSubnets[i]->destroy != NULL) {
116                 g_physicalSubnets[i]->destroy(g_physicalSubnets[i]);
117             }
118             g_physicalSubnets[i] = NULL;
119         }
120     }
121     return SOFTBUS_OK;
122 }
123 
LnnUnregistPhysicalSubnetByType(ProtocolType type)124 int32_t LnnUnregistPhysicalSubnetByType(ProtocolType type)
125 {
126     int32_t ret = SOFTBUS_OK;
127     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock start, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
128     CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoUnregistSubnetByType(type));
129     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock end, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
130     return ret;
131 }
132 
DoNotifyStatusChange(const char * ifName,ProtocolType protocolType,void * status)133 void DoNotifyStatusChange(const char *ifName, ProtocolType protocolType, void *status)
134 {
135     for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
136         if (g_physicalSubnets[i] == NULL || g_physicalSubnets[i]->protocol->id != protocolType) {
137             continue;
138         }
139 
140         if (strcmp(g_physicalSubnets[i]->ifName, LNN_PHYSICAL_SUBNET_ALL_NETIF) != 0 &&
141             strcmp(g_physicalSubnets[i]->ifName, ifName) != 0) {
142             continue;
143         }
144 
145         if (g_physicalSubnets[i]->onNetifStatusChanged != NULL) {
146             g_physicalSubnets[i]->onNetifStatusChanged(g_physicalSubnets[i], status);
147         }
148     }
149 }
150 
LnnNotifyPhysicalSubnetStatusChanged(const char * ifName,ProtocolType protocolType,void * status)151 void LnnNotifyPhysicalSubnetStatusChanged(const char *ifName, ProtocolType protocolType, void *status)
152 {
153     CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, DoNotifyStatusChange(ifName, protocolType, status));
154     LNN_LOGI(LNN_BUILDER, "success");
155 }
156 
EnableResetingSubnetByType(ProtocolType protocolType)157 static void EnableResetingSubnetByType(ProtocolType protocolType)
158 {
159     for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
160         if (g_physicalSubnets[i] == NULL || g_physicalSubnets[i]->protocol->id != protocolType) {
161             continue;
162         }
163         if (g_physicalSubnets[i]->onSoftbusNetworkDisconnected != NULL) {
164             g_physicalSubnets[i]->onSoftbusNetworkDisconnected(g_physicalSubnets[i]);
165         }
166     }
167 }
168 
LnnNotifyAllTypeOffline(ConnectionAddrType type)169 void LnnNotifyAllTypeOffline(ConnectionAddrType type)
170 {
171     if (type == CONNECTION_ADDR_ETH || type == CONNECTION_ADDR_WLAN || type == CONNECTION_ADDR_MAX) {
172         CALL_VOID_FUNC_WITH_LOCK(&g_physicalSubnetsLock, EnableResetingSubnetByType(LNN_PROTOCOL_IP));
173         LNN_LOGI(LNN_BUILDER, "success");
174     }
175 }
176 
DoVisitSubnet(LnnVisitPhysicalSubnetCallback callback,void * data)177 static bool DoVisitSubnet(LnnVisitPhysicalSubnetCallback callback, void *data)
178 {
179     VisitNextChoice result = CHOICE_VISIT_NEXT;
180     for (uint16_t i = 0; i < MAX_SUPPORTED_PHYSICAL_SUBNET; i++) {
181         if (g_physicalSubnets[i] == NULL) {
182             continue;
183         }
184         result = callback(g_physicalSubnets[i], data);
185         if (result == CHOICE_FINISH_VISITING) {
186             return false;
187         }
188     }
189     return true;
190 }
191 
LnnVisitPhysicalSubnet(LnnVisitPhysicalSubnetCallback callback,void * data)192 bool LnnVisitPhysicalSubnet(LnnVisitPhysicalSubnetCallback callback, void *data)
193 {
194     bool ret = false;
195     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock start, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
196     CALL_WITH_LOCK(ret, &g_physicalSubnetsLock, DoVisitSubnet(callback, data));
197     LNN_LOGI(LNN_BUILDER, "get g_physicalSubnetsLock end, currTime=%{public}" PRIu64, SoftBusGetSysTimeMs());
198     return ret;
199 }
200