Add API reference and exception as per the guidelines
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.WiFi / Tizen.Network.WiFi / WiFiAP.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.Threading.Tasks;
19 using System.Collections.Generic;
20
21 namespace Tizen.Network.WiFi
22 {
23     /// <summary>
24     /// A class for managing the network information of the access point(AP).
25     /// </summary>
26     public class WiFiAP : IDisposable
27     {
28         private IntPtr _apHandle = IntPtr.Zero;
29         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
30         private static Dictionary<IntPtr, Interop.WiFi.VoidCallback> s_callbackMap = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
31         private int _requestId = 0;
32         private static int s_requestId = 0;
33         private WiFiNetwork _network;
34         private WiFiSecurity _security;
35         private bool _disposed = false;
36
37         /// <summary>
38         /// The network information of the access point(AP).
39         /// </summary>
40         /// <value>WiFiNetwork instance containing network information of AP.</value>
41         public WiFiNetwork NetworkInformation
42         {
43             get
44             {
45                 return _network;
46             }
47         }
48
49         /// <summary>
50         /// The security information of the access point(AP).
51         /// </summary>
52         /// <value>WiFiSecurity instance containing security information of AP.</value>
53         public WiFiSecurity SecurityInformation
54         {
55             get
56             {
57                 return _security;
58             }
59         }
60
61         internal WiFiAP(IntPtr handle)
62         {
63             Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle);
64             _apHandle = handle;
65             Initialize();
66         }
67
68         /// <summary>
69         /// Creates an object for the access point.
70         /// </summary>
71         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
72         /// <feature>http://tizen.org/feature/network.wifi</feature>
73         /// <privilege>http://tizen.org/privilege/network.get</privilege>
74         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
75         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
76         /// <exception cref="ArgumentNullException">Thrown when Essid is passed as null.</exception>
77         /// <exception cref="ArgumentException">Thrown when it is failed due to an invalid parameter.</exception>
78         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
79         /// <exception cref="InvalidOperationException">Thrown when it is failed due to invalid operation.</exception>
80         public WiFiAP(string essid)
81         {
82             Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid);
83             createHandle(essid, true);
84             Initialize();
85         }
86
87         /// <summary>
88         /// Creates an object for the hidden access point.
89         /// </summary>
90         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
91         /// <param name="hidden">The value to set hidden AP</param>
92         /// <feature>http://tizen.org/feature/network.wifi</feature>
93         /// <privilege>http://tizen.org/privilege/network.get</privilege>
94         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
95         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
96         /// <exception cref="ArgumentNullException">Thrown when Essid is passed as null.</exception>
97         /// <exception cref="ArgumentException">Thrown when it is failed due to an invalid parameter.</exception>
98         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
99         /// <exception cref="InvalidOperationException">Thrown when it is failed due to invalid operation.</exception>
100         public WiFiAP(string essid, bool hidden)
101         {
102             createHandle(essid, hidden);
103             Initialize();
104         }
105
106         ~WiFiAP()
107         {
108             Dispose(false);
109         }
110
111         /// <summary>
112         /// A method to destroy the managed WiFiAP objects.
113         /// </summary>
114         public void Dispose()
115         {
116             Dispose(true);
117             GC.SuppressFinalize(this);
118         }
119
120         private void Dispose(bool disposing)
121         {
122             if (_disposed)
123                 return;
124
125             if (disposing)
126             {
127                 Interop.WiFi.AP.Destroy(_apHandle);
128                 _apHandle = IntPtr.Zero;
129             }
130             _disposed = true;
131         }
132
133         private void createHandle(string id, bool hidden)
134         {
135             int ret = -1;
136             if (id == null)
137             {
138                 throw new ArgumentNullException("Essid is null");
139             }
140
141             if (hidden)
142             {
143                 ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
144             }
145
146             else
147             {
148                 ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
149             }
150
151             if (ret != (int)WiFiError.None)
152             {
153                 Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret);
154                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
155             }
156         }
157
158         private void Initialize()
159         {
160             Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle);
161             _network = new WiFiNetwork(apHandle);
162             _security = new WiFiSecurity(apHandle);
163         }
164
165         /// <summary>
166         /// Refreshes the access point information.
167         /// </summary>
168         /// <feature>http://tizen.org/feature/network.wifi</feature>
169         /// <privilege>http://tizen.org/privilege/network.get</privilege>
170         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
171         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
172         /// <exception cref="ObjectDisposedException">Thrown when object instance is disposed or released.</exception>
173         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
174         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
175         public void Refresh()
176         {
177             Log.Debug(Globals.LogTag, "Refresh");
178             if (_disposed)
179             {
180                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
181             }
182             int ret = Interop.WiFi.AP.Refresh(_apHandle);
183             if (ret != (int)WiFiError.None)
184             {
185                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
186                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get");
187             }
188         }
189
190         /// <summary>
191         /// Connects the access point asynchronously.
192         /// </summary>
193         /// <returns> A task indicating whether the Connect method is done or not.</returns>
194         /// <feature>http://tizen.org/feature/network.wifi</feature>
195         /// <privilege>http://tizen.org/privilege/network.set</privilege>
196         /// <privilege>http://tizen.org/privilege/network.get</privilege>
197         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
198         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
199         /// <exception cref="ObjectDisposedException">Thrown when object instance is disposed or released.</exception>
200         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
201         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
202         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
203         public Task ConnectAsync()
204         {
205             Log.Debug(Globals.LogTag, "ConnectAsync");
206             if (_disposed)
207             {
208                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
209             }
210             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
211             IntPtr id;
212             lock (_callback_map)
213             {
214                 id = (IntPtr)_requestId++;
215                 _callback_map[id] = (error, key) =>
216                 {
217                     Log.Debug(Globals.LogTag, "Connecting finished : " + (WiFiError)error);
218                     if (error != (int)WiFiError.None)
219                     {
220                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
221                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
222                     }
223                     task.SetResult(true);
224                     lock (_callback_map)
225                     {
226                         _callback_map.Remove(key);
227                     }
228                 };
229             }
230
231             int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
232             if (ret != (int)WiFiError.None)
233             {
234                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
235                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
236             }
237
238             return task.Task;
239         }
240
241         /// <summary>
242         /// Connects the access point with WPS asynchronously.
243         /// </summary>
244         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
245         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
246         /// <feature>http://tizen.org/feature/network.wifi</feature>
247         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
248         /// <privilege>http://tizen.org/privilege/network.get</privilege>
249         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
250         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
251         /// <exception cref="ObjectDisposedException">Thrown when object instance is disposed or released.</exception>
252         /// <exception cref="ArgumentNullException">Thrown when WpsPinInfo object is constructed with null pin.</exception>
253         /// <exception cref="ArgumentOutOfRangeException">Thrown when WpsPinInfo object is constructed with pin which is an empty string or more than 7 characters.</exception>
254         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
255         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
256         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
257         public Task ConnectWpsAsync(WpsInfo info)
258         {
259             Log.Debug(Globals.LogTag, "ConnectWpsAsync");
260             if (_disposed)
261             {
262                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
263             }
264             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
265             IntPtr id;
266             lock (_callback_map)
267             {
268                 id = (IntPtr)_requestId++;
269                 _callback_map[id] = (error, key) =>
270                 {
271                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
272                     if (error != (int)WiFiError.None)
273                     {
274                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
275                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
276                     }
277                     task.SetResult(true);
278                     lock (_callback_map)
279                     {
280                         _callback_map.Remove(key);
281                     }
282                 };
283             }
284
285             int ret = -1;
286             if (info.GetType() == typeof(WpsPbcInfo))
287             {
288                 ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
289             }
290
291             else if (info.GetType() == typeof(WpsPinInfo))
292             {
293                 WpsPinInfo pinInfo = (WpsPinInfo)info;
294                 if (pinInfo.GetWpsPin() == null)
295                 {
296                     throw new ArgumentNullException("Wps pin should not be null");
297                 }
298
299                 if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8)
300                 {
301                     throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters");
302                 }
303
304                 ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
305             }
306
307             if (ret != (int)WiFiError.None)
308             {
309                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
310                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
311             }
312
313             return task.Task;
314         }
315
316         /// <summary>
317         /// Connects the access point with WPS without ssid asynchronously.
318         /// </summary>
319         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
320         /// <returns>A task which contains Connected access point information.</returns>
321         /// <remarks>
322         /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long.
323         /// </remarks>
324         /// <feature>http://tizen.org/feature/network.wifi</feature>
325         /// <privilege>http://tizen.org/privilege/network.set</privilege>
326         /// <privilege>http://tizen.org/privilege/network.get</privilege>
327         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
328         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
329         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
330         /// <exception cref="ArgumentNullException">Thrown when WpsPinInfo object is constructed with null pin.</exception>
331         /// <exception cref="ArgumentOutOfRangeException">Thrown when WpsPinInfo object is constructed with pin which is not of 4 or 8 characters long.</exception>
332         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
333         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
334         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
335         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
336         {
337             TaskCompletionSource<WiFiAP> task = new TaskCompletionSource<WiFiAP>();
338             IntPtr id;
339             lock (s_callbackMap)
340             {
341                 id = (IntPtr)s_requestId++;
342                 s_callbackMap[id] = (error, key) =>
343                 {
344                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
345                     if (error != (int)WiFiError.None)
346                     {
347                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
348                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
349                     }
350                     WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
351                     task.SetResult(ap);
352                     lock (s_callbackMap)
353                     {
354                         s_callbackMap.Remove(key);
355                     }
356                 };
357             }
358
359             int ret = -1;
360             if (info.GetType() == typeof(WpsPbcInfo))
361             {
362                 ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);   
363             }
364
365             else if (info.GetType() == typeof(WpsPinInfo))
366             {
367                 WpsPinInfo pinInfo = (WpsPinInfo)info;
368                 if (pinInfo.GetWpsPin() == null)
369                 {
370                     throw new ArgumentNullException("Wps pin should not be null");
371                 }
372
373                 if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8)
374                 {
375                     throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long");
376                 }
377
378                 ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
379             }
380
381             if (ret != (int)WiFiError.None)
382             {
383                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
384                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
385             }
386
387             return task.Task;
388         }
389
390         /// <summary>
391         /// Disconnects the access point asynchronously.
392         /// </summary>
393         /// <returns> A task indicating whether the Disconnect method is done or not.</returns>
394         /// <feature>http://tizen.org/feature/network.wifi</feature>
395         /// <privilege>http://tizen.org/privilege/network.set</privilege>
396         /// <privilege>http://tizen.org/privilege/network.get</privilege>
397         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
398         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
399         /// <exception cref="ObjectDisposedException">Thrown when object instance is disposed or released.</exception>
400         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
401         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
402         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
403         public Task DisconnectAsync()
404         {
405             Log.Debug(Globals.LogTag, "DisconnectAsync");
406             if (_disposed)
407             {
408                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
409             }
410             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
411             IntPtr id;
412             lock (_callback_map)
413             {
414                 id = (IntPtr)_requestId++;
415                 _callback_map[id] = (error, key) =>
416                 {
417                     Log.Debug(Globals.LogTag, "Disconnecting finished");
418                     if (error != (int)WiFiError.None)
419                     {
420                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
421                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
422                     }
423                     task.SetResult(true);
424                     lock (_callback_map)
425                     {
426                         _callback_map.Remove(key);
427                     }
428                 };
429             }
430             int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
431             if (ret != (int)WiFiError.None)
432             {
433                 Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
434                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
435             }
436             return task.Task;
437         }
438
439         /// <summary>
440         /// Deletes the information of stored access point and disconnects it when it is connected.<br>
441         /// If an AP is connected, then connection information will be stored. This information is used when a connection to that AP is established automatically.
442         /// </summary>
443         /// <feature>http://tizen.org/feature/network.wifi</feature>
444         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
445         /// <privilege>http://tizen.org/privilege/network.get</privilege>
446         /// <exception cref="NotSupportedException">Thrown when WiFi is not supported.</exception>
447         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
448         /// <exception cref="ObjectDisposedException">Thrown when object instance is disposed or released.</exception>
449         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
450         /// <exception cref="ArgumentException">Thrown when method is failed due to an invalid parameter.</exception>
451         /// <exception cref="InvalidOperationException">Thrown when the method failed due to invalid operation.</exception>
452         public void ForgetAP()
453         {
454             Log.Debug(Globals.LogTag, "ForgetAP");
455             if (_disposed)
456             {
457                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
458             }
459             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
460             if (ret != (int)WiFiError.None)
461             {
462                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
463                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
464             }
465         }
466     }
467
468     /// <summary>
469     /// An abstract class which is used to represent WPS information of access point.
470     /// </summary>
471     public abstract class WpsInfo
472     {
473     }
474
475     /// <summary>
476     /// A class which is used to represent WPS PBC information of access point.
477     /// </summary>
478     public class WpsPbcInfo : WpsInfo
479     {
480     }
481
482     /// <summary>
483     /// A class which is used to represent WPS PIN information of access point.
484     /// </summary>
485     public class WpsPinInfo : WpsInfo
486     {
487         private string _pin;
488
489         private WpsPinInfo()
490         {
491         }
492
493         /// <summary>
494         /// A public constructor which instantiates WpsPinInfo class with the given pin.
495         /// </summary>
496         /// <param name="pin">WPS Pin of the access point.</param>
497         /// <remarks>
498         /// Pin should not be null or empty. It should be of less than 8 characters.
499         /// </remarks>
500         public WpsPinInfo(string pin)
501         {
502             _pin = pin;
503         }
504
505         internal string GetWpsPin()
506         {
507             return _pin;
508         }
509     }
510 }