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