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 Log.Debug(Globals.LogTag, "HandleHolder() ^^");
36 Interop.Connection.Create(out Handle);
37 Log.Debug(Globals.LogTag, "Handle: " + Handle);
45 internal IntPtr GetHandle()
47 Log.Debug(Globals.LogTag, "handleholder handle = " + Handle);
53 GC.SuppressFinalize(this);
56 private void Dispose(bool disposing)
58 Log.Debug(Globals.LogTag, ">>> HandleHolder Dispose with " + disposing);
59 Log.Debug(Globals.LogTag, ">>> Handle: " + Handle);
65 // Free managed objects.
71 private void Destroy()
73 Interop.Connection.Destroy(Handle);
77 internal class ConnectionInternalManager
79 private bool disposed = false;
80 private static ConnectionInternalManager s_instance = null;
82 private EventHandler _ConnectionTypeChanged = null;
83 private EventHandler _IPAddressChanged = null;
84 private EventHandler _EthernetCableStateChanged = null;
85 private EventHandler _ProxyAddressChanged = null;
87 private Interop.Connection.ConnectionAddressChangedCallback _connectionAddressChangedCallback;
88 private Interop.Connection.ConnectionTypeChangedCallback _connectionTypeChangedCallback;
89 private Interop.Connection.ConnectionAddressChangedCallback _proxyAddressChangedCallback;
91 internal static ConnectionInternalManager Instance
95 if (s_instance == null)
97 s_instance = new ConnectionInternalManager();
104 private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
106 Log.Info(Globals.LogTag, "In threadlocal delegate");
107 return new HandleHolder();
110 private ConnectionInternalManager()
115 ~ConnectionInternalManager()
120 public void Dispose()
123 GC.SuppressFinalize(this);
126 private void Dispose(bool disposing)
128 Log.Debug(Globals.LogTag, ">>> ConnectionInternalManager Dispose with disposing " + disposing + ", disposed " + disposed);
129 Log.Debug(Globals.LogTag, ">>> Handle: " + GetHandle());
135 // Free managed objects.
142 internal IntPtr GetHandle()
144 Log.Debug(Globals.LogTag, "GetHandle, Thread Id = " + Thread.CurrentThread.ManagedThreadId);
145 return s_threadName.Value.GetHandle();
148 internal event EventHandler ConnectionTypeChanged
152 if (_ConnectionTypeChanged == null)
154 ConnectionTypeChangedStart();
157 _ConnectionTypeChanged += value;
161 _ConnectionTypeChanged -= value;
162 if (_ConnectionTypeChanged == null)
164 ConnectionTypeChangedStop();
169 private void ConnectionTypeChangedStart()
171 _connectionTypeChangedCallback = (ConnectionType type, IntPtr user_data) =>
173 if (_ConnectionTypeChanged != null)
175 _ConnectionTypeChanged(null, new ConnectionTypeEventArgs(type));
179 int ret = Interop.Connection.SetTypeChangedCallback(GetHandle(), _connectionTypeChangedCallback, IntPtr.Zero);
180 if ((ConnectionError)ret != ConnectionError.None)
182 Log.Error(Globals.LogTag, "It failed to register connection type changed callback, " + (ConnectionError)ret);
183 ConnectionErrorFactory.ThrowConnectionException(ret);
187 private void ConnectionTypeChangedStop()
189 int ret = Interop.Connection.UnsetTypeChangedCallback(GetHandle());
190 if ((ConnectionError)ret != ConnectionError.None)
192 Log.Error(Globals.LogTag, "It failed to unregister connection type changed callback, " + (ConnectionError)ret);
193 ConnectionErrorFactory.ThrowConnectionException(ret);
197 internal event EventHandler EthernetCableStateChanged
201 if (_EthernetCableStateChanged == null)
203 EthernetCableStateChangedStart();
205 _EthernetCableStateChanged += value;
209 _EthernetCableStateChanged -= value;
210 if (_EthernetCableStateChanged == null)
212 EthernetCableStateChangedStop();
217 private void EthernetCableStateChangedStart()
219 int ret = Interop.Connection.SetEthernetCableStateChagedCallback(GetHandle(), EthernetCableStateChangedCallback, IntPtr.Zero);
220 if ((ConnectionError)ret != ConnectionError.None)
222 Log.Error(Globals.LogTag, "It failed to register ethernet cable state changed callback, " + (ConnectionError)ret);
223 ConnectionErrorFactory.ThrowConnectionException(ret);
227 private void EthernetCableStateChangedStop()
229 int ret = Interop.Connection.UnsetEthernetCableStateChagedCallback(GetHandle());
230 if ((ConnectionError)ret != ConnectionError.None)
232 Log.Error(Globals.LogTag, "It failed to unregister ethernet cable state changed callback, " + (ConnectionError)ret);
233 ConnectionErrorFactory.ThrowConnectionException(ret);
237 private void EthernetCableStateChangedCallback(EthernetCableState state, IntPtr user_data)
239 if (_EthernetCableStateChanged != null)
241 _EthernetCableStateChanged(null, new EthernetCableStateEventArgs(state));
245 internal event EventHandler IPAddressChanged
249 if (_IPAddressChanged == null)
251 IPAddressChangedStart();
253 _IPAddressChanged += value;
258 _IPAddressChanged -= value;
259 if (_IPAddressChanged == null)
261 IPAddressChangedStop();
266 private void IPAddressChangedStart()
268 _connectionAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
270 if (_IPAddressChanged != null)
272 string ipv4 = Marshal.PtrToStringAnsi(IPv4);
273 string ipv6 = Marshal.PtrToStringAnsi(IPv6);
275 if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
277 _IPAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
282 int ret = Interop.Connection.SetIPAddressChangedCallback(GetHandle(), _connectionAddressChangedCallback, IntPtr.Zero);
283 if ((ConnectionError)ret != ConnectionError.None)
285 Log.Error(Globals.LogTag, "It failed to register callback for changing IP address, " + (ConnectionError)ret);
289 private void IPAddressChangedStop()
291 int ret = Interop.Connection.UnsetIPAddressChangedCallback(GetHandle());
292 if ((ConnectionError)ret != ConnectionError.None)
294 Log.Error(Globals.LogTag, "It failed to unregister callback for changing IP address, " + (ConnectionError)ret);
298 internal event EventHandler ProxyAddressChanged
302 //Console.WriteLine("ProxyAddressChanged Add **");
303 if (_ProxyAddressChanged == null)
305 ProxyAddressChangedStart();
308 _ProxyAddressChanged += value;
312 //Console.WriteLine("ProxyAddressChanged Remove");
313 _ProxyAddressChanged -= value;
314 if (_ProxyAddressChanged == null)
316 ProxyAddressChangedStop();
321 private void ProxyAddressChangedStart()
323 _proxyAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
325 if (_ProxyAddressChanged != null)
327 string ipv4 = Marshal.PtrToStringAnsi(IPv4);
328 string ipv6 = Marshal.PtrToStringAnsi(IPv6);
330 if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
332 _ProxyAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
337 int ret = Interop.Connection.SetProxyAddressChangedCallback(GetHandle(), _proxyAddressChangedCallback, IntPtr.Zero);
338 if ((ConnectionError)ret != ConnectionError.None)
340 Log.Error(Globals.LogTag, "It failed to register callback for changing proxy address, " + (ConnectionError)ret);
344 private void ProxyAddressChangedStop()
346 int ret = Interop.Connection.UnsetProxyAddressChangedCallback(GetHandle());
347 if ((ConnectionError)ret != ConnectionError.None)
349 Log.Error(Globals.LogTag, "It failed to unregister callback for changing proxy address, " + (ConnectionError)ret);
353 private void UnregisterEvents()
355 if (_ConnectionTypeChanged != null)
357 ConnectionTypeChangedStop();
359 if (_IPAddressChanged != null)
361 IPAddressChangedStop();
363 if (_EthernetCableStateChanged != null)
365 EthernetCableStateChangedStop();
367 if (_ProxyAddressChanged != null)
369 ProxyAddressChangedStop();
373 internal int GetProfileIterator(ProfileListType type, out IntPtr iterator)
375 return Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
378 internal bool HasNext(IntPtr iterator)
380 return Interop.Connection.HasNextProfileIterator(iterator);
383 internal int NextProfileIterator(IntPtr iterator, out IntPtr profileHandle)
385 return Interop.Connection.GetNextProfileIterator(iterator, out profileHandle);
388 internal int DestoryProfileIterator(IntPtr iterator)
390 return Interop.Connection.DestroyProfileIterator(iterator);
393 internal string GetIPAddress(AddressFamily family)
396 int ret = Interop.Connection.GetIPAddress(GetHandle(), (int)family, out ip);
397 if ((ConnectionError)ret != ConnectionError.None)
399 Log.Error(Globals.LogTag, "It failed to get IP address, " + (ConnectionError)ret);
400 ConnectionErrorFactory.ThrowConnectionException(ret);
402 string result = Marshal.PtrToStringAnsi(ip);
403 Interop.Libc.Free(ip);
407 internal string GetProxy(AddressFamily family)
410 int ret = Interop.Connection.GetProxy(GetHandle(), (int)family, out ip);
411 if ((ConnectionError)ret != ConnectionError.None)
413 Log.Error(Globals.LogTag, "It failed to get proxy, " + (ConnectionError)ret);
414 ConnectionErrorFactory.ThrowConnectionException(ret);
416 string result = Marshal.PtrToStringAnsi(ip);
417 Interop.Libc.Free(ip);
421 internal string GetMacAddress(ConnectionType type)
424 int ret = Interop.Connection.GetMacAddress(GetHandle(), (int)type, out ip);
425 if ((ConnectionError)ret != ConnectionError.None)
427 Log.Error(Globals.LogTag, "It failed to get mac address, " + (ConnectionError)ret);
428 ConnectionErrorFactory.ThrowConnectionException(ret);
430 string result = Marshal.PtrToStringAnsi(ip);
431 Interop.Libc.Free(ip);
435 internal ConnectionType ConnectionType
440 Log.Debug(Globals.LogTag, "Handle: " + GetHandle());
441 int ret = Interop.Connection.GetType(GetHandle(), out type);
442 if ((ConnectionError)ret != ConnectionError.None)
444 Log.Error(Globals.LogTag, "It failed to get connection type, " + (ConnectionError)ret);
445 ConnectionErrorFactory.ThrowConnectionException(ret);
447 return (ConnectionType)type;
451 internal CellularState CellularState
456 Log.Debug(Globals.LogTag, "CellularState Handle: " + GetHandle());
457 int ret = Interop.Connection.GetCellularState(GetHandle(), out type);
458 if ((ConnectionError)ret != ConnectionError.None)
460 Log.Error(Globals.LogTag, "It failed to get cellular state, " + (ConnectionError)ret);
461 ConnectionErrorFactory.ThrowConnectionException(ret);
463 return (CellularState)type;
467 internal ConnectionState WiFiState
472 int ret = Interop.Connection.GetWiFiState(GetHandle(), out type);
473 if ((ConnectionError)ret != ConnectionError.None)
475 Log.Error(Globals.LogTag, "It failed to get wifi state, " + (ConnectionError)ret);
476 ConnectionErrorFactory.ThrowConnectionException(ret);
478 return (ConnectionState)type;
482 internal ConnectionState BluetoothState
487 int ret = Interop.Connection.GetBtState(GetHandle(), out type);
488 if ((ConnectionError)ret != ConnectionError.None)
490 Log.Error(Globals.LogTag, "It failed to get bluetooth state, " + (ConnectionError)ret);
491 ConnectionErrorFactory.ThrowConnectionException(ret);
493 return (ConnectionState)type;
497 internal ConnectionState EthernetState
502 int ret = Interop.Connection.GetEthernetState(GetHandle(), out type);
503 if ((ConnectionError)ret != ConnectionError.None)
505 Log.Error(Globals.LogTag, "It failed to get ethernet state, " + (ConnectionError)ret);
506 ConnectionErrorFactory.ThrowConnectionException(ret);
508 return (ConnectionState)type;
512 internal EthernetCableState EthernetCableState
517 int ret = Interop.Connection.GetEthernetCableState(GetHandle(), out type);
518 if ((ConnectionError)ret != ConnectionError.None)
520 Log.Error(Globals.LogTag, "It failed to get ethernet cable state, " + (ConnectionError)ret);
521 ConnectionErrorFactory.ThrowConnectionException(ret);
523 return (EthernetCableState)type;
527 internal IntPtr CreateCellularProfile(ConnectionProfileType type, string keyword)
529 Log.Error(Globals.LogTag, "CreateCellularProfile, " + type + ", " + keyword);
530 IntPtr connectionHandle = GetHandle();
531 if (connectionHandle == IntPtr.Zero)
533 Log.Error(Globals.LogTag, "It failed to create connection handle");
534 throw new InvalidOperationException("Invalid connection handle");
537 IntPtr handle = IntPtr.Zero;
538 int ret = Interop.ConnectionProfile.Create((int)type, keyword, out handle);
539 if ((ConnectionError)ret != ConnectionError.None)
541 Log.Error(Globals.LogTag, "It failed to Create profile, " + (ConnectionError)ret);
542 ConnectionErrorFactory.ThrowConnectionException(ret);
548 internal void AddCellularProfile(CellularProfile profile)
550 if (profile.Type == ConnectionProfileType.Cellular)
552 int ret = Interop.Connection.AddProfile(GetHandle(), profile.ProfileHandle);
553 if ((ConnectionError)ret != ConnectionError.None)
555 Log.Error(Globals.LogTag, "Failed to add cellular profile, " + (ConnectionError)ret);
556 ConnectionErrorFactory.ThrowConnectionException(ret);
562 throw new InvalidOperationException("Profile type is not cellular");
566 internal void RemoveProfile(ConnectionProfile profile)
568 int ret = Interop.Connection.RemoveProfile(GetHandle(), profile.ProfileHandle);
569 if ((ConnectionError)ret != ConnectionError.None)
571 Log.Error(Globals.LogTag, "It failed to remove profile, " + (ConnectionError)ret);
572 ConnectionErrorFactory.ThrowConnectionException(ret);
576 internal void UpdateProfile(ConnectionProfile profile)
578 int ret = Interop.Connection.UpdateProfile(GetHandle(), profile.ProfileHandle);
579 if ((ConnectionError)ret != ConnectionError.None)
581 Log.Error(Globals.LogTag, "It failed to update profile, " + (ConnectionError)ret);
582 ConnectionErrorFactory.ThrowConnectionException(ret);
586 internal ConnectionProfile GetCurrentProfile()
588 IntPtr ProfileHandle;
589 int ret = Interop.Connection.GetCurrentProfile(GetHandle(), out ProfileHandle);
590 if ((ConnectionError)ret != ConnectionError.None)
592 Log.Error(Globals.LogTag, "It failed to get current profile, " + (ConnectionError)ret);
593 ConnectionErrorFactory.ThrowConnectionException(ret);
595 ConnectionProfile Profile = new ConnectionProfile(ProfileHandle);
599 internal ConnectionProfile GetDefaultCellularProfile(CellularServiceType type)
601 IntPtr ProfileHandle;
602 int ret = Interop.Connection.GetDefaultCellularServiceProfile(GetHandle(), (int)type, out ProfileHandle);
603 if ((ConnectionError)ret != ConnectionError.None)
605 Log.Error(Globals.LogTag, "Error: " + ret);
606 Log.Error(Globals.LogTag, "It failed to get default cellular profile, " + (ConnectionError)ret);
607 ConnectionErrorFactory.ThrowConnectionException(ret);
609 CellularProfile Profile = new CellularProfile(ProfileHandle);
613 internal Task SetDefaultCellularProfile(CellularServiceType type, ConnectionProfile profile)
615 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
616 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
618 if (Result != ConnectionError.None)
620 Log.Error(Globals.LogTag, "Error occurs during set default cellular profile, " + Result);
621 task.SetException(new InvalidOperationException("Error occurs during set default cellular profile, " + Result));
624 task.SetResult(true);
627 int ret = Interop.Connection.SetDefaultCellularServiceProfileAsync(GetHandle(), (int)type, profile.ProfileHandle, Callback, (IntPtr)0);
628 if ((ConnectionError)ret != ConnectionError.None)
630 Log.Error(Globals.LogTag, "It failed to set default cellular profile, " + (ConnectionError)ret);
631 ConnectionErrorFactory.ThrowConnectionException(ret);
638 internal Task<IEnumerable<ConnectionProfile>> GetProfileListAsync(ProfileListType type)
640 var task = new TaskCompletionSource<IEnumerable<ConnectionProfile>>();
642 List<ConnectionProfile> Result = new List<ConnectionProfile>();
644 int ret = Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
645 if ((ConnectionError)ret != ConnectionError.None)
647 Log.Error(Globals.LogTag, "It failed to get profile iterator, " + (ConnectionError)ret);
650 while (Interop.Connection.HasNextProfileIterator(iterator))
654 Interop.Connection.GetNextProfileIterator(iterator, out nextH);
655 Interop.ConnectionProfile.Clone(out profileH, nextH);
658 Interop.ConnectionProfile.GetType(profileH, out profileType);
660 if ((ConnectionProfileType)profileType == ConnectionProfileType.WiFi)
662 WiFiProfile cur = new WiFiProfile(profileH);
665 else if ((ConnectionProfileType)profileType == ConnectionProfileType.Cellular)
667 CellularProfile cur = new CellularProfile(profileH);
671 ConnectionProfile cur = new ConnectionProfile(profileH);
675 Interop.Connection.DestroyProfileIterator(iterator);
676 task.SetResult(Result);
680 internal Task OpenProfileAsync(ConnectionProfile profile)
682 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
683 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
685 if (Result != ConnectionError.None)
687 Log.Error(Globals.LogTag, "Error occurs during connecting profile, " + Result);
688 task.SetException(new InvalidOperationException("Error occurs during connecting profile, " + Result));
691 task.SetResult(true);
694 int ret = Interop.Connection.OpenProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
695 if ((ConnectionError)ret != ConnectionError.None)
697 Log.Error(Globals.LogTag, "It failed to connect profile, " + (ConnectionError)ret);
698 ConnectionErrorFactory.ThrowConnectionException(ret);
704 internal Task CloseProfileAsync(ConnectionProfile profile)
706 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
707 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
709 if (Result != ConnectionError.None)
711 Log.Error(Globals.LogTag, "Error occurs during disconnecting profile, " + Result);
712 task.SetException(new InvalidOperationException("Error occurs during disconnecting profile, " + Result));
715 task.SetResult(true);
718 int ret = Interop.Connection.CloseProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
719 if ((ConnectionError)ret != ConnectionError.None)
721 Log.Error(Globals.LogTag, "It failed to disconnect profile, " + (ConnectionError)ret);
722 ConnectionErrorFactory.ThrowConnectionException(ret);