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