Fixed issues, Modified spec to use xbuild, doxygen comments
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.IoTConnectivity / Tizen.Network.IoTConnectivity / RemoteResource.cs
1 /// Copyright 2016 by Samsung Electronics, Inc.,
2 ///
3 /// This software is the confidential and proprietary information
4 /// of Samsung Electronics, Inc. ("Confidential Information"). You
5 /// shall not disclose such Confidential Information and shall use
6 /// it only in accordance with the terms of the license agreement
7 /// you entered into with Samsung.
8
9 using System;
10 using System.Collections.Generic;
11 using System.Net;
12 using System.Runtime.InteropServices;
13 using System.Threading.Tasks;
14
15 namespace Tizen.Network.IoTConnectivity
16 {
17     /// <summary>
18     /// This class represents a remote resource.
19     /// </summary>
20     public class RemoteResource : IDisposable
21     {
22         internal const int TimeOutMax = 3600;
23         internal IntPtr _remoteResourceHandle = IntPtr.Zero;
24
25         private bool _disposed = false;
26         private bool _cacheEnabled = false;
27         private ResourceOptions _options;
28
29         private int _responseCallbackId = 1;
30         private static Dictionary<IntPtr, Interop.IoTConnectivity.Client.RemoteResource.ResponseCallback> _responseCallbacksMap = new Dictionary<IntPtr, Interop.IoTConnectivity.Client.RemoteResource.ResponseCallback>();
31
32         private Interop.IoTConnectivity.Client.RemoteResource.CachedRepresentationChangedCallback _cacheUpdatedCallback;
33         private Interop.IoTConnectivity.Client.RemoteResource.StateChangedCallback _stateChangedCallback;
34         private Interop.IoTConnectivity.Client.RemoteResource.ObserveCallback _observeCallback;
35
36         private EventHandler<StateChangedEventArgs> _stateChangedEventHandler;
37
38         /// <summary>
39         /// Constructor
40         /// </summary>
41         public RemoteResource(string hostAddress, string uriPath, ResourcePolicy policy, ResourceTypes resourceTypes, ResourceInterfaces resourceInterfaces)
42         {
43             if (hostAddress == null || uriPath == null || resourceTypes == null || resourceInterfaces == null)
44             {
45                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Invalid parameters");
46                 throw new ArgumentException("Invalid parameter");
47             }
48
49             HostAddress = hostAddress;
50             UriPath = uriPath;
51             Policy = policy;
52             Types = new List<string>(resourceTypes);
53             Interfaces = new List<string>(resourceInterfaces);
54             DeviceId = null;
55
56             CreateRemoteResource(resourceTypes._resourceTypeHandle, resourceInterfaces.ResourceInterfacesHandle);
57         }
58
59         internal RemoteResource(IntPtr handleToClone)
60         {
61             int ret = Interop.IoTConnectivity.Client.RemoteResource.Clone(handleToClone, out _remoteResourceHandle);
62             if (ret != (int)IoTConnectivityError.None)
63             {
64                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to clone");
65                 throw IoTConnectivityErrorFactory.GetException(ret);
66             }
67             SetRemoteResource();
68         }
69
70         ~RemoteResource()
71         {
72             Dispose(false);
73         }
74
75         /// <summary>
76         /// Event that is called to cache resource attribute's
77         /// </summary>
78         public event EventHandler<CacheUpdatedEventArgs> CacheUpdated;
79
80         /// <summary>
81         /// Observe event on the resource
82         /// </summary>
83         public event EventHandler<ObserverNotifiedEventArgs> ObserverNotified;
84
85         /// <summary>
86         /// Event that is called when remote resource's state are changed
87         /// </summary>
88         public event EventHandler<StateChangedEventArgs> StateChanged
89         {
90             add
91             {
92                 if (_stateChangedEventHandler == null)
93                 {
94                     RegisterStateChangedEvent();
95                 }
96                 _stateChangedEventHandler += value;
97             }
98             remove
99             {
100                 _stateChangedEventHandler -= value;
101                 if (_stateChangedEventHandler == null)
102                 {
103                     UnregisterStateChangedEvent();
104                 }
105             }
106         }
107
108         /// <summary>
109         /// The host address of the resource
110         /// </summary>
111         public string HostAddress { get; private set; }
112
113         /// <summary>
114         /// The URI path of the resource
115         /// </summary>
116         public string UriPath { get; private set; }
117
118         /// <summary>
119         /// The resource types of the remote resource
120         /// </summary>
121         public IEnumerable<string> Types { get; private set; }
122
123         /// <summary>
124         /// The interfaces of the resource
125         /// </summary>
126         public IEnumerable<string> Interfaces { get; private set; }
127
128         /// <summary>
129         /// The policy of the resource
130         /// </summary>
131         public ResourcePolicy Policy { get; private set; }
132
133         /// <summary>
134         /// The device name of the remote resource
135         /// </summary>
136         public string DeviceName { get; private set; }
137
138         /// <summary>
139         /// The header options of the resource
140         /// </summary>
141         public ResourceOptions Options
142         {
143             get
144             {
145                 return _options;
146             }
147             set
148             {
149                 _options = value;
150                 if (value != null)
151                 {
152                     int ret = Interop.IoTConnectivity.Client.RemoteResource.SetOptions(_remoteResourceHandle, value._resourceOptionsHandle);
153                     if (ret != (int)IoTConnectivityError.None)
154                     {
155                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set options");
156                         throw IoTConnectivityErrorFactory.GetException(ret);
157                     }
158                 }
159             }
160         }
161
162         /// <summary>
163         /// Cache enabled property
164         /// </summary>
165         public bool CacheEnabled
166         {
167             get
168             {
169                 return _cacheEnabled;
170             }
171             set
172             {
173                 if (_cacheEnabled != value)
174                 {
175                     _cacheEnabled = value;
176                     HandleCachePolicyChanged();
177                 }
178             }
179         }
180
181         /// <summary>
182         /// Time interval of monitoring and caching API
183         /// </summary>
184         public int TimeInterval
185         {
186             get
187             {
188                 int interval;
189                 int ret = Interop.IoTConnectivity.Client.RemoteResource.GetTimeInterval(out interval);
190                 if (ret != (int)IoTConnectivityError.None)
191                 {
192                     Log.Warn(IoTConnectivityErrorFactory.LogTag, "Failed to get time interval");
193                     return 0;
194                 }
195                 return interval;
196             }
197             set
198             {
199                 int ret = (int)IoTConnectivityError.InvalidParameter;
200                 if (value < TimeOutMax && value > 0)
201                 {
202                     ret = Interop.IoTConnectivity.Client.RemoteResource.SetTimeInterval(value);
203                 }
204                 if (ret != (int)IoTConnectivityError.None)
205                 {
206                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set time interval");
207                     throw IoTConnectivityErrorFactory.GetException(ret);
208                 }
209             }
210         }
211
212         /// <summary>
213         /// The device id of the resource
214         /// </summary>
215         public string DeviceId { get; private set; }
216
217         /// <summary>
218         /// Gets cached representation of the remote resource
219         /// </summary>
220         public Representation CachedRepresentation()
221         {
222             IntPtr handle;
223             int ret = Interop.IoTConnectivity.Client.RemoteResource.GetCachedRepresentation(_remoteResourceHandle, out handle);
224             if (ret != (int)IoTConnectivityError.None)
225             {
226                 Log.Warn(IoTConnectivityErrorFactory.LogTag, "Failed to get CachedRepresentation");
227                 return null;
228             }
229
230             Representation representation = new Representation(handle);
231             return representation;
232         }
233
234         /// <summary>
235         /// Registers the observe callback on the resource
236         /// </summary>
237         /// <param name="policy">The type to specify how client wants to observe</param>
238         /// <param name="query">The ResourceQuery to send to server</param>
239         public void StartObserving(ObservePolicy policy, ResourceQuery query = null)
240         {
241             _observeCallback = (IntPtr resource, int err, int sequenceNumber, IntPtr response, IntPtr userData) =>
242             {
243                 int result;
244                 IntPtr representationHandle;
245                 int ret = Interop.IoTConnectivity.Server.Response.GetResult(response, out result);
246                 if (ret != (int)IoTConnectivityError.None)
247                 {
248                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get result");
249                     return;
250                 }
251
252                 ret = Interop.IoTConnectivity.Server.Response.GetRepresentation(response, out representationHandle);
253                 if (ret != (int)IoTConnectivityError.None)
254                 {
255                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get representation");
256                     return;
257                 }
258
259                 Representation repr = null;
260                 try
261                 {
262                     repr = new Representation(representationHandle);
263                 }
264                 catch (Exception exp)
265                 {
266                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new representation: " + exp.Message);
267                     return;
268                 }
269
270                 ObserverNotifiedEventArgs e = new ObserverNotifiedEventArgs()
271                 {
272                     Representation = repr,
273                     Result = (ResponseCode)result
274                 };
275                 ObserverNotified?.Invoke(null, e);
276             };
277
278             IntPtr queryHandle = IntPtr.Zero;
279             if (query != null)
280             {
281                 queryHandle = query._resourceQueryHandle;
282             }
283
284             int errCode = Interop.IoTConnectivity.Client.RemoteResource.RegisterObserve(_remoteResourceHandle, (int)policy, queryHandle, _observeCallback, IntPtr.Zero);
285             if (errCode != (int)IoTConnectivityError.None)
286             {
287                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to register observe callbacks");
288                 throw IoTConnectivityErrorFactory.GetException(errCode);
289             }
290         }
291
292         /// <summary>
293         /// Deregisters the observe callback on the resource
294         /// </summary>
295         public void StopObserving()
296         {
297             int ret = Interop.IoTConnectivity.Client.RemoteResource.DeregisterObserve(_remoteResourceHandle);
298             if (ret != (int)IoTConnectivityError.None)
299             {
300                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to deregister observe callbacks");
301                 throw IoTConnectivityErrorFactory.GetException(ret);
302             }
303         }
304
305         /// <summary>
306         /// Gets the attributes of a resource
307         /// </summary>
308         /// <param name="query">The ResourceQuery to send to server</param>
309         /// <returns></returns>
310         public async Task<RemoteResponse> GetAsync(ResourceQuery query = null)
311         {
312             TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
313
314             IntPtr id = IntPtr.Zero;
315             lock (_responseCallbacksMap)
316             {
317                 id = (IntPtr)_responseCallbackId++;
318             }
319             _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
320             {
321                 IntPtr responseCallbackId = userData;
322                 lock(_responseCallbacksMap)
323                 {
324                     _responseCallbacksMap.Remove(responseCallbackId);
325                 }
326
327                 if (responseHandle != IntPtr.Zero)
328                 {
329                     try
330                     {
331                         tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
332                     }
333                     catch(Exception exp)
334                     {
335                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
336                         tcsRemoteResponse.TrySetException(exp);
337                     }
338                 }
339                 else
340                 {
341                     tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
342                 }
343             };
344
345             IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
346             int errCode = Interop.IoTConnectivity.Client.RemoteResource.Get(_remoteResourceHandle, queryHandle, _responseCallbacksMap[id], id);
347             if (errCode != (int)IoTConnectivityError.None)
348             {
349                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource attributes");
350                 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
351             }
352             return await tcsRemoteResponse.Task;
353         }
354
355         /// <summary>
356         /// Puts the representation of a resource, asynchronously.
357         /// </summary>
358         /// <param name="representation">Resource representation</param>
359         /// <param name="query">The ResourceQuery to send to server</param>
360         /// <returns></returns>
361         public async Task<RemoteResponse> PutAsync(Representation representation, ResourceQuery query = null)
362         {
363             TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
364
365             IntPtr id = IntPtr.Zero;
366             lock (_responseCallbacksMap)
367             {
368                 id = (IntPtr)_responseCallbackId++;
369             }
370             _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
371             {
372                 IntPtr responseCallbackId = userData;
373                 lock (_responseCallbacksMap)
374                 {
375                     _responseCallbacksMap.Remove(responseCallbackId);
376                 }
377                 if (err == (int)(IoTConnectivityError.Iotivity))
378                 {
379                     RemoteResponse response = new RemoteResponse();
380                     response.Result = ResponseCode.Forbidden;
381                     response.Representation = null;
382                     tcsRemoteResponse.TrySetResult(response);
383                 }
384                 else if (responseHandle != IntPtr.Zero)
385                 {
386                     try
387                     {
388                         tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
389                     }
390                     catch (Exception exp)
391                     {
392                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
393                         tcsRemoteResponse.TrySetException(exp);
394                     }
395                 }
396                 else
397                 {
398                     tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
399                 }
400             };
401             IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
402             int errCode = Interop.IoTConnectivity.Client.RemoteResource.Put(_remoteResourceHandle, representation._representationHandle, queryHandle, _responseCallbacksMap[id], id);
403             if (errCode != (int)IoTConnectivityError.None)
404             {
405                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to put resource representation");
406                 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
407             }
408             return await tcsRemoteResponse.Task;
409         }
410
411         /// <summary>
412         /// Post request on a resource
413         /// </summary>
414         /// <param name="representation">Resource representation</param>
415         /// <param name="query">The ResourceQuery to send to server</param>
416         /// <returns></returns>
417         public async Task<RemoteResponse> PostAsync(Representation representation, ResourceQuery query = null)
418         {
419             TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
420
421             IntPtr id = IntPtr.Zero;
422             lock (_responseCallbacksMap)
423             {
424                 id = (IntPtr)_responseCallbackId++;
425             }
426             _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
427             {
428                 IntPtr responseCallbackId = userData;
429                 lock (_responseCallbacksMap)
430                 {
431                     _responseCallbacksMap.Remove(responseCallbackId);
432                 }
433
434                 if (responseHandle != IntPtr.Zero)
435                 {
436                     try
437                     {
438                         tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
439                     }
440                     catch (Exception exp)
441                     {
442                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
443                         tcsRemoteResponse.TrySetException(exp);
444                     }
445                 }
446                 else
447                 {
448                     tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
449                 }
450             };
451
452             IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
453             int errCode = Interop.IoTConnectivity.Client.RemoteResource.Post(_remoteResourceHandle, representation._representationHandle, queryHandle, _responseCallbacksMap[id], id);
454             if (errCode != (int)IoTConnectivityError.None)
455             {
456                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to post request");
457                 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
458             }
459             return await tcsRemoteResponse.Task;
460         }
461
462         /// <summary>
463         /// Delete the resource
464         /// </summary>
465         /// <returns></returns>
466         public async Task<RemoteResponse> DeleteAsync()
467         {
468             TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
469
470             IntPtr id = IntPtr.Zero;
471             lock (_responseCallbacksMap)
472             {
473                 id = (IntPtr)_responseCallbackId++;
474             }
475             _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
476             {
477                 IntPtr responseCallbackId = userData;
478                 lock (_responseCallbacksMap)
479                 {
480                     _responseCallbacksMap.Remove(responseCallbackId);
481                 }
482                 if (err == (int)(IoTConnectivityError.Iotivity))
483                 {
484                     RemoteResponse response = new RemoteResponse();
485                     response.Result = ResponseCode.Forbidden;
486                     response.Representation = null;
487                     tcsRemoteResponse.TrySetResult(response);
488                 }
489                 else if (responseHandle != IntPtr.Zero)
490                 {
491                     try
492                     {
493                         tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
494                     }
495                     catch (Exception exp)
496                     {
497                         Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
498                         tcsRemoteResponse.TrySetException(exp);
499                     }
500                 }
501                 else
502                 {
503                     tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
504                 }
505             };
506
507             int errCode = Interop.IoTConnectivity.Client.RemoteResource.Delete(_remoteResourceHandle, _responseCallbacksMap[id], id);
508             if (errCode != (int)IoTConnectivityError.None)
509             {
510                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to delete");
511                 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
512             }
513             return await tcsRemoteResponse.Task;
514         }
515
516         public void Dispose()
517         {
518             Dispose(true);
519             GC.SuppressFinalize(this);
520         }
521
522         internal static Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType GetConnectivityType(string hostAddress)
523         {
524             Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.None;
525
526             if (hostAddress == IoTConnectivityClientManager.MulticastAddress)
527             {
528                 type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv4;
529             }
530             else
531             {
532                 IPAddress address;
533                 string hostName = hostAddress;
534                 if (hostAddress.Contains(":"))
535                 {
536                     string[] hostParts = hostAddress.Split(':');
537                     if (hostParts.Length == 2)
538                     {
539                         hostName = hostParts[0];
540                     }
541                 }
542                 if (IPAddress.TryParse(hostName, out address))
543                 {
544                     switch (address.AddressFamily)
545                     {
546                         case System.Net.Sockets.AddressFamily.InterNetwork:
547                             type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv4;
548                             break;
549                         case System.Net.Sockets.AddressFamily.InterNetworkV6:
550                             type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv6;
551                             break;
552                         default:
553                             Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to parse for Ipv4 or Ipv6");
554                             break;
555                     }
556                 }
557             }
558             return type;
559         }
560
561         protected virtual void Dispose(bool disposing)
562         {
563             if (_disposed)
564                 return;
565
566             if (disposing)
567             {
568                 // Free managed objects
569             }
570
571             Interop.IoTConnectivity.Client.RemoteResource.Destroy(_remoteResourceHandle);
572             _disposed = true;
573         }
574
575         private void HandleCachePolicyChanged()
576         {
577             if (_cacheEnabled)
578             {
579                 _cacheUpdatedCallback = (IntPtr resource, IntPtr representation, IntPtr userData) =>
580                 {
581                     if (CacheEnabled)
582                     {
583                         Representation repr = null;
584                         try
585                         {
586                             repr = new Representation(representation);
587                         }
588                         catch (Exception exp)
589                         {
590                             Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
591                             return;
592                         }
593
594                         CacheUpdatedEventArgs e = new CacheUpdatedEventArgs()
595                         {
596                             Representation = repr
597                         };
598                         CacheUpdated?.Invoke(null, e);
599                     }
600                 };
601
602                 int ret = Interop.IoTConnectivity.Client.RemoteResource.StartCaching(_remoteResourceHandle, _cacheUpdatedCallback, IntPtr.Zero);
603                 if (ret != (int)IoTConnectivityError.None)
604                 {
605                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add cache updated event handler");
606                     throw IoTConnectivityErrorFactory.GetException(ret);
607                 }
608             }
609             else
610             {
611                 int ret = Interop.IoTConnectivity.Client.RemoteResource.StopCaching(_remoteResourceHandle);
612                 if (ret != (int)IoTConnectivityError.None)
613                 {
614                     Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove cache updated event handler");
615                     throw IoTConnectivityErrorFactory.GetException(ret);
616                 }
617             }
618         }
619
620         private void RegisterStateChangedEvent()
621         {
622             _stateChangedCallback = (IntPtr resource, int state, IntPtr userData) =>
623             {
624                 StateChangedEventArgs e = new StateChangedEventArgs()
625                 {
626                     State = (ResourceState)state
627                 };
628                 _stateChangedEventHandler?.Invoke(null, e);
629             };
630
631             int ret = Interop.IoTConnectivity.Client.RemoteResource.StartMonitoring(_remoteResourceHandle, _stateChangedCallback, IntPtr.Zero);
632             if (ret != (int)IoTConnectivityError.None)
633             {
634                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add state changed event handler");
635                 throw IoTConnectivityErrorFactory.GetException(ret);
636             }
637         }
638
639         private void UnregisterStateChangedEvent()
640         {
641             int ret = Interop.IoTConnectivity.Client.RemoteResource.StopMonitoring(_remoteResourceHandle);
642             if (ret != (int)IoTConnectivityError.None)
643             {
644                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove state changed event handler");
645                 throw IoTConnectivityErrorFactory.GetException(ret);
646             }
647         }
648
649         private void CreateRemoteResource(IntPtr resourceTypeHandle, IntPtr resourceInterfaceHandle)
650         {
651             Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType connectivityType = GetConnectivityType(HostAddress);
652             if (connectivityType == Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.None)
653             {
654                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Unable to parse host address");
655                 throw new ArgumentException("Unable to parse host address");
656             }
657             int ret = Interop.IoTConnectivity.Client.RemoteResource.Create(HostAddress, (int)connectivityType, UriPath, (int)Policy, resourceTypeHandle, resourceInterfaceHandle, out _remoteResourceHandle);
658             if (ret != (int)IoTConnectivityError.None)
659             {
660                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get remote resource");
661                 throw IoTConnectivityErrorFactory.GetException(ret);
662             }
663
664             /*IntPtr deviceName;
665             ret = Interop.IoTConnectivity.Client.RemoteResource.GetDeviceName(_remoteResourceHandle, out deviceName);
666             if (ret != (int)IoTConnectivityError.None)
667             {
668                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get device name of remote resource");
669                 throw IoTConnectivityErrorFactory.GetException(ret);
670             }
671             DeviceName = Marshal.PtrToStringAuto(deviceName);*/
672         }
673
674         private void SetRemoteResource()
675         {
676             IntPtr hostAddressPtr, uriPathPtr;
677             int ret = Interop.IoTConnectivity.Client.RemoteResource.GetHostAddress(_remoteResourceHandle, out hostAddressPtr);
678             if (ret != (int)IoTConnectivityError.None)
679             {
680                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get host address");
681                 throw IoTConnectivityErrorFactory.GetException(ret);
682             }
683
684             ret = Interop.IoTConnectivity.Client.RemoteResource.GetUriPath(_remoteResourceHandle, out uriPathPtr);
685             if (ret != (int)IoTConnectivityError.None)
686             {
687                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get uri path");
688                 throw IoTConnectivityErrorFactory.GetException(ret);
689             }
690
691             int policy = (int)ResourcePolicy.NoProperty;
692             ret = Interop.IoTConnectivity.Client.RemoteResource.GetPolicies(_remoteResourceHandle, out policy);
693             if (ret != (int)IoTConnectivityError.None)
694             {
695                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get uri path");
696                 throw IoTConnectivityErrorFactory.GetException(ret);
697             }
698
699             IntPtr typesHandle, interfacesHandle;
700             ret = Interop.IoTConnectivity.Client.RemoteResource.GetTypes(_remoteResourceHandle, out typesHandle);
701             if (ret != (int)IoTConnectivityError.None)
702             {
703                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource types");
704                 throw IoTConnectivityErrorFactory.GetException(ret);
705             }
706
707             ret = Interop.IoTConnectivity.Client.RemoteResource.GetInterfaces(_remoteResourceHandle, out interfacesHandle);
708             if (ret != (int)IoTConnectivityError.None)
709             {
710                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource interfaces");
711                 throw IoTConnectivityErrorFactory.GetException(ret);
712             }
713
714             IntPtr deviceIdPtr;
715             ret = Interop.IoTConnectivity.Client.RemoteResource.GetDeviceId(_remoteResourceHandle, out deviceIdPtr);
716             if (ret != (int)IoTConnectivityError.None)
717             {
718                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get device id");
719                 throw IoTConnectivityErrorFactory.GetException(ret);
720             }
721             IntPtr deviceName;
722             ret = Interop.IoTConnectivity.Client.RemoteResource.GetDeviceName(_remoteResourceHandle, out deviceName);
723             if (ret != (int)IoTConnectivityError.None)
724             {
725                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get device name of remote resource");
726                 throw IoTConnectivityErrorFactory.GetException(ret);
727             }
728             DeviceName = Marshal.PtrToStringAuto(deviceName);
729             DeviceId = Marshal.PtrToStringAuto(deviceIdPtr);
730             HostAddress = Marshal.PtrToStringAuto(hostAddressPtr);
731             UriPath = Marshal.PtrToStringAuto(uriPathPtr);
732             Types = new ResourceTypes(typesHandle);
733             Interfaces = new ResourceInterfaces(interfacesHandle);
734             Policy = (ResourcePolicy)policy;
735         }
736
737         private RemoteResponse GetRemoteResponse(IntPtr response)
738         {
739             int result;
740             IntPtr representationHandle, optionsHandle;
741             int ret = Interop.IoTConnectivity.Server.Response.GetResult(response, out result);
742             if (ret != (int)IoTConnectivityError.None)
743             {
744                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get result");
745                 throw IoTConnectivityErrorFactory.GetException(ret);
746             }
747
748             ret = Interop.IoTConnectivity.Server.Response.GetRepresentation(response, out representationHandle);
749             if (ret != (int)IoTConnectivityError.None)
750             {
751                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get representation");
752                 throw IoTConnectivityErrorFactory.GetException(ret);
753             }
754
755             ret = Interop.IoTConnectivity.Server.Response.GetOptions(response, out optionsHandle);
756             if (ret != (int)IoTConnectivityError.None)
757             {
758                 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get options");
759                 throw IoTConnectivityErrorFactory.GetException(ret);
760             }
761             return new RemoteResponse()
762             {
763                 Result = (ResponseCode)result,
764                 Representation = new Representation(representationHandle),
765                 Options = (optionsHandle == IntPtr.Zero)? null : new ResourceOptions(optionsHandle)
766             };
767         }
768     }
769 }