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