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