[WiFi] Design issue fixes.
[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         public WiFiNetwork NetworkInformation
41         {
42             get
43             {
44                 return _network;
45             }
46         }
47
48         /// <summary>
49         /// The security information of the access point(AP).
50         /// </summary>
51         public WiFiSecurity SecurityInformation
52         {
53             get
54             {
55                 return _security;
56             }
57         }
58
59         internal WiFiAP(IntPtr handle)
60         {
61             Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle);
62             _apHandle = handle;
63             Initialize();
64         }
65
66         /// <summary>
67         /// Creates an object for the access point.
68         /// </summary>
69         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
70         public WiFiAP(string essid)
71         {
72             Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid);
73             createHandle(essid, true);
74             Initialize();
75         }
76
77         /// <summary>
78         /// Creates an object for the hidden access point.
79         /// </summary>
80         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
81         /// <param name="hidden">The value to set hidden AP</param>
82         public WiFiAP(string essid, bool hidden)
83         {
84             createHandle(essid, hidden);
85             Initialize();
86         }
87
88         ~WiFiAP()
89         {
90             Dispose(false);
91         }
92
93         /// <summary>
94         /// A method to destroy the managed WiFiAP objects.
95         /// </summary>
96         public void Dispose()
97         {
98             Dispose(true);
99             GC.SuppressFinalize(this);
100         }
101
102         private void Dispose(bool disposing)
103         {
104             if (_disposed)
105                 return;
106
107             if (disposing)
108             {
109                 Interop.WiFi.AP.Destroy(_apHandle);
110                 _apHandle = IntPtr.Zero;
111             }
112             _disposed = true;
113         }
114
115         private void createHandle(string id, bool hidden)
116         {
117             int ret = -1;
118             if (hidden)
119             {
120                 ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
121             }
122
123             else
124             {
125                 ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
126             }
127
128             if (ret != (int)WiFiError.None)
129             {
130                 Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret);
131                 WiFiErrorFactory.ThrowWiFiException(ret);
132             }
133         }
134
135         private void Initialize()
136         {
137             Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle);
138             _network = new WiFiNetwork(apHandle);
139             _security = new WiFiSecurity(apHandle);
140         }
141
142         /// <summary>
143         /// Refreshes the access point information.
144         /// </summary>
145         public void Refresh()
146         {
147             Log.Debug(Globals.LogTag, "Refresh");
148             int ret = Interop.WiFi.AP.Refresh(_apHandle);
149             if (ret != (int)WiFiError.None)
150             {
151                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
152                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle);
153             }
154         }
155
156         /// <summary>
157         /// Connects the access point asynchronously.
158         /// </summary>
159         /// <returns> A task indicating whether the Connect method is done or not.</returns>
160         public Task ConnectAsync()
161         {
162             Log.Debug(Globals.LogTag, "ConnectAsync");
163             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
164             IntPtr id;
165             lock (_callback_map)
166             {
167                 id = (IntPtr)_requestId++;
168                 _callback_map[id] = (error, key) =>
169                 {
170                     Log.Debug(Globals.LogTag, "Connecting finished : " + (WiFiError)error);
171                     if (error != (int)WiFiError.None)
172                     {
173                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
174                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
175                     }
176                     task.SetResult(true);
177                     lock (_callback_map)
178                     {
179                         _callback_map.Remove(key);
180                     }
181                 };
182             }
183             int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
184             if (ret != (int)WiFiError.None)
185             {
186                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
187                 WiFiErrorFactory.ThrowWiFiException(ret);
188             }
189             return task.Task;
190         }
191
192         /// <summary>
193         /// Connects the access point with WPS asynchronously.
194         /// </summary>
195         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
196         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
197         public Task ConnectWpsAsync(WpsInfo info)
198         {
199             Log.Debug(Globals.LogTag, "ConnectWpsAsync");
200             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
201             IntPtr id;
202             lock (_callback_map)
203             {
204                 id = (IntPtr)_requestId++;
205                 _callback_map[id] = (error, key) =>
206                 {
207                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
208                     if (error != (int)WiFiError.None)
209                     {
210                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
211                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
212                     }
213                     task.SetResult(true);
214                     lock (_callback_map)
215                     {
216                         _callback_map.Remove(key);
217                     }
218                 };
219             }
220
221             if (info.GetType() == typeof(WpsPbcInfo))
222             {
223                 int ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
224                 if (ret != (int)WiFiError.None)
225                 {
226                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
227                     WiFiErrorFactory.ThrowWiFiException(ret);
228                 }
229             }
230
231             else if (info.GetType() == typeof(WpsPinInfo))
232             {
233                 WpsPinInfo pinInfo = (WpsPinInfo)info;
234                 int ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
235                 if (ret != (int)WiFiError.None)
236                 {
237                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
238                     WiFiErrorFactory.ThrowWiFiException(ret);
239                 }
240             }
241
242             return task.Task;
243         }
244
245         /// <summary>
246         /// Connects the access point with WPS without ssid asynchronously.
247         /// </summary>
248         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
249         /// <returns>A task which contains Connected access point information.</returns>
250         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
251         {
252             TaskCompletionSource<WiFiAP> task = new TaskCompletionSource<WiFiAP>();
253             IntPtr id;
254             lock (s_callbackMap)
255             {
256                 id = (IntPtr)s_requestId++;
257                 s_callbackMap[id] = (error, key) =>
258                 {
259                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
260                     if (error != (int)WiFiError.None)
261                     {
262                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
263                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
264                     }
265                     WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
266                     task.SetResult(ap);
267                     lock (s_callbackMap)
268                     {
269                         s_callbackMap.Remove(key);
270                     }
271                 };
272             }
273
274             if (info.GetType() == typeof(WpsPbcInfo))
275             {
276                 int ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);
277                 if (ret != (int)WiFiError.None)
278                 {
279                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
280                     WiFiErrorFactory.ThrowWiFiException(ret);
281                 }
282             }
283
284             else if (info.GetType() == typeof(WpsPinInfo))
285             {
286                 WpsPinInfo pinInfo = (WpsPinInfo)info;
287                 int ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
288                 if (ret != (int)WiFiError.None)
289                 {
290                     Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
291                     WiFiErrorFactory.ThrowWiFiException(ret);
292                 }
293             }
294
295             return task.Task;
296         }
297
298         /// <summary>
299         /// Disconnects the access point asynchronously.
300         /// </summary>
301         /// <returns> A task indicating whether the Disconnect method is done or not.</returns>
302         public Task DisconnectAsync()
303         {
304             Log.Debug(Globals.LogTag, "DisconnectAsync");
305             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
306             IntPtr id;
307             lock (_callback_map)
308             {
309                 id = (IntPtr)_requestId++;
310                 _callback_map[id] = (error, key) =>
311                 {
312                     Log.Debug(Globals.LogTag, "Disconnecting finished");
313                     if (error != (int)WiFiError.None)
314                     {
315                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
316                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
317                     }
318                     task.SetResult(true);
319                     lock (_callback_map)
320                     {
321                         _callback_map.Remove(key);
322                     }
323                 };
324             }
325             int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
326             if (ret != (int)WiFiError.None)
327             {
328                 Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
329                 WiFiErrorFactory.ThrowWiFiException(ret);
330             }
331             return task.Task;
332         }
333
334         /// <summary>
335         /// Deletes the information of stored access point and disconnects it when it is connected.<br>
336         /// If an AP is connected, then connection information will be stored. This information is used when a connection to that AP is established automatically.
337         /// </summary>
338         public void ForgetAP()
339         {
340             Log.Debug(Globals.LogTag, "ForgetAP");
341             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
342             if (ret != (int)WiFiError.None)
343             {
344                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
345                 WiFiErrorFactory.ThrowWiFiException(ret);
346             }
347         }
348     }
349
350     /// <summary>
351     /// An abstract class which is used to represent WPS information of access point.
352     /// </summary>
353     public abstract class WpsInfo
354     {
355     }
356
357     /// <summary>
358     /// A class which is used to represent WPS PBC information of access point.
359     /// </summary>
360     public class WpsPbcInfo : WpsInfo
361     {
362     }
363
364     /// <summary>
365     /// A class which is used to represent WPS PIN information of access point.
366     /// </summary>
367     public class WpsPinInfo : WpsInfo
368     {
369         private string _pin;
370
371         private WpsPinInfo()
372         {
373         }
374
375         /// <summary>
376         /// A public constructor which instantiates WpsPinInfo class with the given pin.
377         /// </summary>
378         /// <param name="pin">WPS Pin of the access point.</param>
379         public WpsPinInfo(string pin)
380         {
381             _pin = pin;
382         }
383
384         internal string GetWpsPin()
385         {
386             return _pin;
387         }
388     }
389 }