[Connection][WiFi] Fix exception handling in async methods (#154)
[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 using Tizen.Applications;
26
27 namespace Tizen.Network.Connection
28 {
29     class HandleHolder
30     {
31         private IntPtr Handle;
32         private int _tid;
33
34         public HandleHolder()
35         {
36             _tid = Thread.CurrentThread.ManagedThreadId;
37             Log.Info(Globals.LogTag, "PInvoke connection_create for Thread " + _tid);
38             int ret = Interop.Connection.Create(_tid, out Handle);
39             Log.Info(Globals.LogTag, "Handle: " + Handle);
40             if(ret != (int)ConnectionError.None)
41             {
42                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
43                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
44                 ConnectionErrorFactory.ThrowConnectionException(ret);
45             }
46         }
47
48         ~HandleHolder()
49         {
50             Destroy();
51         }
52
53         internal IntPtr GetHandle()
54         {
55             Log.Debug(Globals.LogTag, "handleholder handle = " + Handle);
56             return Handle;
57         }
58
59         private void Destroy()
60         {
61
62             Log.Info(Globals.LogTag, "PInvoke connection_destroy for Thread " + _tid);
63             Interop.Connection.Destroy(_tid, Handle);
64             if (Handle != IntPtr.Zero)
65             {
66                 Handle = IntPtr.Zero;
67             }
68         }
69     }
70
71     internal class ConnectionInternalManager
72     {
73         private static readonly Lazy<ConnectionInternalManager> s_instance =
74             new Lazy<ConnectionInternalManager>(() => new ConnectionInternalManager());
75
76         private EventHandler<ConnectionTypeEventArgs> _ConnectionTypeChanged = null;
77         private EventHandler<AddressEventArgs> _IPAddressChanged = null;
78         private EventHandler<EthernetCableStateEventArgs> _EthernetCableStateChanged = null;
79         private EventHandler<AddressEventArgs> _ProxyAddressChanged = null;
80
81         private Interop.Connection.ConnectionAddressChangedCallback _connectionAddressChangedCallback;
82         private Interop.Connection.ConnectionTypeChangedCallback _connectionTypeChangedCallback;
83         private Interop.Connection.ConnectionAddressChangedCallback _proxyAddressChangedCallback;
84         private Interop.Connection.EthernetCableStateChangedCallback _ethernetCableStateChangedCallback;
85
86         private TizenSynchronizationContext context = new TizenSynchronizationContext();
87
88         internal static ConnectionInternalManager Instance
89         {
90             get
91             {
92                 return s_instance.Value;
93             }
94         }
95
96         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
97         {
98             Log.Info(Globals.LogTag, "In threadlocal delegate");
99             return new HandleHolder();
100         });
101
102         private ConnectionInternalManager()
103         {
104             Log.Info(Globals.LogTag, "ConnectionInternalManager constructor");
105         }
106
107         ~ConnectionInternalManager()
108         {
109             UnregisterEvents();
110         }
111
112         internal IntPtr GetHandle()
113         {
114             return s_threadName.Value.GetHandle();
115         }
116
117         internal event EventHandler<ConnectionTypeEventArgs> ConnectionTypeChanged
118         {
119             add
120             {
121                 context.Post((x) =>
122                 {
123                     if (_ConnectionTypeChanged == null)
124                     {
125                         try
126                         {
127                             ConnectionTypeChangedStart();
128                         }
129                         catch (Exception e)
130                         {
131                             Log.Error(Globals.LogTag, "Exception on adding ConnectionTypeChanged\n" + e.ToString());
132                             return;
133                         }
134                     }
135                     _ConnectionTypeChanged += value;
136                 }, null);
137             }
138             remove
139             {
140                 context.Post((x) =>
141                 {
142                     _ConnectionTypeChanged -= value;
143                     if (_ConnectionTypeChanged == null)
144                     {
145                         try
146                         {
147                             ConnectionTypeChangedStop();
148                         }
149                         catch (Exception e)
150                         {
151                             Log.Error(Globals.LogTag, "Exception on removing ConnectionTypeChanged\n" + e.ToString());
152                         }
153                     }
154                 }, null);
155             }
156         }
157
158         private void ConnectionTypeChangedStart()
159         {
160             Log.Info(Globals.LogTag, "Register ConnectionTypeChanged");
161             _connectionTypeChangedCallback = (ConnectionType type, IntPtr user_data) =>
162             {
163                 if (_ConnectionTypeChanged != null)
164                 {
165                     _ConnectionTypeChanged(null, new ConnectionTypeEventArgs(type));
166                 }
167             };
168
169             int ret = Interop.Connection.SetTypeChangedCallback(GetHandle(), _connectionTypeChangedCallback, IntPtr.Zero);
170             if ((ConnectionError)ret != ConnectionError.None)
171             {
172                 Log.Error(Globals.LogTag, "It failed to register connection type changed callback, " + (ConnectionError)ret);
173                 ConnectionErrorFactory.ThrowConnectionException(ret);
174             }
175         }
176
177         private void ConnectionTypeChangedStop()
178         {
179             Log.Info(Globals.LogTag, "Unregister ConnectionTypeChanged");
180             int ret = Interop.Connection.UnsetTypeChangedCallback(GetHandle());
181             if ((ConnectionError)ret != ConnectionError.None)
182             {
183                 Log.Error(Globals.LogTag, "It failed to unregister connection type changed callback, " + (ConnectionError)ret);
184                 ConnectionErrorFactory.ThrowConnectionException(ret);
185             }
186         }
187
188         internal event EventHandler<EthernetCableStateEventArgs> EthernetCableStateChanged
189         {
190             add
191             {
192                 context.Post((x) =>
193                 {
194                     if (_EthernetCableStateChanged == null)
195                     {
196                         try
197                         {
198                             EthernetCableStateChangedStart();
199                         }
200                         catch (Exception e)
201                         {
202                             Log.Error(Globals.LogTag, "Exception on adding EthernetCableStateChanged\n" + e.ToString());
203                             return;
204                         }
205                     }
206                     _EthernetCableStateChanged += value;
207                 }, null);
208             }
209             remove
210             {
211                 context.Post((x) =>
212                 {
213                     _EthernetCableStateChanged -= value;
214                     if (_EthernetCableStateChanged == null)
215                     {
216                         try
217                         {
218                             EthernetCableStateChangedStop();
219                         }
220                         catch (Exception e)
221                         {
222                             Log.Error(Globals.LogTag, "Exception on removing EthernetCableStateChanged\n" + e.ToString());
223                         }
224                     }
225                 }, null);
226             }
227         }
228
229         private void EthernetCableStateChangedStart()
230         {
231             Log.Info(Globals.LogTag, "Register EthernetCableStateChanged");
232             _ethernetCableStateChangedCallback = (EthernetCableState state, IntPtr user_data) =>
233             {
234                 if (_EthernetCableStateChanged != null)
235                 {
236                     _EthernetCableStateChanged(null, new EthernetCableStateEventArgs(state));
237                 }
238             };
239             int ret = Interop.Connection.SetEthernetCableStateChagedCallback(GetHandle(),
240                     _ethernetCableStateChangedCallback, IntPtr.Zero);
241             if ((ConnectionError)ret != ConnectionError.None)
242             {
243                 Log.Error(Globals.LogTag,
244                         "It failed to register ethernet cable state changed callback, " +
245                         (ConnectionError)ret);
246                 ConnectionErrorFactory.ThrowConnectionException(ret);
247             }
248         }
249
250         private void EthernetCableStateChangedStop()
251         {
252             Log.Info(Globals.LogTag, "Unregister EthernetCableStateChanged");
253             int ret = Interop.Connection.UnsetEthernetCableStateChagedCallback(GetHandle());
254             if ((ConnectionError)ret != ConnectionError.None)
255             {
256                 Log.Error(Globals.LogTag,
257                         "It failed to unregister ethernet cable state changed callback, " + 
258                         (ConnectionError)ret);
259                 ConnectionErrorFactory.ThrowConnectionException(ret);
260             }
261         }
262
263         internal event EventHandler<AddressEventArgs> IPAddressChanged
264         {
265             add
266             {
267                 context.Post((x) =>
268                 {
269                     if (_IPAddressChanged == null)
270                     {
271                         try
272                         {
273                             IPAddressChangedStart();
274                         }
275                         catch (Exception e)
276                         {
277                             Log.Error(Globals.LogTag, "Exception on adding IPAddressChanged\n" + e.ToString());
278                             return;
279                         }
280                     }
281                     _IPAddressChanged += value;
282                 }, null);
283             }
284
285             remove
286             {
287                 context.Post((x) =>
288                 {
289                     _IPAddressChanged -= value;
290                     if (_IPAddressChanged == null)
291                     {
292                         try
293                         {
294                             IPAddressChangedStop();
295                         }
296                         catch (Exception e)
297                         {
298                             Log.Error(Globals.LogTag, "Exception on removing IPAddressChanged\n" + e.ToString());
299                         }
300                     }
301                 }, null);
302             }
303         }
304
305         private void IPAddressChangedStart()
306         {
307             Log.Info(Globals.LogTag, "Register IPAddressChanged");
308             _connectionAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
309             {
310                 if (_IPAddressChanged != null)
311                 {
312                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
313                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
314
315                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
316                     {
317                         _IPAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
318                     }
319                 }
320             };
321
322             int ret = Interop.Connection.SetIPAddressChangedCallback(GetHandle(), _connectionAddressChangedCallback, IntPtr.Zero);
323             if ((ConnectionError)ret != ConnectionError.None)
324             {
325                 Log.Error(Globals.LogTag, "It failed to register callback for changing IP address, " + (ConnectionError)ret);
326             }
327         }
328
329         private void IPAddressChangedStop()
330         {
331             Log.Info(Globals.LogTag, "Unregister IPAddressChanged");
332             int ret = Interop.Connection.UnsetIPAddressChangedCallback(GetHandle());
333             if ((ConnectionError)ret != ConnectionError.None)
334             {
335                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing IP address, " + (ConnectionError)ret);
336             }
337         }
338
339         internal event EventHandler<AddressEventArgs> ProxyAddressChanged
340         {
341             add
342             {
343                 context.Post((x) =>
344                 {
345                     if (_ProxyAddressChanged == null)
346                     {
347                         try
348                         {
349                             ProxyAddressChangedStart();
350                         }
351                         catch (Exception e)
352                         {
353                             Log.Error(Globals.LogTag, "Exception on adding ProxyAddressChanged\n" + e.ToString());
354                             return;
355                         }
356                     }
357                     _ProxyAddressChanged += value;
358                 }, null);
359             }
360             remove
361             {
362                 context.Post((x) =>
363                 {
364                     _ProxyAddressChanged -= value;
365                     if (_ProxyAddressChanged == null)
366                     {
367                         try
368                         {
369                             ProxyAddressChangedStop();
370                         }
371                         catch (Exception e)
372                         {
373                             Log.Error(Globals.LogTag, "Exception on removing ProxyAddressChanged\n" + e.ToString());
374                         }
375                     }
376                 }, null);
377             }
378         }
379
380         private void ProxyAddressChangedStart()
381         {
382             Log.Info(Globals.LogTag, "Register ProxyAddressChanged");
383             _proxyAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
384             {
385                 if (_ProxyAddressChanged != null)
386                 {
387                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
388                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
389
390                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
391                     {
392                         _ProxyAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
393                     }
394                 }
395             };
396
397             int ret = Interop.Connection.SetProxyAddressChangedCallback(GetHandle(), _proxyAddressChangedCallback, IntPtr.Zero);
398             if ((ConnectionError)ret != ConnectionError.None)
399             {
400                 Log.Error(Globals.LogTag, "It failed to register callback for changing proxy address, " + (ConnectionError)ret);
401             }
402         }
403
404         private void ProxyAddressChangedStop()
405         {
406             Log.Info(Globals.LogTag, "Unregister ProxyAddressChanged");
407             int ret = Interop.Connection.UnsetProxyAddressChangedCallback(GetHandle());
408             if ((ConnectionError)ret != ConnectionError.None)
409             {
410                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing proxy address, " + (ConnectionError)ret);
411             }
412         }
413
414         private void UnregisterEvents()
415         {
416             if (_ConnectionTypeChanged != null)
417             {
418                 ConnectionTypeChangedStop();
419             }
420             if (_IPAddressChanged != null)
421             {
422                 IPAddressChangedStop();
423             }
424             if (_EthernetCableStateChanged != null)
425             {
426                 EthernetCableStateChangedStop();
427             }
428             if (_ProxyAddressChanged != null)
429             {
430                 ProxyAddressChangedStop();
431             }
432         }
433
434         internal int GetProfileIterator(ProfileListType type, out IntPtr iterator)
435         {
436             return Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
437         }
438
439         internal bool HasNext(IntPtr iterator)
440         {
441             return Interop.Connection.HasNextProfileIterator(iterator);
442         }
443
444         internal int NextProfileIterator(IntPtr iterator, out IntPtr profileHandle)
445         {
446             return Interop.Connection.GetNextProfileIterator(iterator, out profileHandle);
447         }
448
449         internal int DestoryProfileIterator(IntPtr iterator)
450         {
451             return Interop.Connection.DestroyProfileIterator(iterator);
452         }
453
454         internal System.Net.IPAddress GetIPAddress(AddressFamily family)
455         {
456             Log.Info(Globals.LogTag, "GetIPAddress " + family);
457             IntPtr ip;
458             int ret = Interop.Connection.GetIPAddress(GetHandle(), (int)family, out ip);
459             if ((ConnectionError)ret != ConnectionError.None)
460             {
461                 Log.Error(Globals.LogTag, "It failed to get IP address, " + (ConnectionError)ret);
462                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
463                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
464                 ConnectionErrorFactory.ThrowConnectionException(ret);
465             }
466
467             string result = Marshal.PtrToStringAnsi(ip);
468             Interop.Libc.Free(ip);
469             Log.Info(Globals.LogTag, "IPAddress " + result + " (" + result.Length + ")");
470             if (result.Length == 0)
471             {
472                 if (family == AddressFamily.IPv4)
473                     return System.Net.IPAddress.Parse("0.0.0.0");
474                 else
475                     return System.Net.IPAddress.Parse("::");
476             }
477             return System.Net.IPAddress.Parse(result);
478         }
479
480         internal IEnumerable<System.Net.IPAddress> GetAllIPv6Addresses(ConnectionType type)
481         {
482             Log.Debug(Globals.LogTag, "GetAllIPv6Addresses");
483             List<System.Net.IPAddress> ipList = new List<System.Net.IPAddress>();
484             Interop.Connection.IPv6AddressCallback callback = (IntPtr ipv6Address, IntPtr userData) =>
485             {
486                 if (ipv6Address != IntPtr.Zero)
487                 {
488                     string ipv6 = Marshal.PtrToStringAnsi(ipv6Address);
489                     if (ipv6.Length == 0)
490                         ipList.Add(System.Net.IPAddress.Parse("::"));
491                     else
492                         ipList.Add(System.Net.IPAddress.Parse(ipv6));
493                     return true;
494                 }
495                 return false;
496             };
497
498             int ret = Interop.Connection.GetAllIPv6Addresses(GetHandle(), (int)type, callback, IntPtr.Zero);
499             if (ret != (int)ConnectionError.None)
500             {
501                 Log.Error(Globals.LogTag, "Failed to get all IPv6 addresses, Error - " + (ConnectionError)ret);
502                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
503                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
504                 ConnectionErrorFactory.ThrowConnectionException(ret);
505             }
506
507             return ipList;
508         }
509
510         internal string GetProxy(AddressFamily family)
511         {
512             Log.Debug(Globals.LogTag, "GetProxy " + family);
513             IntPtr ip;
514             int ret = Interop.Connection.GetProxy(GetHandle(), (int)family, out ip);
515             if ((ConnectionError)ret != ConnectionError.None)
516             {
517                 Log.Error(Globals.LogTag, "It failed to get proxy, " + (ConnectionError)ret);
518                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
519                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
520                 ConnectionErrorFactory.ThrowConnectionException(ret);
521             }
522
523             string result = Marshal.PtrToStringAnsi(ip);
524             Interop.Libc.Free(ip);
525             return result;
526         }
527
528         internal string GetMacAddress(ConnectionType type)
529         {
530             Log.Info(Globals.LogTag, "GetMacAddress " + type);
531             IntPtr mac;
532             int ret = Interop.Connection.GetMacAddress(GetHandle(), (int)type, out mac);
533             if ((ConnectionError)ret != ConnectionError.None)
534             {
535                 Log.Error(Globals.LogTag, "It failed to get mac address, " + (ConnectionError)ret);
536                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.ethernet");
537                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
538                 ConnectionErrorFactory.ThrowConnectionException(ret);
539             }
540
541             string result = Marshal.PtrToStringAnsi(mac);
542             Interop.Libc.Free(mac);
543             return result;
544         }
545
546         internal long GetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
547         {
548             Log.Debug(Globals.LogTag, "GetStatistics " + connectionType + ", " + statisticsType);
549             long size;
550             int ret = Interop.Connection.GetStatistics(GetHandle(), (int)connectionType,
551                     (int)statisticsType, out size);
552             if ((ConnectionError)ret != ConnectionError.None)
553             {
554                 Log.Error(Globals.LogTag, "It failed to get statistics, " + (ConnectionError)ret);
555                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
556                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
557                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
558                 ConnectionErrorFactory.ThrowConnectionException(ret);
559             }
560             return size;
561         }
562
563         internal void ResetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
564         {
565             Log.Debug(Globals.LogTag, "ResetStatistics " + connectionType + ", " + statisticsType);
566             int ret = Interop.Connection.ResetStatistics(GetHandle(), (int)connectionType,
567                     (int)statisticsType);
568             if ((ConnectionError)ret != ConnectionError.None)
569             {
570                 Log.Error(Globals.LogTag, "It failed to reset statistics, " + (ConnectionError)ret);
571                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
572                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
573                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
574                 ConnectionErrorFactory.ThrowConnectionException(ret);
575             }
576         }
577
578         internal void AddRoute(AddressFamily family, string interfaceName, System.Net.IPAddress address, System.Net.IPAddress gateway)
579         {
580             if (interfaceName != null && address != null && gateway != null)
581             {
582                 Log.Debug(Globals.LogTag, "AddRoute " + family + ", " + interfaceName + ", " + address + ", " + gateway);
583                 int ret = Interop.Connection.AddRoute(GetHandle(), family, interfaceName, address.ToString(), gateway.ToString());
584                 if ((ConnectionError)ret != ConnectionError.None)
585                 {
586                     Log.Error(Globals.LogTag, "It failed to add route to the routing table, " + (ConnectionError)ret);
587                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
588                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
589                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
590                     ConnectionErrorFactory.ThrowConnectionException(ret);
591                 }
592             }
593
594             else
595             {
596                 throw new ArgumentNullException("Arguments are null");
597             }
598         }
599
600         internal void RemoveRoute(AddressFamily family, string interfaceName, System.Net.IPAddress address, System.Net.IPAddress gateway)
601         {
602             if (interfaceName != null && address != null && gateway != null)
603             {
604                 Log.Debug(Globals.LogTag, "RemoveRoute " + family + ", " + interfaceName + ", " + address + ", " + gateway);
605                 int ret = Interop.Connection.RemoveRoute(GetHandle(), family, interfaceName, address.ToString(), gateway.ToString());
606                 if ((ConnectionError)ret != ConnectionError.None)
607                 {
608                     Log.Error(Globals.LogTag, "It failed to remove route from the routing table, " + (ConnectionError)ret);
609                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
610                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
611                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
612                     ConnectionErrorFactory.ThrowConnectionException(ret);
613                 }
614             }
615
616             else
617             {
618                 throw new ArgumentNullException("Arguments are null");
619             }
620         }
621
622         internal ConnectionType ConnectionType
623         {
624             get
625             {
626                 Log.Info(Globals.LogTag, "get ConnectionType");
627                 int type = 0;
628                 int ret = Interop.Connection.GetType(GetHandle(), out type);
629                 if ((ConnectionError)ret != ConnectionError.None)
630                 {
631                     Log.Error(Globals.LogTag, "It failed to get connection type, " + (ConnectionError)ret);
632                     ConnectionErrorFactory.ThrowConnectionException(ret);
633                 }
634                 return (ConnectionType)type;
635             }
636         }
637
638         internal CellularState CellularState
639         {
640             get
641             {
642                 Log.Info(Globals.LogTag, "get CellularState");
643                 int type = 0;
644                 int ret = Interop.Connection.GetCellularState(GetHandle(), out type);
645                 if ((ConnectionError)ret != ConnectionError.None)
646                 {
647                     Log.Error(Globals.LogTag, "It failed to get cellular state, " + (ConnectionError)ret);
648                     ConnectionErrorFactory.ThrowConnectionException(ret);
649                 }
650                 return (CellularState)type;
651             }
652         }
653
654         internal ConnectionState WiFiState
655         {
656             get
657             {
658                 Log.Info(Globals.LogTag, "get WiFiState");
659                 int type = 0;
660                 int ret = Interop.Connection.GetWiFiState(GetHandle(), out type);
661                 if ((ConnectionError)ret != ConnectionError.None)
662                 {
663                     Log.Error(Globals.LogTag, "It failed to get wifi state, " + (ConnectionError)ret);
664                     ConnectionErrorFactory.ThrowConnectionException(ret);
665                 }
666                 return (ConnectionState)type;
667             }
668         }
669
670         internal ConnectionState BluetoothState
671         {
672             get
673             {
674                 Log.Info(Globals.LogTag, "get BluetoothState");
675                 int type = 0;
676                 int ret = Interop.Connection.GetBtState(GetHandle(), out type);
677                 if ((ConnectionError)ret != ConnectionError.None)
678                 {
679                     Log.Error(Globals.LogTag, "It failed to get bluetooth state, " + (ConnectionError)ret);
680                     ConnectionErrorFactory.ThrowConnectionException(ret);
681                 }
682                 return (ConnectionState)type;
683             }
684         }
685
686         internal ConnectionState EthernetState
687         {
688             get
689             {
690                 Log.Info(Globals.LogTag, "get ConnectionType");
691                 int type = 0;
692                 int ret = Interop.Connection.GetEthernetState(GetHandle(), out type);
693                 if ((ConnectionError)ret != ConnectionError.None)
694                 {
695                     Log.Error(Globals.LogTag, "It failed to get ethernet state, " + (ConnectionError)ret);
696                     ConnectionErrorFactory.ThrowConnectionException(ret);
697                 }
698                 return (ConnectionState)type;
699             }
700         }
701
702         internal EthernetCableState EthernetCableState
703         {
704             get
705             {
706                 Log.Info(Globals.LogTag, "get EthernetCableState");
707                 int type = 0;
708                 int ret = Interop.Connection.GetEthernetCableState(GetHandle(), out type);
709                 if ((ConnectionError)ret != ConnectionError.None)
710                 {
711                     Log.Error(Globals.LogTag, "It failed to get ethernet cable state, " + (ConnectionError)ret);
712                     ConnectionErrorFactory.ThrowConnectionException(ret);
713                 }
714                 return (EthernetCableState)type;
715             }
716         }
717
718         internal IntPtr CreateCellularProfile(ConnectionProfileType type, string keyword)
719         {
720             Log.Debug(Globals.LogTag, "CreateCellularProfile, " + type + ", " + keyword);
721             if (keyword != null)
722             {
723                 IntPtr handle = IntPtr.Zero;
724                 int ret = Interop.ConnectionProfile.Create((int)type, keyword, out handle);
725                 if ((ConnectionError)ret != ConnectionError.None)
726                 {
727                     Log.Error(Globals.LogTag, "It failed to Create profile, " + (ConnectionError)ret);
728                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
729                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
730                     ConnectionErrorFactory.ThrowConnectionException(ret);
731                 }
732
733                 return handle;
734             }
735
736             else
737             {
738                 throw new ArgumentNullException("Keyword is null");
739             }
740         }
741
742         internal void AddCellularProfile(CellularProfile profile)
743         {
744
745             Log.Debug(Globals.LogTag, "AddCellularProfile");
746             if (profile != null)
747             {
748                 if (profile.Type == ConnectionProfileType.Cellular)
749                 {
750                     int ret = Interop.Connection.AddProfile(GetHandle(), profile.ProfileHandle);
751                     if ((ConnectionError)ret != ConnectionError.None)
752                     {
753                         Log.Error(Globals.LogTag, "Failed to add cellular profile, " + (ConnectionError)ret);
754                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
755                         ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.profile)");
756                         ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
757                         ConnectionErrorFactory.ThrowConnectionException(ret);
758                     }
759                 }
760
761                 else
762                 {
763                     throw new ArgumentException("Profile type is not cellular");
764                 }
765             }
766
767             else
768             {
769                 throw new ArgumentNullException("Profile is null");
770             }
771         }
772
773         internal void RemoveProfile(ConnectionProfile profile)
774         {
775             Log.Debug(Globals.LogTag, "RemoveProfile");
776             if (profile != null)
777             {
778                 int ret = Interop.Connection.RemoveProfile(GetHandle(), profile.ProfileHandle);
779                 if ((ConnectionError)ret != ConnectionError.None)
780                 {
781                     Log.Error(Globals.LogTag, "It failed to remove profile, " + (ConnectionError)ret);
782                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
783                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
784                     ConnectionErrorFactory.ThrowConnectionException(ret);
785                 }
786             }
787
788             else
789             {
790                 throw new ArgumentNullException("Profile is null");
791             }
792         }
793
794         internal void UpdateProfile(ConnectionProfile profile)
795         {
796             Log.Info(Globals.LogTag, "UpdateProfile");
797             if (profile != null)
798             {
799                 int ret = Interop.Connection.UpdateProfile(GetHandle(), profile.ProfileHandle);
800                 if ((ConnectionError)ret != ConnectionError.None)
801                 {
802                     Log.Error(Globals.LogTag, "It failed to update profile, " + (ConnectionError)ret);
803                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.ethernet");
804                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
805                     ConnectionErrorFactory.ThrowConnectionException(ret);
806                 }
807             }
808
809             else
810             {
811                 throw new ArgumentNullException("Profile is null");
812             }
813         }
814
815         internal ConnectionProfile GetCurrentProfile()
816         {
817             Log.Info(Globals.LogTag, "GetCurrentProfile");
818             IntPtr ProfileHandle;
819             int ret = Interop.Connection.GetCurrentProfile(GetHandle(), out ProfileHandle);
820             if ((ConnectionError)ret != ConnectionError.None)
821             {
822                 if ((ConnectionError)ret == ConnectionError.NoConnection)
823                 {
824                     Log.Error(Globals.LogTag, "No connection " + (ConnectionError)ret);
825                     return null;
826                 }
827                 else
828                 {
829                     Log.Error(Globals.LogTag, "It failed to get current profile, " + (ConnectionError)ret);
830                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
831                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
832                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
833                     ConnectionErrorFactory.ThrowConnectionException(ret);
834                 }
835             }
836
837             ConnectionProfile Profile = new ConnectionProfile(ProfileHandle);
838             return Profile;
839         }
840
841         internal ConnectionProfile GetDefaultCellularProfile(CellularServiceType type)
842         {
843             Log.Debug(Globals.LogTag, "GetDefaultCellularProfile");
844             IntPtr ProfileHandle;
845             int ret = Interop.Connection.GetDefaultCellularServiceProfile(GetHandle(), (int)type, out ProfileHandle);
846             if ((ConnectionError)ret != ConnectionError.None)
847             {
848                 Log.Error(Globals.LogTag, "Error: " + ret);
849                 Log.Error(Globals.LogTag, "It failed to get default cellular profile, " + (ConnectionError)ret);
850                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
851                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
852                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
853                 ConnectionErrorFactory.ThrowConnectionException(ret);
854             }
855
856             CellularProfile Profile = new CellularProfile(ProfileHandle);
857             return Profile;
858         }
859
860         internal Task SetDefaultCellularProfile(CellularServiceType type, ConnectionProfile profile)
861         {
862             Log.Info(Globals.LogTag, "SetDefaultCellularProfile");
863             if (profile != null)
864             {
865                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
866                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
867                 {
868                     Log.Info(Globals.LogTag, "SetDefaultCellularProfile done " + profile.Name);
869                     if (Result != ConnectionError.None)
870                     {
871                         Log.Error(Globals.LogTag, "Error occurs during set default cellular profile, " + Result);
872                         task.SetException(new InvalidOperationException("Error occurs during set default cellular profile, " + Result));
873                     }
874                     else
875                     {
876                         task.SetResult(true);
877                     }
878                 };
879
880                 context.Post((x) =>
881                 {
882                     Log.Info(Globals.LogTag, "Interop.Connection.SetDefaultCellularServiceProfileAsync " + profile.Name);
883                     try
884                     {
885                         int ret = Interop.Connection.SetDefaultCellularServiceProfileAsync(GetHandle(), (int)type, profile.ProfileHandle, Callback, (IntPtr)0);
886
887                         if ((ConnectionError)ret != ConnectionError.None)
888                         {
889                             Log.Error(Globals.LogTag, "It failed to set default cellular profile, " + (ConnectionError)ret);
890                             ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
891                             ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
892                             ConnectionErrorFactory.ThrowConnectionException(ret);
893                         }
894                     } catch (Exception e)
895                     {
896                         Log.Error(Globals.LogTag, "Exception on SetDefaultCellularServiceProfileAsync\n" + e.ToString());
897                         task.SetException(e);
898                     }
899                 }, null);
900
901                 return task.Task;
902             }
903             else
904             {
905                 throw new ArgumentNullException("Profile is null");
906             }
907         }
908
909
910         internal Task<IEnumerable<ConnectionProfile>> GetProfileListAsync(ProfileListType type)
911         {
912             Log.Debug(Globals.LogTag, "GetProfileListAsync");
913             var task = new TaskCompletionSource<IEnumerable<ConnectionProfile>>();
914
915             List<ConnectionProfile> Result = new List<ConnectionProfile>();
916             IntPtr iterator;
917             int ret = Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
918             if ((ConnectionError)ret != ConnectionError.None)
919             {
920                 Log.Error(Globals.LogTag, "It failed to get profile iterator, " + (ConnectionError)ret);
921                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
922                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
923                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
924                 ConnectionErrorFactory.ThrowConnectionException(ret);
925             }
926
927             while (Interop.Connection.HasNextProfileIterator(iterator))
928             {
929                 IntPtr nextH;
930                 IntPtr profileH;
931                 Interop.Connection.GetNextProfileIterator(iterator, out nextH);
932                 Interop.ConnectionProfile.Clone(out profileH, nextH);
933
934                 int profileType;
935                 Interop.ConnectionProfile.GetType(profileH, out profileType);
936
937                 if ((ConnectionProfileType)profileType == ConnectionProfileType.WiFi)
938                 {
939                     WiFiProfile cur = new WiFiProfile(profileH);
940                     Result.Add(cur);
941                 }
942                 else if ((ConnectionProfileType)profileType == ConnectionProfileType.Cellular)
943                 {
944                     CellularProfile cur = new CellularProfile(profileH);
945                     Result.Add(cur);
946                 }
947                 else {
948                     ConnectionProfile cur = new ConnectionProfile(profileH);
949                     Result.Add(cur);
950                 }
951             }
952             Interop.Connection.DestroyProfileIterator(iterator);
953             task.SetResult(Result);
954             return task.Task;
955         }
956
957         internal Task OpenProfileAsync(ConnectionProfile profile)
958         {
959             Log.Info(Globals.LogTag, "OpenProfileAsync");
960             if (profile != null)
961             {
962                 Log.Debug(Globals.LogTag, "OpenProfileAsync " + profile.Name);
963                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
964                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
965                 {
966                     Log.Info(Globals.LogTag, "OpenProfileAsync done " + profile.Name);
967                     if (Result != ConnectionError.None)
968                     {
969                         Log.Error(Globals.LogTag, "Error occurs during connecting profile, " + Result);
970                         task.SetException(new InvalidOperationException("Error occurs during connecting profile, " + Result));
971                     }
972                     else
973                     {
974                         task.SetResult(true);
975                     }
976                 };
977
978                 context.Post((x) =>
979                 {
980                     Log.Info(Globals.LogTag, "Interop.Connection.OpenProfile " + profile.Name);
981                     try
982                     {
983                         int ret = Interop.Connection.OpenProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
984                         if ((ConnectionError)ret != ConnectionError.None)
985                         {
986                             Log.Error(Globals.LogTag, "It failed to connect profile, " + (ConnectionError)ret);
987                             ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth");
988                             ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
989                             ConnectionErrorFactory.ThrowConnectionException(ret);
990                         }
991                     }
992                     catch (Exception e)
993                     {
994                         Log.Error(Globals.LogTag, "Exception on OpenProfile\n" + e.ToString());
995                         task.SetException(e);
996                     }
997                 }, null);
998
999                 return task.Task;
1000             }
1001
1002             else
1003             {
1004                 throw new ArgumentNullException("Profile is null");
1005             }
1006         }
1007
1008         internal Task CloseProfileAsync(ConnectionProfile profile)
1009         {
1010             Log.Info(Globals.LogTag, "CloseProfileAsync");
1011             if (profile != null)
1012             {
1013                 Log.Info(Globals.LogTag, "CloseProfileAsync " + profile.Name);
1014                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
1015                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
1016                 {
1017                     Log.Info(Globals.LogTag, "CloseProfileAsync done " + profile.Name);
1018                     if (Result != ConnectionError.None)
1019                     {
1020                         Log.Error(Globals.LogTag, "Error occurs during disconnecting profile, " + Result);
1021                         task.SetException(new InvalidOperationException("Error occurs during disconnecting profile, " + Result));
1022                     }
1023                     else
1024                     {
1025                         task.SetResult(true);
1026                     }
1027                 };
1028
1029                 context.Post((x) =>
1030                 {
1031                     Log.Info(Globals.LogTag, "Interop.Connection.CloseProfile " + profile.Name);
1032                     try
1033                     {
1034                         int ret = Interop.Connection.CloseProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
1035                         if ((ConnectionError)ret != ConnectionError.None)
1036                         {
1037                             Log.Error(Globals.LogTag, "It failed to disconnect profile, " + (ConnectionError)ret);
1038                             ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth");
1039                             ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
1040                             ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
1041                             ConnectionErrorFactory.ThrowConnectionException(ret);
1042                         }
1043                     }
1044                     catch (Exception e)
1045                     {
1046                         Log.Error(Globals.LogTag, "Exception on CloseProfile\n" + e.ToString());
1047                         task.SetException(e);
1048                     }
1049                 }, null);
1050
1051                 return task.Task;
1052             }
1053
1054             else
1055             {
1056                 throw new ArgumentNullException("Profile is null");
1057             }
1058         }
1059     }
1060 }