2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
21 using System.Threading.Tasks;
22 using System.Runtime.InteropServices;
23 using System.Collections;
24 using System.Threading;
26 namespace Tizen.Network.Connection
28 class HandleHolder : IDisposable
30 private IntPtr Handle;
31 private bool disposed = false;
35 Interop.Connection.Create(out Handle);
36 Log.Debug(Globals.LogTag, "Handle: " + Handle);
44 internal IntPtr GetHandle()
46 Log.Debug(Globals.LogTag, "handleholder handle = " + Handle);
52 GC.SuppressFinalize(this);
55 private void Dispose(bool disposing)
57 Log.Debug(Globals.LogTag, ">>> HandleHolder Dispose with " + disposing);
58 Log.Debug(Globals.LogTag, ">>> Handle: " + Handle);
64 // Free managed objects.
70 private void Destroy()
72 Interop.Connection.Destroy(Handle);
76 internal class ConnectionInternalManager
78 private bool disposed = false;
79 private static ConnectionInternalManager s_instance = null;
81 private EventHandler _ConnectionTypeChanged = null;
82 private EventHandler _IPAddressChanged = null;
83 private EventHandler _EthernetCableStateChanged = null;
84 private EventHandler _ProxyAddressChanged = null;
86 private Interop.Connection.ConnectionAddressChangedCallback _connectionAddressChangedCallback;
87 private Interop.Connection.ConnectionTypeChangedCallback _connectionTypeChangedCallback;
88 private Interop.Connection.ConnectionAddressChangedCallback _proxyAddressChangedCallback;
90 internal static ConnectionInternalManager Instance
94 if (s_instance == null)
96 s_instance = new ConnectionInternalManager();
103 private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
105 Log.Info(Globals.LogTag, "In threadlocal delegate");
106 return new HandleHolder();
109 private ConnectionInternalManager()
114 ~ConnectionInternalManager()
119 public void Dispose()
122 GC.SuppressFinalize(this);
125 private void Dispose(bool disposing)
127 Log.Debug(Globals.LogTag, ">>> ConnectionInternalManager Dispose with disposing " + disposing + ", disposed " + disposed);
128 Log.Debug(Globals.LogTag, ">>> Handle: " + GetHandle());
134 // Free managed objects.
141 internal IntPtr GetHandle()
143 return s_threadName.Value.GetHandle();
146 internal event EventHandler ConnectionTypeChanged
150 if (_ConnectionTypeChanged == null)
152 ConnectionTypeChangedStart();
155 _ConnectionTypeChanged += value;
159 _ConnectionTypeChanged -= value;
160 if (_ConnectionTypeChanged == null)
162 ConnectionTypeChangedStop();
167 private void ConnectionTypeChangedStart()
169 _connectionTypeChangedCallback = (ConnectionType type, IntPtr user_data) =>
171 if (_ConnectionTypeChanged != null)
173 _ConnectionTypeChanged(null, new ConnectionTypeEventArgs(type));
177 int ret = Interop.Connection.SetTypeChangedCallback(GetHandle(), _connectionTypeChangedCallback, IntPtr.Zero);
178 if ((ConnectionError)ret != ConnectionError.None)
180 Log.Error(Globals.LogTag, "It failed to register connection type changed callback, " + (ConnectionError)ret);
181 ConnectionErrorFactory.ThrowConnectionException(ret);
185 private void ConnectionTypeChangedStop()
187 int ret = Interop.Connection.UnsetTypeChangedCallback(GetHandle());
188 if ((ConnectionError)ret != ConnectionError.None)
190 Log.Error(Globals.LogTag, "It failed to unregister connection type changed callback, " + (ConnectionError)ret);
191 ConnectionErrorFactory.ThrowConnectionException(ret);
195 internal event EventHandler EthernetCableStateChanged
199 if (_EthernetCableStateChanged == null)
201 EthernetCableStateChangedStart();
203 _EthernetCableStateChanged += value;
207 _EthernetCableStateChanged -= value;
208 if (_EthernetCableStateChanged == null)
210 EthernetCableStateChangedStop();
215 private void EthernetCableStateChangedStart()
217 int ret = Interop.Connection.SetEthernetCableStateChagedCallback(GetHandle(), EthernetCableStateChangedCallback, IntPtr.Zero);
218 if ((ConnectionError)ret != ConnectionError.None)
220 Log.Error(Globals.LogTag, "It failed to register ethernet cable state changed callback, " + (ConnectionError)ret);
221 ConnectionErrorFactory.ThrowConnectionException(ret);
225 private void EthernetCableStateChangedStop()
227 int ret = Interop.Connection.UnsetEthernetCableStateChagedCallback(GetHandle());
228 if ((ConnectionError)ret != ConnectionError.None)
230 Log.Error(Globals.LogTag, "It failed to unregister ethernet cable state changed callback, " + (ConnectionError)ret);
231 ConnectionErrorFactory.ThrowConnectionException(ret);
235 private void EthernetCableStateChangedCallback(EthernetCableState state, IntPtr user_data)
237 if (_EthernetCableStateChanged != null)
239 _EthernetCableStateChanged(null, new EthernetCableStateEventArgs(state));
243 internal event EventHandler IPAddressChanged
247 if (_IPAddressChanged == null)
249 IPAddressChangedStart();
251 _IPAddressChanged += value;
256 _IPAddressChanged -= value;
257 if (_IPAddressChanged == null)
259 IPAddressChangedStop();
264 private void IPAddressChangedStart()
266 _connectionAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
268 if (_IPAddressChanged != null)
270 string ipv4 = Marshal.PtrToStringAnsi(IPv4);
271 string ipv6 = Marshal.PtrToStringAnsi(IPv6);
273 if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
275 _IPAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
280 int ret = Interop.Connection.SetIPAddressChangedCallback(GetHandle(), _connectionAddressChangedCallback, IntPtr.Zero);
281 if ((ConnectionError)ret != ConnectionError.None)
283 Log.Error(Globals.LogTag, "It failed to register callback for changing IP address, " + (ConnectionError)ret);
287 private void IPAddressChangedStop()
289 int ret = Interop.Connection.UnsetIPAddressChangedCallback(GetHandle());
290 if ((ConnectionError)ret != ConnectionError.None)
292 Log.Error(Globals.LogTag, "It failed to unregister callback for changing IP address, " + (ConnectionError)ret);
296 internal event EventHandler ProxyAddressChanged
300 //Console.WriteLine("ProxyAddressChanged Add **");
301 if (_ProxyAddressChanged == null)
303 ProxyAddressChangedStart();
306 _ProxyAddressChanged += value;
310 //Console.WriteLine("ProxyAddressChanged Remove");
311 _ProxyAddressChanged -= value;
312 if (_ProxyAddressChanged == null)
314 ProxyAddressChangedStop();
319 private void ProxyAddressChangedStart()
321 _proxyAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
323 if (_ProxyAddressChanged != null)
325 string ipv4 = Marshal.PtrToStringAnsi(IPv4);
326 string ipv6 = Marshal.PtrToStringAnsi(IPv6);
328 if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
330 _ProxyAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
335 int ret = Interop.Connection.SetProxyAddressChangedCallback(GetHandle(), _proxyAddressChangedCallback, IntPtr.Zero);
336 if ((ConnectionError)ret != ConnectionError.None)
338 Log.Error(Globals.LogTag, "It failed to register callback for changing proxy address, " + (ConnectionError)ret);
342 private void ProxyAddressChangedStop()
344 int ret = Interop.Connection.UnsetProxyAddressChangedCallback(GetHandle());
345 if ((ConnectionError)ret != ConnectionError.None)
347 Log.Error(Globals.LogTag, "It failed to unregister callback for changing proxy address, " + (ConnectionError)ret);
351 private void UnregisterEvents()
353 if (_ConnectionTypeChanged != null)
355 ConnectionTypeChangedStop();
357 if (_IPAddressChanged != null)
359 IPAddressChangedStop();
361 if (_EthernetCableStateChanged != null)
363 EthernetCableStateChangedStop();
365 if (_ProxyAddressChanged != null)
367 ProxyAddressChangedStop();
371 internal int GetProfileIterator(ProfileListType type, out IntPtr iterator)
373 return Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
376 internal bool HasNext(IntPtr iterator)
378 return Interop.Connection.HasNextProfileIterator(iterator);
381 internal int NextProfileIterator(IntPtr iterator, out IntPtr profileHandle)
383 return Interop.Connection.GetNextProfileIterator(iterator, out profileHandle);
386 internal int DestoryProfileIterator(IntPtr iterator)
388 return Interop.Connection.DestroyProfileIterator(iterator);
391 internal System.Net.IPAddress GetIPAddress(AddressFamily family)
393 Log.Debug(Globals.LogTag, "GetIPAddress " + family);
395 int ret = Interop.Connection.GetIPAddress(GetHandle(), (int)family, out ip);
396 if ((ConnectionError)ret != ConnectionError.None)
398 Log.Error(Globals.LogTag, "It failed to get IP address, " + (ConnectionError)ret);
399 ConnectionErrorFactory.ThrowConnectionException(ret);
401 string result = Marshal.PtrToStringAnsi(ip);
402 Interop.Libc.Free(ip);
403 return System.Net.IPAddress.Parse(result);
406 internal IEnumerable<System.Net.IPAddress> GetAllIPv6Addresses(ConnectionType type)
408 Log.Debug(Globals.LogTag, "GetAllIPv6Addresses");
409 List<System.Net.IPAddress> ipList = new List<System.Net.IPAddress>();
410 Interop.Connection.IPv6AddressCallback callback = (IntPtr ipv6Address, IntPtr userData) =>
412 if (ipv6Address != IntPtr.Zero)
414 string ipv6 = Marshal.PtrToStringAnsi(ipv6Address);
415 ipList.Add(System.Net.IPAddress.Parse(ipv6));
421 int ret = Interop.Connection.GetAllIPv6Addresses(GetHandle(), (int)type, callback, IntPtr.Zero);
422 if (ret != (int)ConnectionError.None)
424 Log.Error(Globals.LogTag, "Failed to get all IPv6 addresses, Error - " + (ConnectionError)ret);
425 ConnectionErrorFactory.ThrowConnectionException(ret);
432 internal string GetProxy(AddressFamily family)
434 Log.Debug(Globals.LogTag, "GetProxy " + family);
436 int ret = Interop.Connection.GetProxy(GetHandle(), (int)family, out ip);
437 if ((ConnectionError)ret != ConnectionError.None)
439 Log.Error(Globals.LogTag, "It failed to get proxy, " + (ConnectionError)ret);
440 ConnectionErrorFactory.ThrowConnectionException(ret);
442 string result = Marshal.PtrToStringAnsi(ip);
443 Interop.Libc.Free(ip);
447 internal string GetMacAddress(ConnectionType type)
449 Log.Debug(Globals.LogTag, "GetMacAddress " + type);
451 int ret = Interop.Connection.GetMacAddress(GetHandle(), (int)type, out mac);
452 if ((ConnectionError)ret != ConnectionError.None)
454 Log.Error(Globals.LogTag, "It failed to get mac address, " + (ConnectionError)ret);
455 ConnectionErrorFactory.ThrowConnectionException(ret);
457 string result = Marshal.PtrToStringAnsi(mac);
458 Interop.Libc.Free(mac);
462 internal long GetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
464 Log.Debug(Globals.LogTag, "GetStatistics " + connectionType + ", " + statisticsType);
466 int ret = Interop.Connection.GetStatistics(GetHandle(), (int)connectionType,
467 (int)statisticsType, out size);
468 if ((ConnectionError)ret != ConnectionError.None)
470 Log.Error(Globals.LogTag, "It failed to get statistics, " + (ConnectionError)ret);
471 ConnectionErrorFactory.ThrowConnectionException(ret);
476 internal void ResetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
478 Log.Debug(Globals.LogTag, "ResetStatistics " + connectionType + ", " + statisticsType);
479 int ret = Interop.Connection.ResetStatistics(GetHandle(), (int)connectionType,
480 (int)statisticsType);
481 if ((ConnectionError)ret != ConnectionError.None)
483 Log.Error(Globals.LogTag, "It failed to reset statistics, " + (ConnectionError)ret);
484 ConnectionErrorFactory.ThrowConnectionException(ret);
488 internal ConnectionType ConnectionType
492 Log.Debug(Globals.LogTag, "get ConnectionType");
494 int ret = Interop.Connection.GetType(GetHandle(), out type);
495 if ((ConnectionError)ret != ConnectionError.None)
497 Log.Error(Globals.LogTag, "It failed to get connection type, " + (ConnectionError)ret);
498 ConnectionErrorFactory.ThrowConnectionException(ret);
500 return (ConnectionType)type;
504 internal CellularState CellularState
508 Log.Debug(Globals.LogTag, "get CellularState");
510 int ret = Interop.Connection.GetCellularState(GetHandle(), out type);
511 if ((ConnectionError)ret != ConnectionError.None)
513 Log.Error(Globals.LogTag, "It failed to get cellular state, " + (ConnectionError)ret);
514 ConnectionErrorFactory.ThrowConnectionException(ret);
516 return (CellularState)type;
520 internal ConnectionState WiFiState
524 Log.Debug(Globals.LogTag, "get WiFiState");
526 int ret = Interop.Connection.GetWiFiState(GetHandle(), out type);
527 if ((ConnectionError)ret != ConnectionError.None)
529 Log.Error(Globals.LogTag, "It failed to get wifi state, " + (ConnectionError)ret);
530 ConnectionErrorFactory.ThrowConnectionException(ret);
532 return (ConnectionState)type;
536 internal ConnectionState BluetoothState
540 Log.Debug(Globals.LogTag, "get BluetoothState");
542 int ret = Interop.Connection.GetBtState(GetHandle(), out type);
543 if ((ConnectionError)ret != ConnectionError.None)
545 Log.Error(Globals.LogTag, "It failed to get bluetooth state, " + (ConnectionError)ret);
546 ConnectionErrorFactory.ThrowConnectionException(ret);
548 return (ConnectionState)type;
552 internal ConnectionState EthernetState
556 Log.Debug(Globals.LogTag, "get ConnectionType");
558 int ret = Interop.Connection.GetEthernetState(GetHandle(), out type);
559 if ((ConnectionError)ret != ConnectionError.None)
561 Log.Error(Globals.LogTag, "It failed to get ethernet state, " + (ConnectionError)ret);
562 ConnectionErrorFactory.ThrowConnectionException(ret);
564 return (ConnectionState)type;
568 internal EthernetCableState EthernetCableState
572 Log.Debug(Globals.LogTag, "get EthernetCableState");
574 int ret = Interop.Connection.GetEthernetCableState(GetHandle(), out type);
575 if ((ConnectionError)ret != ConnectionError.None)
577 Log.Error(Globals.LogTag, "It failed to get ethernet cable state, " + (ConnectionError)ret);
578 ConnectionErrorFactory.ThrowConnectionException(ret);
580 return (EthernetCableState)type;
584 internal IntPtr CreateCellularProfile(ConnectionProfileType type, string keyword)
586 Log.Debug(Globals.LogTag, "CreateCellularProfile, " + type + ", " + keyword);
587 IntPtr connectionHandle = GetHandle();
588 if (connectionHandle == IntPtr.Zero)
590 Log.Error(Globals.LogTag, "It failed to create connection handle");
591 throw new InvalidOperationException("Invalid connection handle");
594 IntPtr handle = IntPtr.Zero;
595 int ret = Interop.ConnectionProfile.Create((int)type, keyword, out handle);
596 if ((ConnectionError)ret != ConnectionError.None)
598 Log.Error(Globals.LogTag, "It failed to Create profile, " + (ConnectionError)ret);
599 ConnectionErrorFactory.ThrowConnectionException(ret);
605 internal void AddCellularProfile(CellularProfile profile)
607 Log.Debug(Globals.LogTag, "AddCellularProfile");
608 if (profile.Type == ConnectionProfileType.Cellular)
610 int ret = Interop.Connection.AddProfile(GetHandle(), profile.ProfileHandle);
611 if ((ConnectionError)ret != ConnectionError.None)
613 Log.Error(Globals.LogTag, "Failed to add cellular profile, " + (ConnectionError)ret);
614 ConnectionErrorFactory.ThrowConnectionException(ret);
620 throw new InvalidOperationException("Profile type is not cellular");
624 internal void RemoveProfile(ConnectionProfile profile)
626 Log.Debug(Globals.LogTag, "RemoveProfile");
627 int ret = Interop.Connection.RemoveProfile(GetHandle(), profile.ProfileHandle);
628 if ((ConnectionError)ret != ConnectionError.None)
630 Log.Error(Globals.LogTag, "It failed to remove profile, " + (ConnectionError)ret);
631 ConnectionErrorFactory.ThrowConnectionException(ret);
635 internal void UpdateProfile(ConnectionProfile profile)
637 Log.Debug(Globals.LogTag, "UpdateProfile");
638 int ret = Interop.Connection.UpdateProfile(GetHandle(), profile.ProfileHandle);
639 if ((ConnectionError)ret != ConnectionError.None)
641 Log.Error(Globals.LogTag, "It failed to update profile, " + (ConnectionError)ret);
642 ConnectionErrorFactory.ThrowConnectionException(ret);
646 internal ConnectionProfile GetCurrentProfile()
648 Log.Debug(Globals.LogTag, "GetCurrentProfile");
649 IntPtr ProfileHandle;
650 int ret = Interop.Connection.GetCurrentProfile(GetHandle(), out ProfileHandle);
651 if ((ConnectionError)ret != ConnectionError.None)
653 Log.Error(Globals.LogTag, "It failed to get current profile, " + (ConnectionError)ret);
654 ConnectionErrorFactory.ThrowConnectionException(ret);
656 ConnectionProfile Profile = new ConnectionProfile(ProfileHandle);
660 internal ConnectionProfile GetDefaultCellularProfile(CellularServiceType type)
662 Log.Debug(Globals.LogTag, "GetDefaultCellularProfile");
663 IntPtr ProfileHandle;
664 int ret = Interop.Connection.GetDefaultCellularServiceProfile(GetHandle(), (int)type, out ProfileHandle);
665 if ((ConnectionError)ret != ConnectionError.None)
667 Log.Error(Globals.LogTag, "Error: " + ret);
668 Log.Error(Globals.LogTag, "It failed to get default cellular profile, " + (ConnectionError)ret);
669 ConnectionErrorFactory.ThrowConnectionException(ret);
671 CellularProfile Profile = new CellularProfile(ProfileHandle);
675 internal Task SetDefaultCellularProfile(CellularServiceType type, ConnectionProfile profile)
677 Log.Debug(Globals.LogTag, "SetDefaultCellularProfile");
678 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
679 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
681 if (Result != ConnectionError.None)
683 Log.Error(Globals.LogTag, "Error occurs during set default cellular profile, " + Result);
684 task.SetException(new InvalidOperationException("Error occurs during set default cellular profile, " + Result));
687 task.SetResult(true);
690 int ret = Interop.Connection.SetDefaultCellularServiceProfileAsync(GetHandle(), (int)type, profile.ProfileHandle, Callback, (IntPtr)0);
691 if ((ConnectionError)ret != ConnectionError.None)
693 Log.Error(Globals.LogTag, "It failed to set default cellular profile, " + (ConnectionError)ret);
694 ConnectionErrorFactory.ThrowConnectionException(ret);
701 internal Task<IEnumerable<ConnectionProfile>> GetProfileListAsync(ProfileListType type)
703 Log.Debug(Globals.LogTag, "GetProfileListAsync");
704 var task = new TaskCompletionSource<IEnumerable<ConnectionProfile>>();
705 List<ConnectionProfile> Result = new List<ConnectionProfile>();
707 int ret = Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
708 if ((ConnectionError)ret != ConnectionError.None)
710 Log.Error(Globals.LogTag, "It failed to get profile iterator, " + (ConnectionError)ret);
713 while (Interop.Connection.HasNextProfileIterator(iterator))
717 Interop.Connection.GetNextProfileIterator(iterator, out nextH);
718 Interop.ConnectionProfile.Clone(out profileH, nextH);
721 Interop.ConnectionProfile.GetType(profileH, out profileType);
723 if ((ConnectionProfileType)profileType == ConnectionProfileType.WiFi)
725 WiFiProfile cur = new WiFiProfile(profileH);
728 else if ((ConnectionProfileType)profileType == ConnectionProfileType.Cellular)
730 CellularProfile cur = new CellularProfile(profileH);
734 ConnectionProfile cur = new ConnectionProfile(profileH);
738 Interop.Connection.DestroyProfileIterator(iterator);
739 task.SetResult(Result);
743 internal Task OpenProfileAsync(ConnectionProfile profile)
745 Log.Debug(Globals.LogTag, "OpenProfileAsync " + profile.Name);
746 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
747 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
749 Log.Debug(Globals.LogTag, "Connected " + profile.Name);
750 if (Result != ConnectionError.None)
752 Log.Error(Globals.LogTag, "Error occurs during connecting profile, " + Result);
753 task.SetException(new InvalidOperationException("Error occurs during connecting profile, " + Result));
756 task.SetResult(true);
759 int ret = Interop.Connection.OpenProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
760 if ((ConnectionError)ret != ConnectionError.None)
762 Log.Error(Globals.LogTag, "It failed to connect profile, " + (ConnectionError)ret);
763 ConnectionErrorFactory.ThrowConnectionException(ret);
769 internal Task CloseProfileAsync(ConnectionProfile profile)
771 Log.Debug(Globals.LogTag, "CloseProfileAsync " + profile.Name);
772 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
773 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
775 if (Result != ConnectionError.None)
777 Log.Error(Globals.LogTag, "Error occurs during disconnecting profile, " + Result);
778 task.SetException(new InvalidOperationException("Error occurs during disconnecting profile, " + Result));
781 task.SetResult(true);
784 int ret = Interop.Connection.CloseProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
785 if ((ConnectionError)ret != ConnectionError.None)
787 Log.Error(Globals.LogTag, "It failed to disconnect profile, " + (ConnectionError)ret);
788 ConnectionErrorFactory.ThrowConnectionException(ret);