/*
* 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();
}
~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;
}
}
}