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