Merge branch 'cloud-interface'
[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 #ifdef HAVE_ARPA_INET_H
27 #include <arpa/inet.h>
28 #endif
29 #ifdef HAVE_WS2TCPIP_H
30 #include <ws2tcpip.h>
31 #endif
32 #ifdef HAVE_IN6ADDR_H
33 #include <in6addr.h>
34 #endif
35
36 namespace OC {
37
38 static const char COAP[] = "coap://";
39 static const char COAPS[] = "coaps://";
40 static const char COAP_TCP[] = "coap+tcp://";
41 static const char COAP_GATT[] = "coap+gatt://";
42 static const char COAP_RFCOMM[] = "coap+rfcomm://";
43
44 using OC::nil_guard;
45 using OC::result_guard;
46 using OC::checked_guard;
47
48 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
49                         const OCDevAddr& devAddr, const std::string& uri,
50                         const std::string& serverId, uint8_t property,
51                         const std::vector<std::string>& resourceTypes,
52                         const std::vector<std::string>& interfaces)
53  :  m_clientWrapper(clientWrapper), m_uri(uri),
54     m_resourceId(serverId, m_uri), m_devAddr(devAddr),
55     m_isCollection(false), m_property(property),
56     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
57     m_observeHandle(nullptr)
58 {
59     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
60                         != m_interfaces.end();
61
62     if (m_uri.empty() ||
63         resourceTypes.empty() ||
64         interfaces.empty()||
65         m_clientWrapper.expired())
66     {
67         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
68                 interfaces.empty(), m_clientWrapper.expired(), false, false);
69     }
70 }
71
72 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
73                         const std::string& host, const std::string& uri,
74                         const std::string& serverId,
75                         OCConnectivityType connectivityType, uint8_t property,
76                         const std::vector<std::string>& resourceTypes,
77                         const std::vector<std::string>& interfaces)
78  :  m_clientWrapper(clientWrapper), m_uri(uri),
79     m_resourceId(serverId, m_uri),
80     m_isCollection(false), m_property(property),
81     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
82     m_observeHandle(nullptr)
83 {
84     m_devAddr = OCDevAddr{OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS, 0, {0}, 0,
85 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
86                           {0}
87 #endif
88                         };
89     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
90                         != m_interfaces.end();
91
92     if (m_uri.empty() ||
93         resourceTypes.empty() ||
94         interfaces.empty()||
95         m_clientWrapper.expired())
96     {
97         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
98                 interfaces.empty(), m_clientWrapper.expired(), false, false);
99     }
100
101     if (uri.length() == 1 && uri[0] == '/')
102     {
103         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
104                 interfaces.empty(), m_clientWrapper.expired(), false, false);
105     }
106
107     if (uri[0] != '/')
108     {
109         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
110                 interfaces.empty(), m_clientWrapper.expired(), false, false);
111     }
112
113     // construct the devAddr from the pieces we have
114     m_devAddr.adapter = static_cast<OCTransportAdapter>(connectivityType >> CT_ADAPTER_SHIFT);
115     m_devAddr.flags = static_cast<OCTransportFlags>(connectivityType & CT_MASK_FLAGS);
116
117     this->setHost(host);
118 }
119
120 OCResource::~OCResource()
121 {
122 }
123
124 void OCResource::setHost(const std::string& host)
125 {
126     size_t prefix_len;
127
128     if(host.compare(0, sizeof(COAP) - 1, COAP) == 0)
129     {
130         prefix_len = sizeof(COAP) - 1;
131     }
132     else if(host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
133     {
134         prefix_len = sizeof(COAPS) - 1;
135         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags | OC_SECURE);
136     }
137     else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
138     {
139         prefix_len = sizeof(COAP_TCP) - 1;
140     }
141     else if (host.compare(0, sizeof(COAP_GATT) - 1, COAP_GATT) == 0)
142     {
143         prefix_len = sizeof(COAP_GATT) - 1;
144     }
145     else if (host.compare(0, sizeof(COAP_RFCOMM) - 1, COAP_RFCOMM) == 0)
146     {
147         prefix_len = sizeof(COAP_RFCOMM) - 1;
148     }
149     else
150     {
151         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
152             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
153     }
154
155     // remove 'coap://' or 'coaps://' or 'coap+tcp://' or 'coap+gatt://' or 'coap+rfcomm://'
156     std::string host_token = host.substr(prefix_len);
157
158     if(host_token[0] == '[') // IPv6
159     {
160         size_t bracket = host_token.find(']');
161
162         if(bracket == std::string::npos || bracket == 0)
163         {
164             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
165                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
166         }
167         // extract the ipv6 address
168         std::string ip6Addr = host_token.substr(1, bracket - 1);
169
170         // address validity check
171         struct in6_addr buf;
172         const char *cAddr = ip6Addr.c_str();
173         if(0 == inet_pton(AF_INET6, cAddr, &buf))
174         {
175             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
176                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
177         }
178
179         //skip ']' and ':' characters in host string
180         host_token = host_token.substr(bracket + 2);
181         int port = std::stoi(host_token);
182
183         if (0 > port || UINT16_MAX < port)
184         {
185             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
186                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
187         }
188
189         ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
190         m_devAddr.addr[ip6Addr.length()] = '\0';
191         m_devAddr.port = static_cast<uint16_t>(port);
192         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_IP_USE_V6);
193     }
194     else if (host_token[0] == ':')
195     {
196         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
197             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
198     }
199     else
200     {
201         size_t dot = host_token.find('.');
202         if (std::string::npos == dot) // MAC
203         {
204             std::string macAddr = host_token;
205
206             // address validity check
207             if (MAC_ADDR_STR_SIZE != macAddr.length())
208             {
209                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
210                     m_interfaces.empty(), m_clientWrapper.expired(), false, false);
211             }
212
213             for (size_t blockCnt = 0; blockCnt < MAC_ADDR_BLOCKS; blockCnt++)
214             {
215                 std::string block = macAddr.substr(blockCnt * 3, 2);
216
217                 if (std::string::npos != block.find_first_not_of("0123456789ABCDEFabcdef"))
218                 {
219                     throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
220                         m_interfaces.empty(), m_clientWrapper.expired(), false, false);
221                 }
222
223                 if (MAC_ADDR_BLOCKS - 1 > blockCnt)
224                 {
225                     char delimiter = macAddr[blockCnt * 3 + 2];
226
227                     if (':' != delimiter)
228                     {
229                         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
230                             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
231                     }
232                 }
233             }
234
235             macAddr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
236             m_devAddr.addr[MAC_ADDR_STR_SIZE] = '\0';
237         }
238         else // IPv4
239         {
240             size_t colon = host_token.find(':');
241
242             if (colon == std::string::npos || colon == 0)
243             {
244                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
245                     m_interfaces.empty(), m_clientWrapper.expired(), false, false);
246             }
247
248             // extract the ipv4 address
249             std::string ip4Addr = host_token.substr(0, colon);
250
251             // address validity check
252             struct in_addr buf;
253             const char *cAddr = ip4Addr.c_str();
254             if(0 == inet_pton(AF_INET, cAddr, &buf))
255             {
256                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
257                     m_interfaces.empty(), m_clientWrapper.expired(), false, false);
258             }
259
260             //skip ':' characters in host string
261             host_token = host_token.substr(colon + 1);
262             int port = std::stoi(host_token);
263
264             if (0 > port || UINT16_MAX < port)
265             {
266                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
267                     m_interfaces.empty(), m_clientWrapper.expired(), false, false);
268             }
269
270             ip4Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
271             m_devAddr.addr[ip4Addr.length()] = '\0';
272             m_devAddr.port = static_cast<uint16_t>(port);
273         }
274     }
275 }
276
277 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
278                               GetCallback attributeHandler, QualityOfService QoS)
279 {
280     return checked_guard(m_clientWrapper.lock(),
281                             &IClientWrapper::GetResourceRepresentation,
282                             m_devAddr, m_uri,
283                             queryParametersMap, m_headerOptions, CT_DEFAULT,
284                             attributeHandler, QoS);
285 }
286
287 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
288                               GetCallback attributeHandler)
289 {
290     QualityOfService defaultQos = OC::QualityOfService::NaQos;
291     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
292     return result_guard(get(queryParametersMap, attributeHandler, defaultQos));
293 }
294
295 OCStackResult OCResource::get(const std::string& resourceType,
296                      const std::string& resourceInterface, const QueryParamsMap& queryParametersMap,
297                      GetCallback attributeHandler)
298 {
299     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
300     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
301
302     return result_guard(get(resourceType, resourceInterface, queryParametersMap, attributeHandler, defaultQoS));
303 }
304
305 OCStackResult OCResource::get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
306         QualityOfService QoS)
307 {
308     QueryParamsMap mapCpy(queryParametersMap);
309
310     if(!resourceType.empty())
311     {
312         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
313     }
314
315     if(!resourceInterface.empty())
316     {
317         mapCpy[OC::Key::INTERFACESKEY]= resourceInterface;
318     }
319
320     return result_guard(get(mapCpy, attributeHandler, QoS));
321 }
322
323 OCStackResult OCResource::put(const OCRepresentation& rep,
324                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler,
325                               QualityOfService QoS)
326 {
327     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation,
328                          m_devAddr, m_uri, rep, queryParametersMap,
329                          m_headerOptions, attributeHandler, QoS);
330 }
331
332 OCStackResult OCResource::put(const OCRepresentation& rep,
333                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
334 {
335     QualityOfService defaultQos = OC::QualityOfService::NaQos;
336     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
337     return result_guard(put(rep, queryParametersMap, attributeHandler, defaultQos));
338 }
339
340 OCStackResult OCResource::put(const std::string& resourceType,
341                               const std::string& resourceInterface, const OCRepresentation& rep,
342                               const QueryParamsMap& queryParametersMap,
343                               PutCallback attributeHandler)
344 {
345     QualityOfService defaultQos = OC::QualityOfService::NaQos;
346     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
347
348     return result_guard(put(resourceType, resourceInterface, rep, queryParametersMap,
349             attributeHandler, defaultQos));
350 }
351
352 OCStackResult OCResource::put(const std::string& resourceType,
353                               const std::string& resourceInterface, const OCRepresentation& rep,
354                               const QueryParamsMap& queryParametersMap,
355                               PutCallback attributeHandler,
356                               QualityOfService QoS)
357 {
358     QueryParamsMap mapCpy(queryParametersMap);
359
360     if(!resourceType.empty())
361     {
362         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
363     }
364
365     if(!resourceInterface.empty())
366     {
367         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
368     }
369
370     return result_guard(put(rep, mapCpy, attributeHandler, QoS));
371 }
372
373 OCStackResult OCResource::post(const OCRepresentation& rep,
374                                const QueryParamsMap& queryParametersMap, PostCallback attributeHandler,
375                                QualityOfService QoS)
376 {
377     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
378                          m_devAddr, m_uri, rep, queryParametersMap,
379                          m_headerOptions, CT_DEFAULT, attributeHandler, QoS);
380 }
381
382 OCStackResult OCResource::post(const OCRepresentation& rep,
383                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
384 {
385     QualityOfService defaultQos = OC::QualityOfService::NaQos;
386     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
387     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
388 }
389
390 OCStackResult OCResource::post(const std::string& resourceType,
391                                const std::string& resourceInterface, const OCRepresentation& rep,
392                                const QueryParamsMap& queryParametersMap,
393                                PostCallback attributeHandler)
394 {
395     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
396     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
397
398     return result_guard(post(resourceType, resourceInterface, rep, queryParametersMap, attributeHandler,
399             defaultQoS));
400 }
401
402 OCStackResult OCResource::post(const std::string& resourceType,
403                                const std::string& resourceInterface, const OCRepresentation& rep,
404                                const QueryParamsMap& queryParametersMap,
405                                PostCallback attributeHandler,
406                                QualityOfService QoS)
407 {
408     QueryParamsMap mapCpy(queryParametersMap);
409
410     if(!resourceType.empty())
411     {
412         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
413     }
414
415     if(!resourceInterface.empty())
416     {
417         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
418     }
419
420     return result_guard(post(rep, mapCpy, attributeHandler, QoS));
421 }
422
423 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler, QualityOfService QoS)
424 {
425     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
426                          m_devAddr, m_uri, m_headerOptions, CT_DEFAULT, deleteHandler, QoS);
427 }
428
429 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler)
430 {
431     QualityOfService defaultQos = OC::QualityOfService::NaQos;
432     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
433
434     return result_guard(deleteResource(deleteHandler, defaultQos));
435 }
436
437 OCStackResult OCResource::observe(ObserveType observeType,
438         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler,
439         QualityOfService QoS)
440 {
441     if(m_observeHandle != nullptr)
442     {
443         return result_guard(OC_STACK_INVALID_PARAM);
444     }
445
446     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
447                          observeType, &m_observeHandle, m_devAddr,
448                          m_uri, queryParametersMap, m_headerOptions,
449                          observeHandler, QoS);
450 }
451
452 OCStackResult OCResource::observe(ObserveType observeType,
453         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
454 {
455     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
456     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
457
458     return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
459 }
460
461 OCStackResult OCResource::cancelObserve()
462 {
463     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
464     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
465     return result_guard(cancelObserve(defaultQoS));
466 }
467
468 OCStackResult OCResource::cancelObserve(QualityOfService QoS)
469 {
470     if(m_observeHandle == nullptr)
471     {
472         return result_guard(OC_STACK_INVALID_PARAM);
473     }
474
475     OCStackResult result =  checked_guard(m_clientWrapper.lock(),
476             &IClientWrapper::CancelObserveResource,
477             m_observeHandle, (const char*)"", m_uri, m_headerOptions, QoS);
478
479     if(result == OC_STACK_OK)
480     {
481         m_observeHandle = nullptr;
482     }
483
484     return result;
485 }
486
487 void OCResource::setHeaderOptions(const HeaderOptions& headerOptions)
488 {
489     m_headerOptions = headerOptions;
490 }
491
492 void OCResource::unsetHeaderOptions()
493 {
494     m_headerOptions.clear();
495 }
496
497 std::string OCResource::host() const
498 {
499     std::ostringstream ss;
500
501     if (m_devAddr.adapter & OC_ADAPTER_TCP)
502     {
503         ss << COAP_TCP;
504     }
505     else if (m_devAddr.adapter & OC_ADAPTER_GATT_BTLE)
506     {
507         ss << COAP_GATT;
508     }
509     else if (m_devAddr.adapter & OC_ADAPTER_RFCOMM_BTEDR)
510     {
511         ss << COAP_RFCOMM;
512     }
513     else
514     {
515         if (m_devAddr.flags & OC_SECURE)
516         {
517             ss << COAPS;
518         }
519         else
520         {
521             ss << COAP;
522         }
523     }
524
525     if (m_devAddr.flags & OC_IP_USE_V6)
526     {
527         ss << '[' << m_devAddr.addr << ']';
528     }
529     else
530     {
531         ss << m_devAddr.addr;
532     }
533     if (m_devAddr.port)
534     {
535         ss << ':' << m_devAddr.port;
536     }
537     return ss.str();
538 }
539
540 std::string OCResource::uri() const
541 {
542     return m_uri;
543 }
544
545 OCConnectivityType OCResource::connectivityType() const
546 {
547     return static_cast<OCConnectivityType>(
548            (m_devAddr.adapter << CT_ADAPTER_SHIFT) | (m_devAddr.flags & CT_MASK_FLAGS));
549 }
550
551 bool OCResource::isObservable() const
552 {
553     return (m_property & OC_OBSERVABLE) == OC_OBSERVABLE;
554 }
555
556 #ifdef WITH_MQ
557 bool OCResource::isPublish() const
558 {
559     return (m_property & OC_MQ_PUBLISHER) == OC_MQ_PUBLISHER;
560 }
561 #endif
562
563 std::vector<std::string> OCResource::getResourceTypes() const
564 {
565     return m_resourceTypes;
566 }
567
568 std::vector<std::string> OCResource::getResourceInterfaces(void) const
569 {
570     return m_interfaces;
571 }
572
573 OCResourceIdentifier OCResource::uniqueIdentifier() const
574 {
575     return m_resourceId;
576 }
577
578 std::string OCResource::sid() const
579 {
580     return this->uniqueIdentifier().m_representation;
581 }
582
583 #ifdef WITH_MQ
584 OCStackResult OCResource::discoveryMQTopics(const QueryParamsMap& queryParametersMap,
585                                             FindCallback attributeHandler)
586 {
587     QualityOfService defaultQos = OC::QualityOfService::NaQos;
588     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
589     return checked_guard(m_clientWrapper.lock(),
590                             &IClientWrapper::ListenForMQTopic,
591                             m_devAddr, m_uri,
592                             queryParametersMap, m_headerOptions,
593                             attributeHandler, defaultQos);
594 }
595
596 OCStackResult OCResource::createMQTopic(const OCRepresentation& rep,
597                                         const std::string& topicUri,
598                                         const QueryParamsMap& queryParametersMap,
599                                         MQCreateTopicCallback attributeHandler)
600 {
601     QualityOfService defaultQos = OC::QualityOfService::NaQos;
602     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
603     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutMQTopicRepresentation,
604                          m_devAddr, topicUri, rep, queryParametersMap,
605                          m_headerOptions, attributeHandler, defaultQos);
606 }
607 #endif
608 #ifdef MQ_SUBSCRIBER
609 OCStackResult OCResource::subscribeMQTopic(ObserveType observeType,
610         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
611 {
612     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
613     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
614
615     return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
616 }
617
618 OCStackResult OCResource::unsubscribeMQTopic()
619 {
620     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
621     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
622     return result_guard(cancelObserve(defaultQoS));
623 }
624
625 OCStackResult OCResource::requestMQPublish(const QueryParamsMap& queryParametersMap,
626                                            PostCallback attributeHandler)
627 {
628     OCRepresentation rep;
629     rep.setValue(std::string("req_pub"), std::string("true"));
630     QualityOfService defaultQos = OC::QualityOfService::NaQos;
631     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
632     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
633 }
634 #endif
635 #ifdef MQ_PUBLISHER
636 OCStackResult OCResource::publishMQTopic(const OCRepresentation& rep,
637                                          const QueryParamsMap& queryParametersMap,
638                                          PostCallback attributeHandler)
639 {
640     QualityOfService defaultQos = OC::QualityOfService::NaQos;
641     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
642     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
643 }
644 #endif
645
646 bool OCResource::operator==(const OCResource &other) const
647 {
648     return m_resourceId == other.m_resourceId;
649 }
650
651 bool OCResource::operator!=(const OCResource &other) const
652 {
653     return m_resourceId != other.m_resourceId;
654 }
655
656 bool OCResource::operator<(const OCResource &other) const
657 {
658     return m_resourceId < other.m_resourceId;
659 }
660
661 bool OCResource::operator>(const OCResource &other) const
662 {
663     return m_resourceId > other.m_resourceId;
664 }
665
666 bool OCResource::operator<=(const OCResource &other) const
667 {
668     return m_resourceId <= other.m_resourceId;
669 }
670
671 bool OCResource::operator>=(const OCResource &other) const
672 {
673     return m_resourceId >= other.m_resourceId;
674 }
675
676 OCResourceIdentifier::OCResourceIdentifier(const std::string& wireServerIdentifier,
677         const std::string& resourceUri)
678     :m_representation(wireServerIdentifier), m_resourceUri(resourceUri)
679 {
680 }
681
682 std::ostream& operator <<(std::ostream& os, const OCResourceIdentifier& ri)
683 {
684     os << ri.m_representation<<ri.m_resourceUri;
685
686     return os;
687 }
688
689 bool OCResourceIdentifier::operator==(const OCResourceIdentifier &other) const
690 {
691     return m_representation == other.m_representation
692         && m_resourceUri == other.m_resourceUri;
693 }
694
695 bool OCResourceIdentifier::operator!=(const OCResourceIdentifier &other) const
696 {
697     return !(*this == other);
698 }
699
700 bool OCResourceIdentifier::operator<(const OCResourceIdentifier &other) const
701 {
702     return m_resourceUri < other.m_resourceUri
703         || (m_resourceUri == other.m_resourceUri &&
704                 m_representation < other.m_representation);
705 }
706
707 bool OCResourceIdentifier::operator>(const OCResourceIdentifier &other) const
708 {
709     return *this != other && !(*this<other);
710 }
711
712 bool OCResourceIdentifier::operator<=(const OCResourceIdentifier &other) const
713 {
714     return !(*this > other);
715 }
716
717 bool OCResourceIdentifier::operator>=(const OCResourceIdentifier &other) const
718 {
719     return !(*this < other);
720 }
721
722 } // namespace OC