Release 5.0.0.14403
[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                         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.ArgumentException">Thrown when a value is an invalid parameter.</exception>
285         /// <exception cref="System.InvalidOperationException">Thrown when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
286         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
287         public void Refresh()
288         {
289             CheckDisposed();
290             int ret = Interop.ConnectionProfile.Refresh(ProfileHandle);
291             if ((ConnectionError)ret != ConnectionError.None)
292             {
293                 Log.Error(Globals.LogTag, "It failed to get network interface name, " + (ConnectionError)ret);
294                 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");
295                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
296                 ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
297                 ConnectionErrorFactory.ThrowConnectionException(ret);
298             }
299         }
300
301         /// <summary>
302         /// Gets the network state.
303         /// </summary>
304         /// <since_tizen> 3 </since_tizen>
305         /// <param name="family">The address family.</param>
306         /// <returns>The network state.</returns>
307         /// <feature>http://tizen.org/feature/network.ethernet</feature>
308         /// <feature>http://tizen.org/feature/network.telephony</feature>
309         /// <feature>http://tizen.org/feature/network.tethering.bluetooth</feature>
310         /// <feature>http://tizen.org/feature/network.wifi</feature>
311         /// <exception cref="System.NotSupportedException">Thrown when a feature is not supported.</exception>
312         /// <exception cref="System.ArgumentException">Thrown when a value is an invalid parameter.</exception>
313         /// <exception cref="System.InvalidOperationException">Thrown when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
314         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
315         public ProfileState GetState(AddressFamily family)
316         {
317             CheckDisposed();
318             int Value;
319             int ret = (int)ConnectionError.None;
320             if (family == AddressFamily.IPv4)
321             {
322                 ret = Interop.ConnectionProfile.GetState(ProfileHandle, out Value);
323             }
324
325             else
326             {
327                 ret = Interop.ConnectionProfile.GetIPv6State(ProfileHandle, out Value);
328             }
329
330             if ((ConnectionError)ret != ConnectionError.None)
331             {
332                 Log.Error(Globals.LogTag, "It failed to get profile state, " + (ConnectionError)ret);
333                 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");
334                 ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
335                 ConnectionErrorFactory.ThrowConnectionException(ret);
336             }
337
338             return (ProfileState)Value;
339         }
340
341         /// <summary>
342         /// The Proxy type.
343         /// </summary>
344         /// <since_tizen> 3 </since_tizen>
345         /// <value>Proxy type of the connection.</value>
346         /// <exception cref="System.NotSupportedException">Thrown during set when a feature is not supported.</exception>
347         /// <exception cref="System.ArgumentException">Thrown during set when a value is an invalid parameter.</exception>
348         /// <exception cref="System.InvalidOperationException">Thrown during set when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
349         /// <exception cref="System.ObjectDisposedException">Thrown during set when a operation is performed on a disposed object.</exception>
350         public ProxyType ProxyType
351         {
352             get
353             {
354                 int Value;
355                 int ret = Interop.ConnectionProfile.GetProxyType(ProfileHandle, out Value);
356                 if ((ConnectionError)ret != ConnectionError.None)
357                 {
358                     Log.Error(Globals.LogTag, "It failed to get proxy type, " + (ConnectionError)ret);
359                 }
360                 return (ProxyType)Value;
361
362             }
363
364             set
365             {
366                 CheckDisposed();
367                 int ret = Interop.ConnectionProfile.SetProxyType(ProfileHandle, (int)value);
368                 if ((ConnectionError)ret != ConnectionError.None)
369                 {
370                     Log.Error(Globals.LogTag, "It failed to set proxy type, " + (ConnectionError)ret);
371                     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");
372                     ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
373                     ConnectionErrorFactory.ThrowConnectionException(ret);
374                 }
375             }
376         }
377
378         /// <summary>
379         /// The proxy address.
380         /// </summary>
381         /// <since_tizen> 3 </since_tizen>
382         /// <value>Proxy address of the connection.</value>
383         /// <exception cref="System.NotSupportedException">Thrown during set when a feature is not supported.</exception>
384         /// <exception cref="System.ArgumentException">Thrown during set when a value is an invalid parameter.</exception>
385         /// <exception cref="System.ArgumentNullException">Thrown during set when a value is null.</exception>
386         /// <exception cref="System.InvalidOperationException">Thrown during set when a profile instance is invalid or when a method fails due to an invalid operation.</exception>
387         /// <exception cref="System.ObjectDisposedException">Thrown when an operation is performed on a disposed object.</exception>
388         public string ProxyAddress
389         {
390             get
391             {
392                 IntPtr Value;
393                 int ret = Interop.ConnectionProfile.GetProxyAddress(ProfileHandle, (int)AddressFamily.IPv4, out Value);
394                 if ((ConnectionError)ret != ConnectionError.None)
395                 {
396                     Log.Error(Globals.LogTag, "It failed to get proxy address, " + (ConnectionError)ret);
397                 }
398                 string result = Marshal.PtrToStringAnsi(Value);
399                 Interop.Libc.Free(Value);
400                 return result;
401
402             }
403
404             set
405             {
406                 CheckDisposed();
407                 if (value != null)
408                 {
409                     int ret = Interop.ConnectionProfile.SetProxyAddress(ProfileHandle, (int)AddressFamily.IPv4, value);
410                     if ((ConnectionError)ret != ConnectionError.None)
411                     {
412                         Log.Error(Globals.LogTag, "It failed to set proxy address, " + (ConnectionError)ret);
413                         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");
414                         ConnectionErrorFactory.CheckHandleNullException(ret, (ProfileHandle == IntPtr.Zero), "ProfileHandle may have been disposed or released");
415                         ConnectionErrorFactory.ThrowConnectionException(ret);
416                     }
417                 }
418
419                 else
420                 {
421                     throw new ArgumentNullException("ProxyAddress is null");
422                 }
423             }
424         }
425
426         /// <summary>
427         /// The address information (IPv4).
428         /// </summary>
429         /// <since_tizen> 3 </since_tizen>
430         /// <value>Instance of IAddressInformation with IPV4 address.</value>
431         public IAddressInformation IPv4Settings
432         {
433             get
434             {
435                 return IPv4;
436
437             }
438         }
439
440         /// <summary>
441         /// The address information (IPv6).
442         /// </summary>
443         /// <since_tizen> 3 </since_tizen>
444         /// <value>Instance of IAddressInformation with IPV6 address.</value>
445         public IAddressInformation IPv6Settings
446         {
447             get
448             {
449                 return IPv6;
450             }
451         }
452     }
453
454     /// <summary>
455     /// An extended EventArgs class, which contains changed profile state.
456     /// </summary>
457     /// <since_tizen> 3 </since_tizen>
458     public class ProfileStateEventArgs : EventArgs
459     {
460         private ProfileState _State = ProfileState.Disconnected;
461
462         internal ProfileStateEventArgs(ProfileState state)
463         {
464             _State = state;
465         }
466
467         /// <summary>
468         /// The profile state.
469         /// </summary>
470         /// <since_tizen> 3 </since_tizen>
471         /// <value>State type of the connection profile.</value>
472         public ProfileState State
473         {
474             get
475             {
476                 return _State;
477             }
478         }
479     }
480 }