[Connection][WiFi] Use TizenSynchronizationContext.Post for asynchronous methods...
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Connection / Tizen.Network.Connection / ConnectionProfile.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.Collections.Generic;
19 using System.Linq;
20 using System.Text;
21 using System.Runtime.InteropServices;
22 using Tizen.Applications;
23
24 namespace Tizen.Network.Connection
25 {
26     /// <summary>
27     /// This is the ConnectionProfile class. It provides event and properties of the connection profile.
28     /// </summary>
29     /// <since_tizen> 3 </since_tizen>
30     public class ConnectionProfile : IDisposable
31     {
32         internal IntPtr ProfileHandle = IntPtr.Zero;
33         private IAddressInformation IPv4;
34         private IAddressInformation IPv6;
35         private bool disposed = false;
36         private EventHandler<ProfileStateEventArgs> _ProfileStateChanged = null;
37
38         private Interop.ConnectionProfile.ProfileStateChangedCallback _profileChangedCallback;
39
40         private TizenSynchronizationContext context = new TizenSynchronizationContext();
41
42         internal IntPtr GetHandle()
43         {
44             return ProfileHandle;
45         }
46
47         /// <summary>
48         /// The event is called when the state of profile is changed.
49         /// </summary>
50         /// <since_tizen> 3 </since_tizen>
51         /// <feature>http://tizen.org/feature/network.ethernet</feature>
52         /// <feature>http://tizen.org/feature/network.telephony</feature>
53         /// <feature>http://tizen.org/feature/network.tethering.bluetooth</feature>
54         /// <feature>http://tizen.org/feature/network.wifi</feature>
55         /// <exception cref="System.NotSupportedException">Thrown when a feature is not supported.</exception>
56         public event EventHandler<ProfileStateEventArgs> ProfileStateChanged
57         {
58             add
59             {
60                 Log.Debug(Globals.LogTag, "ProfileStateChanged add");
61                 context.Post((x) =>
62                 {
63                     if (_ProfileStateChanged == null)
64                     {
65                         ProfileStateChangedStart();
66                     }
67                     _ProfileStateChanged += value;
68                 }, null);
69             }
70             remove
71             {
72                 Log.Debug(Globals.LogTag, "ProfileStateChanged remove");
73                 context.Post((x) =>
74                 {
75                     _ProfileStateChanged -= value;
76                     if (_ProfileStateChanged == null)
77                     {
78                         ProfileStateChangedStop();
79                     }
80                 }, null);
81             }
82         }
83
84         private void ProfileStateChangedStart()
85         {
86             _profileChangedCallback = (ProfileState state, IntPtr userData) =>
87             {
88                 Log.Info(Globals.LogTag, "***** MOON ProfileStateChanged occur");
89                 if (_ProfileStateChanged != null)
90                 {
91                     _ProfileStateChanged(null, new ProfileStateEventArgs(state));
92                 }
93             };
94
95             Log.Debug(Globals.LogTag, "ProfileStateChangedStart");
96             int ret = Interop.ConnectionProfile.SetStateChangeCallback(ProfileHandle, _profileChangedCallback, IntPtr.Zero);
97             if ((ConnectionError)ret != ConnectionError.None)
98             {
99                 Log.Error(Globals.LogTag, "It failed to register callback for changing profile state, " + (ConnectionError)ret);
100             }
101         }
102
103         private void ProfileStateChangedStop()
104         {
105             Log.Debug(Globals.LogTag, "ProfileStateChangedStop");
106             int ret = Interop.ConnectionProfile.UnsetStateChangeCallback(ProfileHandle);
107             if ((ConnectionError)ret != ConnectionError.None)
108             {
109                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing profile state, " + (ConnectionError)ret);
110             }
111         }
112
113         internal ConnectionProfile(IntPtr handle)
114         {
115             ProfileHandle = handle;
116             IPv4 = new ConnectionAddressInformation(ProfileHandle, AddressFamily.IPv4);
117             IPv6 = new ConnectionAddressInformation(ProfileHandle, AddressFamily.IPv6);
118         }
119
120         /// <summary>
121         /// Destroy the ConnectionProfile object
122         /// </summary>
123         ~ConnectionProfile()
124         {
125             Dispose(false);
126         }
127
128         /// <summary>
129         /// Disposes the memory allocated to unmanaged resources.
130         /// </summary>
131         /// <since_tizen> 3 </since_tizen>
132         public void Dispose()
133         {
134             Dispose(true);
135             GC.SuppressFinalize(this);
136         }
137
138         private void Dispose(bool disposing)
139         {
140             Log.Debug(Globals.LogTag, ">>> ConnectionProfile Dispose with " + disposing);
141             if (disposed)
142                 return;
143
144             // Free unmanaged objects
145             UnregisterEvents();
146             Destroy();
147             disposed = true;
148         }
149
150         private void UnregisterEvents()
151         {
152             if (_ProfileStateChanged != null)
153             {
154                 ProfileStateChangedStop();
155             }
156         }
157
158         private void Destroy()
159         {
160             Interop.ConnectionProfile.Destroy(ProfileHandle);
161             ProfileHandle = IntPtr.Zero;
162         }
163
164         internal void CheckDisposed()
165         {
166             if (disposed)
167             {
168                 throw new ObjectDisposedException(GetType().FullName);
169             }
170         }
171
172         /// <summary>
173         /// The profile ID.
174         /// </summary>
175         /// <since_tizen> 3 </since_tizen>
176         /// <value>Unique ID of the profile.</value>
177         public string Id
178         {
179             get
180             {
181                 IntPtr Value;
182                 int ret = Interop.ConnectionProfile.GetId(ProfileHandle, out Value);
183                 if ((ConnectionError)ret != ConnectionError.None)
184                 {
185                     Log.Error(Globals.LogTag, "It failed to get id of connection profile, " + (ConnectionError)ret);
186                 }
187                 string result = Marshal.PtrToStringAnsi(Value);
188                 Interop.Libc.Free(Value);
189                 return result;
190             }
191         }
192
193         /// <summary>
194         /// The profile name.
195         /// </summary>
196         /// <since_tizen> 3 </since_tizen>
197         /// <value>User friendly name of the profile.</value>
198         public string Name
199         {
200             get
201             {
202                 IntPtr Value;
203                 int ret = Interop.ConnectionProfile.GetName(ProfileHandle, out Value);
204                 if ((ConnectionError)ret != ConnectionError.None)
205                 {
206                     Log.Error(Globals.LogTag, "It failed to get name of connection profile, " + (ConnectionError)ret);
207                 }
208                 string result = Marshal.PtrToStringAnsi(Value);
209                 Interop.Libc.Free(Value);
210                 return result;
211             }
212         }
213
214         /// <summary>
215         /// The network type.
216         /// </summary>
217         /// <since_tizen> 3 </since_tizen>
218         /// <value>Profile type of the network connection.</value>
219         public ConnectionProfileType Type
220         {
221             get
222             {
223                 int Value;
224                 int ret = Interop.ConnectionProfile.GetType(ProfileHandle, out Value);
225                 if ((ConnectionError)ret != ConnectionError.None)
226                 {
227                     Log.Error(Globals.LogTag, "It failed to get type of connection profile, " + (ConnectionError)ret);
228                 }
229                 return (ConnectionProfileType)Value;
230             }
231         }
232
233         /// <summary>
234         /// The name of the network interface.
235         /// </summary>
236         /// <since_tizen> 3 </since_tizen>
237         /// <value>Network interface name, for example, eth0 and pdp0.</value>
238         public string InterfaceName
239         {
240             get
241             {
242                 IntPtr Value;
243                 int ret = Interop.ConnectionProfile.GetNetworkInterfaceName(ProfileHandle, out Value);
244                 if ((ConnectionError)ret != ConnectionError.None)
245                 {
246                     Log.Error(Globals.LogTag, "It failed to get network interface name, " + (ConnectionError)ret);
247                 }
248                 string result = Marshal.PtrToStringAnsi(Value);
249                 Interop.Libc.Free(Value);
250                 return result;
251             }
252         }
253
254         /// <summary>
255         /// Refreshes the profile information.
256         /// </summary>
257         /// <since_tizen> 3 </since_tizen>
258         /// <privilege>http://tizen.org/privilege/network.get</privilege>
259         /// <feature>http://tizen.org/feature/network.ethernet</feature>
260         /// <feature>http://tizen.org/feature/network.telephony</feature>
261         /// <feature>http://tizen.org/feature/network.tethering.bluetooth</feature>
262         /// <feature>http://tizen.org/feature/network.wifi</feature>
263         /// <exception cref="System.NotSupportedException">Thrown when a feature is not supported.</exception>
264         /// <exception cref="System.UnauthorizedAccessException">Thrown when a permission is denied.</exception>
265         /// <exception cref="System.ArgumentException">Thrown when a value is an invalid parameter.</exception>
266         /// <exception cref="System.InvalidOperationException">Thrown when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
267         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
268         public void Refresh()
269         {
270             CheckDisposed();
271             int ret = Interop.ConnectionProfile.Refresh(ProfileHandle);
272             if ((ConnectionError)ret != ConnectionError.None)
273             {
274                 Log.Error(Globals.LogTag, "It failed to get network interface name, " + (ConnectionError)ret);
275                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
276                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
277                 ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
278                 ConnectionErrorFactory.ThrowConnectionException(ret);
279             }
280         }
281
282         /// <summary>
283         /// Gets the network state.
284         /// </summary>
285         /// <since_tizen> 3 </since_tizen>
286         /// <param name="family">The address family.</param>
287         /// <returns>The network state.</returns>
288         /// <feature>http://tizen.org/feature/network.ethernet</feature>
289         /// <feature>http://tizen.org/feature/network.telephony</feature>
290         /// <feature>http://tizen.org/feature/network.tethering.bluetooth</feature>
291         /// <feature>http://tizen.org/feature/network.wifi</feature>
292         /// <exception cref="System.NotSupportedException">Thrown when a feature is not supported.</exception>
293         /// <exception cref="System.ArgumentException">Thrown when a value is an invalid parameter.</exception>
294         /// <exception cref="System.InvalidOperationException">Thrown when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
295         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
296         public ProfileState GetState(AddressFamily family)
297         {
298             CheckDisposed();
299             int Value;
300             int ret = (int)ConnectionError.None;
301             if (family == AddressFamily.IPv4)
302             {
303                 ret = Interop.ConnectionProfile.GetState(ProfileHandle, out Value);
304             }
305
306             else
307             {
308                 ret = Interop.ConnectionProfile.GetIPv6State(ProfileHandle, out Value);
309             }
310
311             if ((ConnectionError)ret != ConnectionError.None)
312             {
313                 Log.Error(Globals.LogTag, "It failed to get profile state, " + (ConnectionError)ret);
314                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
315                 ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
316                 ConnectionErrorFactory.ThrowConnectionException(ret);
317             }
318
319             return (ProfileState)Value;
320         }
321
322         /// <summary>
323         /// The Proxy type.
324         /// </summary>
325         /// <since_tizen> 3 </since_tizen>
326         /// <value>Proxy type of the connection.</value>
327         /// <exception cref="System.NotSupportedException">Thrown during set when a feature is not supported.</exception>
328         /// <exception cref="System.ArgumentException">Thrown during set when a value is an invalid parameter.</exception>
329         /// <exception cref="System.InvalidOperationException">Thrown during set when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
330         /// <exception cref="System.ObjectDisposedException">Thrown during set when a operation is performed on a disposed object.</exception>
331         public ProxyType ProxyType
332         {
333             get
334             {
335                 int Value;
336                 int ret = Interop.ConnectionProfile.GetProxyType(ProfileHandle, out Value);
337                 if ((ConnectionError)ret != ConnectionError.None)
338                 {
339                     Log.Error(Globals.LogTag, "It failed to get proxy type, " + (ConnectionError)ret);
340                 }
341                 return (ProxyType)Value;
342
343             }
344
345             set
346             {
347                 CheckDisposed();
348                 int ret = Interop.ConnectionProfile.SetProxyType(ProfileHandle, (int)value);
349                 if ((ConnectionError)ret != ConnectionError.None)
350                 {
351                     Log.Error(Globals.LogTag, "It failed to set proxy type, " + (ConnectionError)ret);
352                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
353                     ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
354                     ConnectionErrorFactory.ThrowConnectionException(ret);
355                 }
356             }
357         }
358
359         /// <summary>
360         /// The proxy address.
361         /// </summary>
362         /// <since_tizen> 3 </since_tizen>
363         /// <value>Proxy address of the connection.</value>
364         /// <exception cref="System.NotSupportedException">Thrown during set when a feature is not supported.</exception>
365         /// <exception cref="System.ArgumentException">Thrown during set when a value is an invalid parameter.</exception>
366         /// <exception cref="System.ArgumentNullException">Thrown during set when a value is null.</exception>
367         /// <exception cref="System.InvalidOperationException">Thrown during set when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
368         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
369         public string ProxyAddress
370         {
371             get
372             {
373                 IntPtr Value;
374                 int ret = Interop.ConnectionProfile.GetProxyAddress(ProfileHandle, (int)AddressFamily.IPv4, out Value);
375                 if ((ConnectionError)ret != ConnectionError.None)
376                 {
377                     Log.Error(Globals.LogTag, "It failed to get proxy address, " + (ConnectionError)ret);
378                 }
379                 string result = Marshal.PtrToStringAnsi(Value);
380                 Interop.Libc.Free(Value);
381                 return result;
382
383             }
384
385             set
386             {
387                 CheckDisposed();
388                 if (value != null)
389                 {
390                     int ret = Interop.ConnectionProfile.SetProxyAddress(ProfileHandle, (int)AddressFamily.IPv4, value);
391                     if ((ConnectionError)ret != ConnectionError.None)
392                     {
393                         Log.Error(Globals.LogTag, "It failed to set proxy address, " + (ConnectionError)ret);
394                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
395                         ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
396                         ConnectionErrorFactory.ThrowConnectionException(ret);
397                     }
398                 }
399
400                 else
401                 {
402                     throw new ArgumentNullException("ProxyAddress is null");
403                 }
404             }
405         }
406
407         /// <summary>
408         /// The address information (IPv4).
409         /// </summary>
410         /// <since_tizen> 3 </since_tizen>
411         /// <value>Instance of IAddressInformation with IPV4 address.</value>
412         public IAddressInformation IPv4Settings
413         {
414             get
415             {
416                 return IPv4;
417
418             }
419         }
420
421         /// <summary>
422         /// The address information (IPv6).
423         /// </summary>
424         /// <since_tizen> 3 </since_tizen>
425         /// <value>Instance of IAddressInformation with IPV6 address.</value>
426         public IAddressInformation IPv6Settings
427         {
428             get
429             {
430                 return IPv6;
431             }
432         }
433     }
434
435     /// <summary>
436     /// An extended EventArgs class, which contains changed profile state.
437     /// </summary>
438     /// <since_tizen> 3 </since_tizen>
439     public class ProfileStateEventArgs : EventArgs
440     {
441         private ProfileState _State = ProfileState.Disconnected;
442
443         internal ProfileStateEventArgs(ProfileState state)
444         {
445             _State = state;
446         }
447
448         /// <summary>
449         /// The profile state.
450         /// </summary>
451         /// <since_tizen> 3 </since_tizen>
452         /// <value>State type of the connection profile.</value>
453         public ProfileState State
454         {
455             get
456             {
457                 return _State;
458             }
459         }
460     }
461 }