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