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