replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / util / src / camanager / bt_le_manager / ios / caleconnectionmanager.m
1 /* ****************************************************************
2  *
3  * Copyright 2017 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include "logger.h"
22 #include "cautilinterface.h"
23 #include "camanagerleinterface.h"
24 #include "camanagerleutil.h"
25 #include "caleautoconnector.h"
26 #include "cacommon.h"
27 #include "cacommonutil.h"
28 #include "camanagerdevice.h"
29 #include "caleclient.h"
30 #include "caleutils.h"
31 #include "uarraylist.h"
32
33 #define TAG "OIC_CA_MANAGER_LE"
34
35 static const int SUPPORT_ADNROID_API_LEVEL = 18;
36 static const int AUTH_FAIL = 5;
37 static const int LINK_LOSS = 8;
38 static const int ACCEPT_TIMEOUT_EXCEPTION = 16;
39 static const int REMOTE_DISCONNECT = 19;
40 static const int LOCAL_DISCONNECT = 22;
41 static const int CONNECTION_FAILED_TO_BE_EASTABLISHED = 62;
42 static const int USER_REMOVED_BOND = 68;
43
44 static dispatch_queue_t g_caManagerAutoConnectQueue = NULL;
45 static NSMutableDictionary *g_candidateACList = NULL;
46
47 static void CAManagerAdapterStateChangeCB(CBCentralManager *central);
48 static void CAManagerLeGattConnectionStateChangeCB(CBPeripheral *peripheral,
49                                        const char *remote_address, bool connected, NSError *error);
50 static void CAManagerLeGattServiceDiscoveredCB(CBPeripheral *peripheral, const char *remote_address,
51                                                NSError *error);
52
53
54 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
55 {
56     OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
57     VERIFY_NON_NULL(address, TAG, "address");
58
59     OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
60
61     if (!CAManagerCheckBTAddress(address))
62     {
63         OIC_LOG(ERROR, TAG, "this address is not BT address string format");
64         return CA_STATUS_FAILED;
65     }
66
67     // if there is target address in SharedPreference. it will be reseted.
68     if (CAManagerIsConnectedDeviceAddress(address))
69     {
70         if (!CAManagerRemoveConnectedDeviceAddress(address))
71         {
72             OIC_LOG(ERROR, TAG, "Preference - remove has failed");
73         }
74         else
75         {
76             OIC_LOG(INFO, TAG, "Preference - remove success");
77         }
78     }
79
80     // check candidate AC list
81     if (g_candidateACList[@(address)] != nil) {
82         OIC_LOG_V(DEBUG, TAG, "Candidate device : %s", address);
83
84         if(!CAManagerIsConnectedDeviceAddress(address))
85         {
86             // if BLE address is matched each other
87             // this address will be added into auto connection list.
88             OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
89             CBPeripheral *peripheral = (CBPeripheral *)g_candidateACList[@(address)];
90
91             CAManagerAddACData(address);
92
93             if(!CAManagerSetValueConnectedDeviceAddress(peripheral, address))
94             {
95                 OIC_LOG(ERROR, TAG, "AC list - address is un-registered");
96                 return CA_STATUS_FAILED;
97             }
98
99             [g_candidateACList removeObjectForKey:@(address)];
100
101             CAManagerSetAutoConnectionFlag(address, false);
102
103             // next connection will be requested as true flag
104             // after first connection
105             CALEClientSetAutoConnectFlag(address, true);
106         }
107     }
108
109     else
110     {
111         // it will be added new target address.
112         if (!CAManagerAddConnectedDeviceAddress(address))
113         {
114             OIC_LOG(ERROR, TAG, "Preference - putting has failed");
115         }
116         else
117         {
118             OIC_LOG(INFO, TAG, "Preference - putting success");
119         }
120     }
121
122     return CA_STATUS_OK;
123 }
124
125 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
126 {
127     OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
128     VERIFY_NON_NULL(address, TAG, "address");
129
130     OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
131
132     if (!CAManagerCheckBTAddress(address))
133     {
134         OIC_LOG(ERROR, TAG, "this address is not BT address string format");
135         return CA_STATUS_FAILED;
136     }
137
138     // if there is target address in SharedPreference. it would be removed
139     if (CAManagerIsConnectedDeviceAddress(address))
140     {
141         if (!CAManagerRemoveConnectedDeviceAddress(address))
142         {
143             OIC_LOG(ERROR, TAG, "Preference - remove has failed");
144         }
145         else
146         {
147             OIC_LOG(INFO, TAG, "Preference - remove success");
148         }
149     }
150
151     // remove target device for auto connection
152     CAResult_t ret = CAManagerRemoveData(address);
153     if (CA_STATUS_OK != ret)
154     {
155         OIC_LOG(ERROR, TAG, "CAManagerRemoveData has failed");
156     }
157
158     CALEClientSetAutoConnectFlag(address, false);
159
160     return CA_STATUS_OK;
161 }
162
163 CAResult_t CAManagerLEClientInitialize()
164 {
165     OIC_LOG(DEBUG, TAG, "CAManagerClientInitialize");
166
167     CAManagerInitMutexVaraibles();
168     CAManagerInitLEAutoConnection();
169
170     CAManagerCreateACDataList();
171
172     g_candidateACList = [[NSMutableDictionary alloc] init];
173
174     if (!g_caManagerAutoConnectQueue) {
175         g_caManagerAutoConnectQueue = dispatch_queue_create("com.caManager.AucoConnect",
176                                                             DISPATCH_QUEUE_SERIAL);
177     }
178
179     //callback register to caleclient
180     CALEClientSetCAManagerCallback(CAManagerAdapterStateChangeCB,
181                                    CAManagerLeGattConnectionStateChangeCB,
182                                    CAManagerLeGattServiceDiscoveredCB);
183
184     // get last connected device list
185     bool ret = false;
186     ret = CAManagerGetConnectedDeviceAddress();
187     if (!ret)
188     {
189         // create new set<String> object
190         ret = CAManagerCreateSetString();
191         if (ret)
192         {
193             OIC_LOG(DEBUG, TAG, "created new SetString");
194         }
195         else
196         {
197             OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
198             return CA_STATUS_FAILED;
199         }
200     }
201     else
202     {
203         OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
204     }
205
206     return CA_STATUS_OK;
207 }
208
209 CAResult_t CAManagerLEClientTerminate()
210 {
211     OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
212
213     // stop gatt connection
214     CAResult_t res = CALEClientDisconnectAll();
215     if (CA_STATUS_OK != res)
216     {
217         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
218     }
219
220     res = CAManagerRemoveAllData();
221     if (CA_STATUS_OK != res)
222     {
223         OIC_LOG(ERROR, TAG, "CAManagerRemoveAllData has failed");
224     }
225
226     CAManagerTerminateLEAutoConnection();
227     CAManagerTerminateMutexVariables();
228
229     if (g_candidateACList)
230     {
231         [g_candidateACList removeAllObjects];
232         [g_candidateACList release];
233         g_candidateACList = nil;
234     }
235
236     res = CAManagerTerminateSetString();
237     if (CA_STATUS_OK != res)
238     {
239         OIC_LOG(ERROR, TAG, "CAManagerTerminateSetString has failed");
240     }
241
242     return res;
243 }
244
245
246 //BLE CALLBACK
247
248
249 static void CAManagerAdapterStateChangeCB(CBCentralManager *central)
250 {
251     switch(central.state){
252         case CBCentralManagerStatePoweredOn:
253         {
254             OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
255
256             // when BT state is on. recovery flag has to be reset.
257             CAManagerSetBTRecovery(false);
258
259             // find target device for autoconnect
260             size_t length = CAManagerGetACDataLength();
261             OIC_LOG_V(DEBUG, TAG, "target device : %d", length);
262             for (size_t idx = 0; idx < length; idx++)
263             {
264                 char *leAddress = CAManagerGetLEAddressFromACData(idx);
265                 if (leAddress)
266                 {
267                     dispatch_async(g_caManagerAutoConnectQueue, ^{
268                         CAResult_t res = CAManagerStartAutoConnection(leAddress);
269                         if (CA_STATUS_OK != res)
270                         {
271                             OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
272                             return;
273                         }
274                     });
275                 }
276             }
277             break;
278         }
279         case CBCentralManagerStatePoweredOff:
280         {
281             OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
282
283             // reset autoconnect flag for all target devices
284             size_t length = CAManagerGetACDataLength();
285             for (size_t idx = 0; idx < length; idx++)
286             {
287                 char *address = CAManagerGetLEAddressFromACData(idx);
288                 if (address)
289                 {
290                     CAManagerSetAutoConnectionFlag(address, false);
291                     CAManagerSignalToRetryCond(address); //cancel if auto connecting is processing
292                 }
293             }
294
295             // check whether BT recovery is needed or not
296             if (CAManagerIsRecoveryFlagSet())
297             {
298                 CAManagerProcessRecovery(STATE_OFF);
299             }
300             break;
301         }
302         case CBCentralManagerStateUnsupported:
303         case CBCentralManagerStateUnauthorized:
304         case CBCentralManagerStateResetting:
305         default:
306             break;
307     }
308 }
309
310 static void CAManagerLeGattConnectionStateChangeCB(CBPeripheral *peripheral,
311                                          const char *remote_address, bool connected, NSError *error)
312 {
313     OIC_LOG_V(DEBUG, TAG, "peripheral : %s", [[peripheral name] UTF8String]);
314     OIC_LOG_V(DEBUG, TAG, "CAManagerLeGattConnectionStateChangeCB-remote_Address(%s),connected(%s)",
315               remote_address, connected ? "true":"false");
316     if (error) {
317         OIC_LOG_V(ERROR, TAG, "error : %s", [[error localizedDescription] UTF8String]);
318     }
319
320     VERIFY_NON_NULL_VOID(peripheral, TAG, "peripheral");
321     VERIFY_NON_NULL_VOID(remote_address, TAG, "remote_address");
322
323
324     if (connected) {
325         OIC_LOG(DEBUG, TAG, "LE is connected");
326     }
327     else {
328         OIC_LOG(DEBUG, TAG, "LE is disconnected");
329
330         if (!CAManagerIsMatchedACData(remote_address))
331         {
332             OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
333                       remote_address);
334             return;
335         }
336
337         CAManagerSetAutoConnectionFlag(remote_address, false);
338
339         dispatch_async(g_caManagerAutoConnectQueue, ^{
340             CAResult_t res = CAManagerStartAutoConnection(remote_address);
341             if (CA_STATUS_OK != res)
342             {
343                 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
344                 return;
345             }
346         });
347     }
348 }
349
350 static void CAManagerLeGattServiceDiscoveredCB(CBPeripheral *peripheral,
351                                                const char *remote_address, NSError *error)
352 {
353     OIC_LOG(DEBUG, TAG, "CAManagerLeGattServiceDiscoveredCB");
354
355     if (error){
356         OIC_LOG(ERROR, TAG, "error - CAManagerLeGattServiceDiscoveredCB");
357         return;
358     }
359
360     VERIFY_NON_NULL_VOID(peripheral, TAG, "peripheral");
361     VERIFY_NON_NULL_VOID(remote_address, TAG, "remote_address");
362
363     OIC_LOG_V(DEBUG, TAG, "ServicesDiscovered device : %s", remote_address);
364
365     if (CAManagerIsConnectedDeviceAddress(remote_address))
366     {
367         // if BLE address is matched each other
368         // this address will be added into auto connection list.
369         OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
370         CAManagerAddACData(remote_address);
371
372         if(!CAManagerSetValueConnectedDeviceAddress(peripheral, remote_address))
373         {
374             OIC_LOG(ERROR, TAG, "AC list - address is un-registered");
375             return;
376         }
377
378         CAManagerSetAutoConnectionFlag(remote_address, false);
379
380         // next connection will be requested as true flag
381         // after first connection
382         CALEClientSetAutoConnectFlag(remote_address, true);
383     }
384     else
385     {
386         OIC_LOG(INFO, TAG, "AC list - device is not matched");
387
388         //store candidate AC peripheral
389         g_candidateACList[@(remote_address)] = peripheral;
390     }
391
392     CAManagerSignalToRetryCond(remote_address);
393
394     OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
395 }
396
397 void CAManagerLEStopScan()
398 {
399     OIC_LOG(DEBUG, TAG, "CAManagerLEStopScan");
400     CALEClientStopScan();
401 }
402
403 void CAManagerLEStartScan()
404 {
405     OIC_LOG(DEBUG, TAG, "CAManagerLEStartScan");
406     CALEClientStartScan();
407 }
408
409 void CAManagerLEDisconnect()
410 {
411     OIC_LOG(DEBUG, TAG, "CAManagerLEDisconnect");
412     CALEClientDisconnectAll();
413 }