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