Revert before adding new apis
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Connection / Tizen.Network.Connection / ConnectionInternalManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 using System.Text;
21 using System.Threading.Tasks;
22 using System.Runtime.InteropServices;
23 using System.Collections;
24 using System.Threading;
25
26 namespace Tizen.Network.Connection
27 {
28     class HandleHolder : IDisposable
29     {
30         private IntPtr Handle;
31         private bool disposed = false;
32
33         public HandleHolder()
34         {
35             Log.Debug(Globals.LogTag, "HandleHolder() ^^");
36             Interop.Connection.Create(out Handle);
37             Log.Debug(Globals.LogTag, "Handle: " + Handle);
38         }
39
40         ~HandleHolder()
41         {
42             Dispose(false);
43         }
44
45         internal IntPtr GetHandle()
46         {
47             Log.Debug(Globals.LogTag, "handleholder handle = " + Handle);
48             return Handle;
49         }
50         public void Dispose()
51         {
52             Dispose(true);
53             GC.SuppressFinalize(this);
54         }
55
56         private void Dispose(bool disposing)
57         {
58             Log.Debug(Globals.LogTag, ">>> HandleHolder Dispose with " + disposing);
59             Log.Debug(Globals.LogTag, ">>> Handle: " + Handle);
60             if (disposed)
61                 return;
62
63             if (disposing)
64             {
65                 // Free managed objects.
66                 Destroy();
67             }
68             disposed = true;
69         }
70
71         private void Destroy()
72         {
73             Interop.Connection.Destroy(Handle);
74         }
75     }
76
77     internal class ConnectionInternalManager
78     {
79         private bool disposed = false;
80         private static ConnectionInternalManager s_instance = null;
81
82         private EventHandler _ConnectionTypeChanged = null;
83         private EventHandler _IPAddressChanged = null;
84         private EventHandler _EthernetCableStateChanged = null;
85         private EventHandler _ProxyAddressChanged = null;
86
87         private Interop.Connection.ConnectionAddressChangedCallback _connectionAddressChangedCallback;
88         private Interop.Connection.ConnectionTypeChangedCallback _connectionTypeChangedCallback;
89         private Interop.Connection.ConnectionAddressChangedCallback _proxyAddressChangedCallback;
90
91         internal static ConnectionInternalManager Instance
92         {
93             get
94             {
95                 if (s_instance == null)
96                 {
97                     s_instance = new ConnectionInternalManager();
98                 }
99
100                 return s_instance;
101             }
102         }
103
104         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
105         {
106             Log.Info(Globals.LogTag, "In threadlocal delegate");
107             return new HandleHolder();
108         });
109
110         private ConnectionInternalManager()
111         {
112
113         }
114
115         ~ConnectionInternalManager()
116         {
117             Dispose(false);
118         }
119
120         public void Dispose()
121         {
122             Dispose(true);
123             GC.SuppressFinalize(this);
124         }
125
126         private void Dispose(bool disposing)
127         {
128             Log.Debug(Globals.LogTag, ">>> ConnectionInternalManager Dispose with disposing " + disposing + ", disposed " + disposed);
129             Log.Debug(Globals.LogTag, ">>> Handle: " + GetHandle());
130             if (disposed)
131                 return;
132
133             if (disposing)
134             {
135                 // Free managed objects.
136             }
137
138             UnregisterEvents();
139             disposed = true;
140         }
141
142         internal IntPtr GetHandle()
143         {
144             Log.Debug(Globals.LogTag, "GetHandle, Thread Id = " + Thread.CurrentThread.ManagedThreadId);
145             return s_threadName.Value.GetHandle();
146         }
147
148         internal event EventHandler ConnectionTypeChanged
149         {
150             add
151             {
152                 if (_ConnectionTypeChanged == null)
153                 {
154                     ConnectionTypeChangedStart();
155                 }
156
157                 _ConnectionTypeChanged += value;
158             }
159             remove
160             {
161                 _ConnectionTypeChanged -= value;
162                 if (_ConnectionTypeChanged == null)
163                 {
164                     ConnectionTypeChangedStop();
165                 }
166             }
167         }
168
169         private void ConnectionTypeChangedStart()
170         {
171             _connectionTypeChangedCallback = (ConnectionType type, IntPtr user_data) =>
172             {
173                 if (_ConnectionTypeChanged != null)
174                 {
175                     _ConnectionTypeChanged(null, new ConnectionTypeEventArgs(type));
176                 }
177             };
178
179             int ret = Interop.Connection.SetTypeChangedCallback(GetHandle(), _connectionTypeChangedCallback, IntPtr.Zero);
180             if ((ConnectionError)ret != ConnectionError.None)
181             {
182                 Log.Error(Globals.LogTag, "It failed to register connection type changed callback, " + (ConnectionError)ret);
183                 ConnectionErrorFactory.ThrowConnectionException(ret);
184             }
185         }
186
187         private void ConnectionTypeChangedStop()
188         {
189             int ret = Interop.Connection.UnsetTypeChangedCallback(GetHandle());
190             if ((ConnectionError)ret != ConnectionError.None)
191             {
192                 Log.Error(Globals.LogTag, "It failed to unregister connection type changed callback, " + (ConnectionError)ret);
193                 ConnectionErrorFactory.ThrowConnectionException(ret);
194             }
195         }
196
197         internal event EventHandler EthernetCableStateChanged
198         {
199             add
200             {
201                 if (_EthernetCableStateChanged == null)
202                 {
203                     EthernetCableStateChangedStart();
204                 }
205                 _EthernetCableStateChanged += value;
206             }
207             remove
208             {
209                 _EthernetCableStateChanged -= value;
210                 if (_EthernetCableStateChanged == null)
211                 {
212                     EthernetCableStateChangedStop();
213                 }
214             }
215         }
216
217         private void EthernetCableStateChangedStart()
218         {
219             int ret = Interop.Connection.SetEthernetCableStateChagedCallback(GetHandle(), EthernetCableStateChangedCallback, IntPtr.Zero);
220             if ((ConnectionError)ret != ConnectionError.None)
221             {
222                 Log.Error(Globals.LogTag, "It failed to register ethernet cable state changed callback, " + (ConnectionError)ret);
223                 ConnectionErrorFactory.ThrowConnectionException(ret);
224             }
225         }
226
227         private void EthernetCableStateChangedStop()
228         {
229             int ret = Interop.Connection.UnsetEthernetCableStateChagedCallback(GetHandle());
230             if ((ConnectionError)ret != ConnectionError.None)
231             {
232                 Log.Error(Globals.LogTag, "It failed to unregister ethernet cable state changed callback, " + (ConnectionError)ret);
233                 ConnectionErrorFactory.ThrowConnectionException(ret);
234             }
235         }
236
237         private void EthernetCableStateChangedCallback(EthernetCableState state, IntPtr user_data)
238         {
239             if (_EthernetCableStateChanged != null)
240             {
241                 _EthernetCableStateChanged(null, new EthernetCableStateEventArgs(state));
242             }
243         }
244
245         internal event EventHandler IPAddressChanged
246         {
247             add
248             {
249                 if (_IPAddressChanged == null)
250                 {
251                     IPAddressChangedStart();
252                 }
253                 _IPAddressChanged += value;
254             }
255
256             remove
257             {
258                 _IPAddressChanged -= value;
259                 if (_IPAddressChanged == null)
260                 {
261                     IPAddressChangedStop();
262                 }
263             }
264         }
265
266         private void IPAddressChangedStart()
267         {
268             _connectionAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
269             {
270                 if (_IPAddressChanged != null)
271                 {
272                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
273                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
274
275                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
276                     {
277                         _IPAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
278                     }
279                 }
280             };
281
282             int ret = Interop.Connection.SetIPAddressChangedCallback(GetHandle(), _connectionAddressChangedCallback, IntPtr.Zero);
283             if ((ConnectionError)ret != ConnectionError.None)
284             {
285                 Log.Error(Globals.LogTag, "It failed to register callback for changing IP address, " + (ConnectionError)ret);
286             }
287         }
288
289         private void IPAddressChangedStop()
290         {
291             int ret = Interop.Connection.UnsetIPAddressChangedCallback(GetHandle());
292             if ((ConnectionError)ret != ConnectionError.None)
293             {
294                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing IP address, " + (ConnectionError)ret);
295             }
296         }
297
298         internal event EventHandler ProxyAddressChanged
299         {
300             add
301             {
302                 //Console.WriteLine("ProxyAddressChanged Add **");
303                 if (_ProxyAddressChanged == null)
304                 {
305                     ProxyAddressChangedStart();
306                 }
307
308                 _ProxyAddressChanged += value;
309             }
310             remove
311             {
312                 //Console.WriteLine("ProxyAddressChanged Remove");
313                 _ProxyAddressChanged -= value;
314                 if (_ProxyAddressChanged == null)
315                 {
316                     ProxyAddressChangedStop();
317                 }
318             }
319         }
320
321         private void ProxyAddressChangedStart()
322         {
323             _proxyAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
324             {
325                 if (_ProxyAddressChanged != null)
326                 {
327                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
328                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
329
330                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
331                     {
332                         _ProxyAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
333                     }
334                 }
335             };
336
337             int ret = Interop.Connection.SetProxyAddressChangedCallback(GetHandle(), _proxyAddressChangedCallback, IntPtr.Zero);
338             if ((ConnectionError)ret != ConnectionError.None)
339             {
340                 Log.Error(Globals.LogTag, "It failed to register callback for changing proxy address, " + (ConnectionError)ret);
341             }
342         }
343
344         private void ProxyAddressChangedStop()
345         {
346             int ret = Interop.Connection.UnsetProxyAddressChangedCallback(GetHandle());
347             if ((ConnectionError)ret != ConnectionError.None)
348             {
349                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing proxy address, " + (ConnectionError)ret);
350             }
351         }
352
353         private void UnregisterEvents()
354         {
355             if (_ConnectionTypeChanged != null)
356             {
357                 ConnectionTypeChangedStop();
358             }
359             if (_IPAddressChanged != null)
360             {
361                 IPAddressChangedStop();
362             }
363             if (_EthernetCableStateChanged != null)
364             {
365                 EthernetCableStateChangedStop();
366             }
367             if (_ProxyAddressChanged != null)
368             {
369                 ProxyAddressChangedStop();
370             }
371         }
372
373         internal int GetProfileIterator(ProfileListType type, out IntPtr iterator)
374         {
375             return Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
376         }
377
378         internal bool HasNext(IntPtr iterator)
379         {
380             return Interop.Connection.HasNextProfileIterator(iterator);
381         }
382
383         internal int NextProfileIterator(IntPtr iterator, out IntPtr profileHandle)
384         {
385             return Interop.Connection.GetNextProfileIterator(iterator, out profileHandle);
386         }
387
388         internal int DestoryProfileIterator(IntPtr iterator)
389         {
390             return Interop.Connection.DestroyProfileIterator(iterator);
391         }
392
393         internal string GetIPAddress(AddressFamily family)
394         {
395             IntPtr ip;
396             int ret = Interop.Connection.GetIPAddress(GetHandle(), (int)family, out ip);
397             if ((ConnectionError)ret != ConnectionError.None)
398             {
399                 Log.Error(Globals.LogTag, "It failed to get IP address, " + (ConnectionError)ret);
400                 ConnectionErrorFactory.ThrowConnectionException(ret);
401             }
402             string result = Marshal.PtrToStringAnsi(ip);
403             Interop.Libc.Free(ip);
404             return result;
405         }
406
407         internal string GetProxy(AddressFamily family)
408         {
409             IntPtr ip;
410             int ret = Interop.Connection.GetProxy(GetHandle(), (int)family, out ip);
411             if ((ConnectionError)ret != ConnectionError.None)
412             {
413                 Log.Error(Globals.LogTag, "It failed to get proxy, " + (ConnectionError)ret);
414                 ConnectionErrorFactory.ThrowConnectionException(ret);
415             }
416             string result = Marshal.PtrToStringAnsi(ip);
417             Interop.Libc.Free(ip);
418             return result;
419         }
420
421         internal string GetMacAddress(ConnectionType type)
422         {
423             IntPtr ip;
424             int ret = Interop.Connection.GetMacAddress(GetHandle(), (int)type, out ip);
425             if ((ConnectionError)ret != ConnectionError.None)
426             {
427                 Log.Error(Globals.LogTag, "It failed to get mac address, " + (ConnectionError)ret);
428                 ConnectionErrorFactory.ThrowConnectionException(ret);
429             }
430             string result = Marshal.PtrToStringAnsi(ip);
431             Interop.Libc.Free(ip);
432             return result;
433         }
434
435         internal ConnectionType ConnectionType
436         {
437             get
438             {
439                 int type = 0;
440                 Log.Debug(Globals.LogTag, "Handle: " + GetHandle());
441                 int ret = Interop.Connection.GetType(GetHandle(), out type);
442                 if ((ConnectionError)ret != ConnectionError.None)
443                 {
444                     Log.Error(Globals.LogTag, "It failed to get connection type, " + (ConnectionError)ret);
445                     ConnectionErrorFactory.ThrowConnectionException(ret);
446                 }
447                 return (ConnectionType)type;
448             }
449         }
450
451         internal CellularState CellularState
452         {
453             get
454             {
455                 int type = 0;
456                 Log.Debug(Globals.LogTag, "CellularState Handle: " + GetHandle());
457                 int ret = Interop.Connection.GetCellularState(GetHandle(), out type);
458                 if ((ConnectionError)ret != ConnectionError.None)
459                 {
460                     Log.Error(Globals.LogTag, "It failed to get cellular state, " + (ConnectionError)ret);
461                     ConnectionErrorFactory.ThrowConnectionException(ret);
462                 }
463                 return (CellularState)type;
464             }
465         }
466
467         internal ConnectionState WiFiState
468         {
469             get
470             {
471                 int type = 0;
472                 int ret = Interop.Connection.GetWiFiState(GetHandle(), out type);
473                 if ((ConnectionError)ret != ConnectionError.None)
474                 {
475                     Log.Error(Globals.LogTag, "It failed to get wifi state, " + (ConnectionError)ret);
476                     ConnectionErrorFactory.ThrowConnectionException(ret);
477                 }
478                 return (ConnectionState)type;
479             }
480         }
481
482         internal ConnectionState BluetoothState
483         {
484             get
485             {
486                 int type = 0;
487                 int ret = Interop.Connection.GetBtState(GetHandle(), out type);
488                 if ((ConnectionError)ret != ConnectionError.None)
489                 {
490                     Log.Error(Globals.LogTag, "It failed to get bluetooth state, " + (ConnectionError)ret);
491                     ConnectionErrorFactory.ThrowConnectionException(ret);
492                 }
493                 return (ConnectionState)type;
494             }
495         }
496
497         internal ConnectionState EthernetState
498         {
499             get
500             {
501                 int type = 0;
502                 int ret = Interop.Connection.GetEthernetState(GetHandle(), out type);
503                 if ((ConnectionError)ret != ConnectionError.None)
504                 {
505                     Log.Error(Globals.LogTag, "It failed to get ethernet state, " + (ConnectionError)ret);
506                     ConnectionErrorFactory.ThrowConnectionException(ret);
507                 }
508                 return (ConnectionState)type;
509             }
510         }
511
512         internal EthernetCableState EthernetCableState
513         {
514             get
515             {
516                 int type = 0;
517                 int ret = Interop.Connection.GetEthernetCableState(GetHandle(), out type);
518                 if ((ConnectionError)ret != ConnectionError.None)
519                 {
520                     Log.Error(Globals.LogTag, "It failed to get ethernet cable state, " + (ConnectionError)ret);
521                     ConnectionErrorFactory.ThrowConnectionException(ret);
522                 }
523                 return (EthernetCableState)type;
524             }
525         }
526
527         internal IntPtr CreateCellularProfile(ConnectionProfileType type, string keyword)
528         {
529             Log.Error(Globals.LogTag, "CreateCellularProfile, " + type + ", " + keyword);
530             IntPtr connectionHandle = GetHandle();
531             if (connectionHandle == IntPtr.Zero)
532             {
533                 Log.Error(Globals.LogTag, "It failed to create connection handle");
534                 throw new InvalidOperationException("Invalid connection handle");
535             }
536
537             IntPtr handle = IntPtr.Zero;
538             int ret = Interop.ConnectionProfile.Create((int)type, keyword, out handle);
539             if ((ConnectionError)ret != ConnectionError.None)
540             {
541                 Log.Error(Globals.LogTag, "It failed to Create profile, " + (ConnectionError)ret);
542                 ConnectionErrorFactory.ThrowConnectionException(ret);
543             }
544
545             return handle;
546         }
547
548         internal void AddCellularProfile(CellularProfile profile)
549         {
550             if (profile.Type == ConnectionProfileType.Cellular)
551             {
552                 int ret = Interop.Connection.AddProfile(GetHandle(), profile.ProfileHandle);
553                 if ((ConnectionError)ret != ConnectionError.None)
554                 {
555                     Log.Error(Globals.LogTag, "Failed to add cellular profile, " + (ConnectionError)ret);
556                     ConnectionErrorFactory.ThrowConnectionException(ret);
557                 }
558             }
559
560             else
561             {
562                 throw new InvalidOperationException("Profile type is not cellular");
563             }
564         }
565
566         internal void RemoveProfile(ConnectionProfile profile)
567         {
568             int ret = Interop.Connection.RemoveProfile(GetHandle(), profile.ProfileHandle);
569             if ((ConnectionError)ret != ConnectionError.None)
570             {
571                 Log.Error(Globals.LogTag, "It failed to remove profile, " + (ConnectionError)ret);
572                 ConnectionErrorFactory.ThrowConnectionException(ret);
573             }
574         }
575
576         internal void UpdateProfile(ConnectionProfile profile)
577         {
578             int ret = Interop.Connection.UpdateProfile(GetHandle(), profile.ProfileHandle);
579             if ((ConnectionError)ret != ConnectionError.None)
580             {
581                 Log.Error(Globals.LogTag, "It failed to update profile, " + (ConnectionError)ret);
582                 ConnectionErrorFactory.ThrowConnectionException(ret);
583             }
584         }
585
586         internal ConnectionProfile GetCurrentProfile()
587         {
588             IntPtr ProfileHandle;
589             int ret = Interop.Connection.GetCurrentProfile(GetHandle(), out ProfileHandle);
590             if ((ConnectionError)ret != ConnectionError.None)
591             {
592                 Log.Error(Globals.LogTag, "It failed to get current profile, " + (ConnectionError)ret);
593                 ConnectionErrorFactory.ThrowConnectionException(ret);
594             }
595             ConnectionProfile Profile = new ConnectionProfile(ProfileHandle);
596             return Profile;
597         }
598
599         internal ConnectionProfile GetDefaultCellularProfile(CellularServiceType type)
600         {
601             IntPtr ProfileHandle;
602             int ret = Interop.Connection.GetDefaultCellularServiceProfile(GetHandle(), (int)type, out ProfileHandle);
603             if ((ConnectionError)ret != ConnectionError.None)
604             {
605                 Log.Error(Globals.LogTag, "Error: " + ret);
606                 Log.Error(Globals.LogTag, "It failed to get default cellular profile, " + (ConnectionError)ret);
607                 ConnectionErrorFactory.ThrowConnectionException(ret);
608             }
609             CellularProfile Profile = new CellularProfile(ProfileHandle);
610             return Profile;
611         }
612
613         internal Task SetDefaultCellularProfile(CellularServiceType type, ConnectionProfile profile)
614         {
615             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
616             Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
617             {
618                 if (Result != ConnectionError.None)
619                 {
620                     Log.Error(Globals.LogTag, "Error occurs during set default cellular profile, " + Result);
621                     task.SetException(new InvalidOperationException("Error occurs during set default cellular profile, " + Result));
622                 }
623
624                 task.SetResult(true);
625             };
626
627             int ret = Interop.Connection.SetDefaultCellularServiceProfileAsync(GetHandle(), (int)type, profile.ProfileHandle, Callback, (IntPtr)0);
628             if ((ConnectionError)ret != ConnectionError.None)
629             {
630                 Log.Error(Globals.LogTag, "It failed to set default cellular profile, " + (ConnectionError)ret);
631                 ConnectionErrorFactory.ThrowConnectionException(ret);
632             }
633
634             return task.Task;
635         }
636
637
638         internal Task<IEnumerable<ConnectionProfile>> GetProfileListAsync(ProfileListType type)
639         {
640             var task = new TaskCompletionSource<IEnumerable<ConnectionProfile>>();
641
642             List<ConnectionProfile> Result = new List<ConnectionProfile>();
643             IntPtr iterator;
644             int ret = Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
645             if ((ConnectionError)ret != ConnectionError.None)
646             {
647                 Log.Error(Globals.LogTag, "It failed to get profile iterator, " + (ConnectionError)ret);
648             }
649
650             while (Interop.Connection.HasNextProfileIterator(iterator))
651             {
652                 IntPtr nextH;
653                 IntPtr profileH;
654                 Interop.Connection.GetNextProfileIterator(iterator, out nextH);
655                 Interop.ConnectionProfile.Clone(out profileH, nextH);
656
657                 int profileType;
658                 Interop.ConnectionProfile.GetType(profileH, out profileType);
659
660                 if ((ConnectionProfileType)profileType == ConnectionProfileType.WiFi)
661                 {
662                     WiFiProfile cur = new WiFiProfile(profileH);
663                     Result.Add(cur);
664                 }
665                 else if ((ConnectionProfileType)profileType == ConnectionProfileType.Cellular)
666                 {
667                     CellularProfile cur = new CellularProfile(profileH);
668                     Result.Add(cur);
669                 }
670                 else {
671                     ConnectionProfile cur = new ConnectionProfile(profileH);
672                     Result.Add(cur);
673                 }
674             }
675             Interop.Connection.DestroyProfileIterator(iterator);
676             task.SetResult(Result);
677             return task.Task;
678         }
679
680         internal Task OpenProfileAsync(ConnectionProfile profile)
681         {
682             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
683             Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
684             {
685                 if (Result != ConnectionError.None)
686                 {
687                     Log.Error(Globals.LogTag, "Error occurs during connecting profile, " + Result);
688                     task.SetException(new InvalidOperationException("Error occurs during connecting profile, " + Result));
689                 }
690
691                 task.SetResult(true);
692             };
693
694             int ret = Interop.Connection.OpenProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
695             if ((ConnectionError)ret != ConnectionError.None)
696             {
697                 Log.Error(Globals.LogTag, "It failed to connect profile, " + (ConnectionError)ret);
698                 ConnectionErrorFactory.ThrowConnectionException(ret);
699             }
700
701             return task.Task;
702         }
703
704         internal Task CloseProfileAsync(ConnectionProfile profile)
705         {
706             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
707             Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
708             {
709                 if (Result != ConnectionError.None)
710                 {
711                     Log.Error(Globals.LogTag, "Error occurs during disconnecting profile, " + Result);
712                     task.SetException(new InvalidOperationException("Error occurs during disconnecting profile, " + Result));
713                 }
714
715                 task.SetResult(true);
716             };
717
718             int ret = Interop.Connection.CloseProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
719             if ((ConnectionError)ret != ConnectionError.None)
720             {
721                 Log.Error(Globals.LogTag, "It failed to disconnect profile, " + (ConnectionError)ret);
722                 ConnectionErrorFactory.ThrowConnectionException(ret);
723             }
724
725             return task.Task;
726         }
727     }
728 }