52fdfa8610bdf79b178920fc8f67c16340065598
[platform/upstream/iotivity.git] / resource / src / OCResource.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "OCResource.h"
22 #include "OCUtilities.h"
23
24 #include <boost/lexical_cast.hpp>
25 #include <sstream>
26
27 namespace OC {
28
29 static const char COAP[] = "coap://";
30 static const char COAPS[] = "coaps://";
31 static const char COAP_TCP[] = "coap+tcp://";
32
33 using OC::nil_guard;
34 using OC::result_guard;
35 using OC::checked_guard;
36
37 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
38                         const OCDevAddr& devAddr, const std::string& uri,
39                         const std::string& serverId, bool observable,
40                         const std::vector<std::string>& resourceTypes,
41                         const std::vector<std::string>& interfaces)
42  :  m_clientWrapper(clientWrapper), m_uri(uri),
43     m_resourceId(serverId, m_uri), m_devAddr(devAddr),
44     m_isObservable(observable), m_isCollection(false),
45     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
46     m_observeHandle(nullptr)
47 {
48     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
49                         != m_interfaces.end();
50
51     if (m_uri.empty() ||
52         resourceTypes.empty() ||
53         interfaces.empty()||
54         m_clientWrapper.expired())
55     {
56         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
57                 interfaces.empty(), m_clientWrapper.expired(), false, false);
58     }
59 }
60
61 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
62                         const std::string& host, const std::string& uri,
63                         const std::string& serverId,
64                         OCConnectivityType connectivityType, bool observable,
65                         const std::vector<std::string>& resourceTypes,
66                         const std::vector<std::string>& interfaces)
67  :  m_clientWrapper(clientWrapper), m_uri(uri),
68     m_resourceId(serverId, m_uri),
69     m_devAddr{ OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS, 0, {0}, 0
70 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
71     , {0}
72 #endif
73     },
74     m_isObservable(observable), m_isCollection(false),
75     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
76     m_observeHandle(nullptr)
77 {
78     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
79                         != m_interfaces.end();
80
81     if (m_uri.empty() ||
82         resourceTypes.empty() ||
83         interfaces.empty()||
84         m_clientWrapper.expired())
85     {
86         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
87                 interfaces.empty(), m_clientWrapper.expired(), false, false);
88     }
89
90     if (uri.length() == 1 && uri[0] == '/')
91     {
92         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
93                 interfaces.empty(), m_clientWrapper.expired(), false, false);
94     }
95
96     if (uri[0] != '/')
97     {
98         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
99                 interfaces.empty(), m_clientWrapper.expired(), false, false);
100     }
101
102     // construct the devAddr from the pieces we have
103     m_devAddr.adapter = static_cast<OCTransportAdapter>(connectivityType >> CT_ADAPTER_SHIFT);
104     m_devAddr.flags = static_cast<OCTransportFlags>(connectivityType & CT_MASK_FLAGS);
105
106     this->setHost(host);
107 }
108
109 OCResource::~OCResource()
110 {
111 }
112
113 void OCResource::setHost(const std::string& host)
114 {
115     size_t prefix_len;
116
117     if(host.compare(0, sizeof(COAP) - 1, COAP) == 0)
118     {
119         prefix_len = sizeof(COAP) - 1;
120     }
121     else if(host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
122     {
123         prefix_len = sizeof(COAPS) - 1;
124         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_SECURE);
125     }
126     else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
127     {
128         prefix_len = sizeof(COAP_TCP) - 1;
129         m_devAddr.adapter = static_cast<OCTransportAdapter>(m_devAddr.adapter & OC_ADAPTER_TCP);
130     }
131     else
132     {
133         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
134             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
135     }
136
137     // removed 'coap://' or 'coaps://' or 'coap+tcp://'
138     std::string host_token = host.substr(prefix_len);
139
140     if (host_token[0] == '[') // ipv6 address
141     {
142         m_devAddr.flags = static_cast< OCTransportFlags >(m_devAddr.flags & OC_IP_USE_V6);
143
144         size_t found = host_token.find(']');
145
146         if (found == std::string::npos || found == 0)
147         {
148             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
149                                         m_interfaces.empty(), m_clientWrapper.expired(), false,
150                                         false);
151         }
152         // extract the ipv6 address
153         std::string ip6Addr = host_token.substr(1, found - 1);
154
155         size_t addrLength = ip6Addr.length();
156
157         if (MAX_ADDR_STR_SIZE <= addrLength)
158         {
159             throw std::length_error("host address is too long.");
160         }
161
162         // address validity check
163         size_t colon = ip6Addr.find(':');
164
165         if (std::string::npos == colon)
166         {
167             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
168                                         m_interfaces.empty(), m_clientWrapper.expired(), false,
169                                         false);
170         }
171
172         size_t colonCnt = 1;
173         int omittedColon = -2;
174
175         while (std::string::npos != colon)
176         {
177             size_t nextColon = ip6Addr.find(':', colon + 1);
178
179             if (nextColon == colon + 1)
180             {
181                 if (0 < omittedColon)
182                 {
183                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
184                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
185                                                 false);
186                 }
187                 omittedColon = colon;
188             }
189
190             colon = nextColon;
191
192             if (7 < colonCnt++)
193             {
194                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
195                                             m_interfaces.empty(), m_clientWrapper.expired(), false,
196                                             false);
197             }
198         }
199
200         if (7 >= colonCnt && 0 > omittedColon)
201         {
202             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
203                                         m_interfaces.empty(), m_clientWrapper.expired(), false,
204                                         false);
205         }
206
207         size_t startPoint = 0;
208
209         if (0 == omittedColon)
210         {
211             startPoint = 2;
212         }
213
214         while (1)
215         {
216             std::string block;
217             colon = ip6Addr.find(':', startPoint);
218
219             if (std::string::npos != colon)
220             {
221                 block = ip6Addr.substr(startPoint, colon - startPoint);
222
223                 if (4 < block.length() ||
224                        std::string::npos != block.find_first_not_of("0123456789ABCDEFabcdef") ||
225                        0 == block.length())
226                 {
227                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
228                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
229                                                 false);
230                 }
231
232                 startPoint = colon + 1;
233             }
234             else
235             {
236                 block = ip6Addr.substr(startPoint);
237
238                 if (4 < block.length() ||
239                         std::string::npos != block.find_first_not_of("0123456789ABCDEFabcdef") ||
240                         0 == block.length())
241                 {
242                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
243                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
244                                                 false);
245                 }
246
247                 break;
248             }
249
250             if ((int)colon == omittedColon)
251             {
252                 if (colon == addrLength - 2)
253                 {
254                     break;
255                 }
256                 startPoint = colon + 2;
257                 continue;
258             }
259
260         }
261         // end of address validity check
262
263         ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
264         m_devAddr.addr[ip6Addr.length()] = '\0';
265         //skip ']' and ':' characters in host string
266         host_token = host_token.substr(found + 2);
267
268         int port = std::stoi(host_token);
269
270         if (0 > port || UINT16_MAX < port)
271         {
272             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
273                                         m_interfaces.empty(), m_clientWrapper.expired(), false,
274                                         false);
275         }
276
277         m_devAddr.port = static_cast< uint16_t >(port);
278     }
279     else if (host_token[0] == ':')
280     {
281         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
282                                     m_interfaces.empty(), m_clientWrapper.expired(), false,
283                                     false);
284     }
285     else
286     {
287         size_t dot = host_token.find('.');
288         if (dot == std::string::npos) // MAC address
289         {
290             std::string macAddr = host_token;
291
292             // address validity check
293             if (MAC_ADDR_STR_SIZE != macAddr.length())
294             {
295                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
296                                             m_interfaces.empty(), m_clientWrapper.expired(), false,
297                                             false);
298             }
299
300             for (size_t blockCnt = 0; blockCnt < 6; blockCnt++)
301             {
302                 std::string block = macAddr.substr(blockCnt * 3, 2);
303
304                 if (std::string::npos != block.find_first_not_of("0123456789ABCDEFabcdef"))
305                 {
306                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
307                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
308                                                 false);
309                 }
310
311                 if (5 > blockCnt)
312                 {
313                     char delimiter = macAddr[blockCnt * 3 + 2];
314
315                     if (':' != delimiter || '-' != delimiter)
316                     {
317                         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
318                                                     m_interfaces.empty(), m_clientWrapper.expired(),
319                                                     false, false);
320                     }
321                 }
322             }
323             // end of address validity check
324
325             macAddr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
326             m_devAddr.addr[macAddr.length()] = '\0';
327         }
328         else // ipv4 address
329         {
330             size_t colon = host_token.find(':');
331
332             if (colon == std::string::npos)
333             {
334                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
335                                             m_interfaces.empty(), m_clientWrapper.expired(), false,
336                                             false);
337             }
338
339             std::string ip4Addr = host_token.substr(0, colon);
340             size_t addrLength = ip4Addr.length();
341
342             if (MAX_ADDR_STR_SIZE <= addrLength)
343             {
344                 throw std::length_error("host address is too long.");
345             }
346
347             // address validity check
348             size_t startPoint = 0;
349
350             for (size_t blockCnt = 1; blockCnt <= 4; blockCnt++)
351             {
352                 size_t dot = ip4Addr.find('.', startPoint);
353                 std::string addrBlock;
354
355                 if (4 > blockCnt)
356                 {
357                     if (std::string::npos == dot || dot <= startPoint)
358                     {
359                         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
360                                                     m_interfaces.empty(), m_clientWrapper.expired(),
361                                                     false, false);
362                     }
363                     addrBlock = ip4Addr.substr(startPoint, dot - startPoint);
364                 }
365                 else
366                 {
367                     if (std::string::npos != dot)
368                     {
369                         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
370                                                     m_interfaces.empty(), m_clientWrapper.expired(),
371                                                     false, false);
372                     }
373                     addrBlock = ip4Addr.substr(startPoint, colon - startPoint);
374                 }
375
376                 int i_addrBlock = std::stoi(addrBlock);
377
378                 if (std::string::npos != addrBlock.find_first_not_of("0123456789") ||
379                     0 > i_addrBlock || 255 < i_addrBlock)
380                 {
381                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
382                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
383                                                 false);
384                 }
385                 startPoint = dot + 1;
386
387                 if (addrLength <= startPoint)
388                 {
389                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
390                                                 m_interfaces.empty(), m_clientWrapper.expired(), false,
391                                                 false);
392                 }
393             }
394             // end of address validity check
395
396             ip4Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
397             m_devAddr.addr[ip4Addr.length()] = '\0';
398             //skip ':' character in host string
399             host_token = host_token.substr(colon + 1);
400
401             int port = std::stoi(host_token);
402
403             if (0 > port || UINT16_MAX < port)
404             {
405                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
406                                             m_interfaces.empty(), m_clientWrapper.expired(), false,
407                                             false);
408             }
409
410             m_devAddr.port = static_cast< uint16_t >(port);
411         }
412     }
413 }
414
415 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
416                               GetCallback attributeHandler, QualityOfService QoS)
417 {
418     return checked_guard(m_clientWrapper.lock(),
419                             &IClientWrapper::GetResourceRepresentation,
420                             m_devAddr, m_uri,
421                             queryParametersMap, m_headerOptions,
422                             attributeHandler, QoS);
423 }
424
425 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
426                               GetCallback attributeHandler)
427 {
428     QualityOfService defaultQos = OC::QualityOfService::NaQos;
429     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
430     return result_guard(get(queryParametersMap, attributeHandler, defaultQos));
431 }
432
433 OCStackResult OCResource::get(const std::string& resourceType,
434                      const std::string& resourceInterface, const QueryParamsMap& queryParametersMap,
435                      GetCallback attributeHandler)
436 {
437     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
438     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
439
440     return result_guard(get(resourceType, resourceInterface, queryParametersMap, attributeHandler, defaultQoS));
441 }
442
443 OCStackResult OCResource::get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
444         QualityOfService QoS)
445 {
446     QueryParamsMap mapCpy(queryParametersMap);
447
448     if(!resourceType.empty())
449     {
450         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
451     }
452
453     if(!resourceInterface.empty())
454     {
455         mapCpy[OC::Key::INTERFACESKEY]= resourceInterface;
456     }
457
458     return result_guard(get(mapCpy, attributeHandler, QoS));
459 }
460
461 OCStackResult OCResource::put(const OCRepresentation& rep,
462                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler,
463                               QualityOfService QoS)
464 {
465     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation,
466                          m_devAddr, m_uri, rep, queryParametersMap,
467                          m_headerOptions, attributeHandler, QoS);
468 }
469
470 OCStackResult OCResource::put(const OCRepresentation& rep,
471                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
472 {
473     QualityOfService defaultQos = OC::QualityOfService::NaQos;
474     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
475     return result_guard(put(rep, queryParametersMap, attributeHandler, defaultQos));
476 }
477
478 OCStackResult OCResource::put(const std::string& resourceType,
479                               const std::string& resourceInterface, const OCRepresentation& rep,
480                               const QueryParamsMap& queryParametersMap,
481                               PutCallback attributeHandler)
482 {
483     QualityOfService defaultQos = OC::QualityOfService::NaQos;
484     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
485
486     return result_guard(put(resourceType, resourceInterface, rep, queryParametersMap,
487             attributeHandler, defaultQos));
488 }
489
490 OCStackResult OCResource::put(const std::string& resourceType,
491                               const std::string& resourceInterface, const OCRepresentation& rep,
492                               const QueryParamsMap& queryParametersMap,
493                               PutCallback attributeHandler,
494                               QualityOfService QoS)
495 {
496     QueryParamsMap mapCpy(queryParametersMap);
497
498     if(!resourceType.empty())
499     {
500         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
501     }
502
503     if(!resourceInterface.empty())
504     {
505         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
506     }
507
508     return result_guard(put(rep, mapCpy, attributeHandler, QoS));
509 }
510
511 OCStackResult OCResource::post(const OCRepresentation& rep,
512                                const QueryParamsMap& queryParametersMap, PostCallback attributeHandler,
513                                QualityOfService QoS)
514 {
515     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
516                          m_devAddr, m_uri, rep, queryParametersMap,
517                          m_headerOptions, attributeHandler, QoS);
518 }
519
520 OCStackResult OCResource::post(const OCRepresentation& rep,
521                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
522 {
523     QualityOfService defaultQos = OC::QualityOfService::NaQos;
524     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
525     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
526 }
527
528 OCStackResult OCResource::post(const std::string& resourceType,
529                                const std::string& resourceInterface, const OCRepresentation& rep,
530                                const QueryParamsMap& queryParametersMap,
531                                PostCallback attributeHandler)
532 {
533     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
534     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
535
536     return result_guard(post(resourceType, resourceInterface, rep, queryParametersMap, attributeHandler,
537             defaultQoS));
538 }
539
540 OCStackResult OCResource::post(const std::string& resourceType,
541                                const std::string& resourceInterface, const OCRepresentation& rep,
542                                const QueryParamsMap& queryParametersMap,
543                                PostCallback attributeHandler,
544                                QualityOfService QoS)
545 {
546     QueryParamsMap mapCpy(queryParametersMap);
547
548     if(!resourceType.empty())
549     {
550         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
551     }
552
553     if(!resourceInterface.empty())
554     {
555         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
556     }
557
558     return result_guard(post(rep, mapCpy, attributeHandler, QoS));
559 }
560
561 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler, QualityOfService QoS)
562 {
563     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
564                          m_devAddr, m_uri, m_headerOptions, deleteHandler, QoS);
565 }
566
567 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler)
568 {
569     QualityOfService defaultQos = OC::QualityOfService::NaQos;
570     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
571
572     return result_guard(deleteResource(deleteHandler, defaultQos));
573 }
574
575 OCStackResult OCResource::observe(ObserveType observeType,
576         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler,
577         QualityOfService QoS)
578 {
579     if(m_observeHandle != nullptr)
580     {
581         return result_guard(OC_STACK_INVALID_PARAM);
582     }
583
584     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
585                          observeType, &m_observeHandle, m_devAddr,
586                          m_uri, queryParametersMap, m_headerOptions,
587                          observeHandler, QoS);
588 }
589
590 OCStackResult OCResource::observe(ObserveType observeType,
591         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
592 {
593     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
594     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
595
596     return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
597 }
598
599 OCStackResult OCResource::cancelObserve()
600 {
601     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
602     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
603     return result_guard(cancelObserve(defaultQoS));
604 }
605
606 OCStackResult OCResource::cancelObserve(QualityOfService QoS)
607 {
608     if(m_observeHandle == nullptr)
609     {
610         return result_guard(OC_STACK_INVALID_PARAM);
611     }
612
613     OCStackResult result =  checked_guard(m_clientWrapper.lock(),
614             &IClientWrapper::CancelObserveResource,
615             m_observeHandle, "", m_uri, m_headerOptions, QoS);
616
617     if(result == OC_STACK_OK)
618     {
619         m_observeHandle = nullptr;
620     }
621
622     return result;
623 }
624
625 void OCResource::setHeaderOptions(const HeaderOptions& headerOptions)
626 {
627     m_headerOptions = headerOptions;
628 }
629
630 void OCResource::unsetHeaderOptions()
631 {
632     m_headerOptions.clear();
633 }
634
635 std::string OCResource::host() const
636 {
637     std::ostringstream ss;
638     if (m_devAddr.flags & OC_SECURE)
639     {
640         ss << COAPS;
641     }
642     else if (m_devAddr.adapter & OC_ADAPTER_TCP)
643     {
644         ss << COAP_TCP;
645     }
646     else
647     {
648         ss << COAP;
649     }
650     if (m_devAddr.flags & OC_IP_USE_V6)
651     {
652         ss << '[' << m_devAddr.addr << ']';
653     }
654     else
655     {
656         ss << m_devAddr.addr;
657     }
658     if (m_devAddr.port)
659     {
660         ss << ':' << m_devAddr.port;
661     }
662     return ss.str();
663 }
664
665 std::string OCResource::uri() const
666 {
667     return m_uri;
668 }
669
670 OCConnectivityType OCResource::connectivityType() const
671 {
672     return static_cast<OCConnectivityType>(
673            (m_devAddr.adapter << CT_ADAPTER_SHIFT) | (m_devAddr.flags & CT_MASK_FLAGS));
674 }
675
676 bool OCResource::isObservable() const
677 {
678     return m_isObservable;
679 }
680
681 std::vector<std::string> OCResource::getResourceTypes() const
682 {
683     return m_resourceTypes;
684 }
685
686 std::vector<std::string> OCResource::getResourceInterfaces(void) const
687 {
688     return m_interfaces;
689 }
690
691 OCResourceIdentifier OCResource::uniqueIdentifier() const
692 {
693     return m_resourceId;
694 }
695
696 std::string OCResource::sid() const
697 {
698     return this->uniqueIdentifier().m_representation;
699 }
700
701 bool OCResource::operator==(const OCResource &other) const
702 {
703     return m_resourceId == other.m_resourceId;
704 }
705
706 bool OCResource::operator!=(const OCResource &other) const
707 {
708     return m_resourceId != other.m_resourceId;
709 }
710
711 bool OCResource::operator<(const OCResource &other) const
712 {
713     return m_resourceId < other.m_resourceId;
714 }
715
716 bool OCResource::operator>(const OCResource &other) const
717 {
718     return m_resourceId > other.m_resourceId;
719 }
720
721 bool OCResource::operator<=(const OCResource &other) const
722 {
723     return m_resourceId <= other.m_resourceId;
724 }
725
726 bool OCResource::operator>=(const OCResource &other) const
727 {
728     return m_resourceId >= other.m_resourceId;
729 }
730
731 OCResourceIdentifier::OCResourceIdentifier(const std::string& wireServerIdentifier,
732         const std::string& resourceUri)
733     :m_representation(wireServerIdentifier), m_resourceUri(resourceUri)
734 {
735 }
736
737 std::ostream& operator <<(std::ostream& os, const OCResourceIdentifier& ri)
738 {
739     os << ri.m_representation<<ri.m_resourceUri;
740
741     return os;
742 }
743
744 bool OCResourceIdentifier::operator==(const OCResourceIdentifier &other) const
745 {
746     return m_representation == other.m_representation
747         && m_resourceUri == other.m_resourceUri;
748 }
749
750 bool OCResourceIdentifier::operator!=(const OCResourceIdentifier &other) const
751 {
752     return !(*this == other);
753 }
754
755 bool OCResourceIdentifier::operator<(const OCResourceIdentifier &other) const
756 {
757     return m_resourceUri < other.m_resourceUri
758         || (m_resourceUri == other.m_resourceUri &&
759                 m_representation < other.m_representation);
760 }
761
762 bool OCResourceIdentifier::operator>(const OCResourceIdentifier &other) const
763 {
764     return *this != other && !(*this<other);
765 }
766
767 bool OCResourceIdentifier::operator<=(const OCResourceIdentifier &other) const
768 {
769     return !(*this > other);
770 }
771
772 bool OCResourceIdentifier::operator>=(const OCResourceIdentifier &other) const
773 {
774     return !(*this < other);
775 }
776
777 } // namespace OC