/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Threading.Tasks; using System.Collections.Generic; namespace Tizen.Network.WiFi { /// /// A class for managing the network information of the access point (AP). /// /// 3 public class WiFiAP : IDisposable { private IntPtr _apHandle = IntPtr.Zero; private Dictionary _callback_map = new Dictionary(); private static Dictionary s_callbackMap = new Dictionary(); private int _requestId = 0; private static int s_requestId = 0; private WiFiNetwork _network; private WiFiSecurity _security; private bool _disposed = false; /// /// The network information of the access point (AP). /// /// 3 /// The WiFiNetwork instance containing the network information of the AP. public WiFiNetwork NetworkInformation { get { return _network; } } /// /// The security information of the access point (AP). /// /// 3 /// The WiFiSecurity instance containing security information of the AP. public WiFiSecurity SecurityInformation { get { return _security; } } internal WiFiAP(IntPtr handle) { Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle); _apHandle = handle; Initialize(); } /// /// Creates an object for the access point. /// /// 3 /// The Extended Service Set Identifier of the access point. /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the ESSID is passed as null. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid operation. public WiFiAP(string essid) { Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid); createHandle(essid, true); Initialize(); } /// /// Creates an object for the hidden access point. /// /// 3 /// The Extended Service Set Identifier of the access point. /// The value to set a hidden AP. /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the ESSID is passed as null. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid operation. public WiFiAP(string essid, bool hidden) { createHandle(essid, hidden); Initialize(); } /// /// Destroy the WiFiAP object /// ~WiFiAP() { Dispose(false); } /// /// A method to destroy the managed WiFiAP objects. /// /// 3 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (_disposed) return; if (disposing) { Interop.WiFi.AP.Destroy(_apHandle); _apHandle = IntPtr.Zero; } _disposed = true; } private void createHandle(string id, bool hidden) { int ret = -1; if (id == null) { throw new ArgumentNullException("Essid is null"); } if (hidden) { ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle); } else { ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle); } if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle()); } } private void Initialize() { Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle); _network = new WiFiNetwork(apHandle); _security = new WiFiSecurity(apHandle); } /// /// Refreshes the access point information. /// /// 3 /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the object instance is disposed or released. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public void Refresh() { Log.Debug(Globals.LogTag, "Refresh"); if (_disposed) { throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)"); } int ret = Interop.WiFi.AP.Refresh(_apHandle); if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get"); } } /// /// Connects the access point asynchronously. /// /// 3 /// A task indicating whether the connect method is done or not. /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.set /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the object instance is disposed or released. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public Task ConnectAsync() { Log.Debug(Globals.LogTag, "ConnectAsync"); if (_disposed) { throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)"); } TaskCompletionSource task = new TaskCompletionSource(); IntPtr id; lock (_callback_map) { id = (IntPtr)_requestId++; _callback_map[id] = (error, key) => { Log.Debug(Globals.LogTag, "Connecting finished : " + (WiFiError)error); if (error != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error); task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error)); } else { task.SetResult(true); } lock (_callback_map) { _callback_map.Remove(key); } }; } int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id); if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle); } return task.Task; } /// /// Connects the access point with the WPS asynchronously. /// /// 3 /// A WpsInfo instance which is type of WpsPbcInfo or WpsPinInfo. /// A task indicating whether the ConnectWps method is done or not. /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.profile /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the object instance is disposed or released. /// Thrown when the WpsPinInfo object is constructed with a null pin. /// Thrown when the WpsPinInfo object is constructed with a pin which is an empty string or more than 7 characters. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public Task ConnectWpsAsync(WpsInfo info) { Log.Debug(Globals.LogTag, "ConnectWpsAsync"); if (_disposed) { throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)"); } TaskCompletionSource task = new TaskCompletionSource(); IntPtr id; lock (_callback_map) { id = (IntPtr)_requestId++; _callback_map[id] = (error, key) => { Log.Debug(Globals.LogTag, "Connecting by WPS finished"); if (error != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error); task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error)); } else { task.SetResult(true); } lock (_callback_map) { _callback_map.Remove(key); } }; } int ret = -1; if (info.GetType() == typeof(WpsPbcInfo)) { ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id); } else if (info.GetType() == typeof(WpsPinInfo)) { WpsPinInfo pinInfo = (WpsPinInfo)info; if (pinInfo.GetWpsPin() == null) { throw new ArgumentNullException("Wps pin should not be null"); } if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8) { throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters"); } ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id); } if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle); } return task.Task; } /// /// Connects the access point with WPS without SSID asynchronously. /// /// 3 /// A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo. /// A task which contains Connected access point information. /// /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long. /// /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.set /// http://tizen.org/privilege/network.get /// http://tizen.org/privilege/network.profile /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the WpsPinInfo object is constructed with a null pin. /// Thrown when the WpsPinInfo object is constructed with a pin which is not of 4 or 8 characters long. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public static Task ConnectWpsWithoutSsidAsync(WpsInfo info) { TaskCompletionSource task = new TaskCompletionSource(); IntPtr id; lock (s_callbackMap) { id = (IntPtr)s_requestId++; s_callbackMap[id] = (error, key) => { Log.Debug(Globals.LogTag, "Connecting by WPS finished"); if (error != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error); task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error)); } else { WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP(); task.SetResult(ap); } lock (s_callbackMap) { s_callbackMap.Remove(key); } }; } int ret = -1; if (info.GetType() == typeof(WpsPbcInfo)) { ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id); } else if (info.GetType() == typeof(WpsPinInfo)) { WpsPinInfo pinInfo = (WpsPinInfo)info; if (pinInfo.GetWpsPin() == null) { throw new ArgumentNullException("Wps pin should not be null"); } if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8) { throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long"); } ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id); } if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle()); } return task.Task; } /// /// Disconnects the access point asynchronously. /// /// 3 /// A task indicating whether the disconnect method is done or not. /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.set /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the object instance is disposed or released. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public Task DisconnectAsync() { Log.Debug(Globals.LogTag, "DisconnectAsync"); if (_disposed) { throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)"); } TaskCompletionSource task = new TaskCompletionSource(); IntPtr id; lock (_callback_map) { id = (IntPtr)_requestId++; _callback_map[id] = (error, key) => { Log.Debug(Globals.LogTag, "Disconnecting finished"); if (error != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error); task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error)); } else { task.SetResult(true); } lock (_callback_map) { _callback_map.Remove(key); } }; } int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id); if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle); } return task.Task; } /// /// Deletes the information of a stored access point and disconnects it when the AP is connected. /// If an AP is connected, then the connection information will be stored. This information is used when a connection to that AP is established automatically. /// /// 3 /// http://tizen.org/feature/network.wifi /// http://tizen.org/privilege/network.profile /// http://tizen.org/privilege/network.get /// Thrown when the Wi-Fi is not supported. /// Thrown when permission is denied. /// Thrown when the object instance is disposed or released. /// Thrown when the system is out of memory. /// Thrown when the method failed due to an invalid parameter. /// Thrown when the method failed due to an invalid operation. public void ForgetAP() { Log.Debug(Globals.LogTag, "ForgetAP"); if (_disposed) { throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)"); } int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle); if (ret != (int)WiFiError.None) { Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret); WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle); } } } /// /// An abstract class which is used to represent the WPS information of the access point. /// /// 3 public abstract class WpsInfo { } /// /// A class which is used to represent WPS PBC information of the access point. /// public class WpsPbcInfo : WpsInfo { } /// /// A class which is used to represent WPS PIN information of the access point. /// public class WpsPinInfo : WpsInfo { private string _pin; private WpsPinInfo() { } /// /// A public constructor which instantiates WpsPinInfo class with the given pin. /// /// 3 /// WPS Pin of the access point. /// /// Pin should not be null or empty. It should be of less than 8 characters. /// public WpsPinInfo(string pin) { _pin = pin; } internal string GetWpsPin() { return _pin; } } }