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