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