Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / src / OCResource.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "OCResource.h"
22 #include "OCUtilities.h"
23
24 #include <boost/lexical_cast.hpp>
25 #include <sstream>
26
27 namespace OC {
28
29 static const char COAP[] = "coap://";
30 static const char COAPS[] = "coaps://";
31
32 #ifdef TCP_ADAPTER
33 static const char COAP_TCP[] = "coap+tcp://";
34 #endif
35
36 using OC::nil_guard;
37 using OC::result_guard;
38 using OC::checked_guard;
39
40 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
41                         const OCDevAddr& devAddr, const std::string& uri,
42                         const std::string& serverId, bool observable,
43                         const std::vector<std::string>& resourceTypes,
44                         const std::vector<std::string>& interfaces)
45  :  m_clientWrapper(clientWrapper), m_uri(uri),
46     m_resourceId(serverId, m_uri), m_devAddr(devAddr),
47     m_isObservable(observable), m_isCollection(false),
48     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
49     m_observeHandle(nullptr)
50 {
51     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
52                         != m_interfaces.end();
53
54     if (m_uri.empty() ||
55         resourceTypes.empty() ||
56         interfaces.empty()||
57         m_clientWrapper.expired())
58     {
59         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
60                 interfaces.empty(), m_clientWrapper.expired(), false, false);
61     }
62 }
63
64 OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
65                         const std::string& host, const std::string& uri,
66                         const std::string& serverId,
67                         OCConnectivityType connectivityType, bool observable,
68                         const std::vector<std::string>& resourceTypes,
69                         const std::vector<std::string>& interfaces)
70  :  m_clientWrapper(clientWrapper), m_uri(uri),
71     m_resourceId(serverId, m_uri),
72     m_devAddr{ OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS, 0, {0}, 0 },
73     m_isObservable(observable), m_isCollection(false),
74     m_resourceTypes(resourceTypes), m_interfaces(interfaces),
75     m_observeHandle(nullptr)
76 {
77     m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE)
78                         != m_interfaces.end();
79
80     if (m_uri.empty() ||
81         resourceTypes.empty() ||
82         interfaces.empty()||
83         m_clientWrapper.expired())
84     {
85         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
86                 interfaces.empty(), m_clientWrapper.expired(), false, false);
87     }
88
89     if (uri.length() == 1 && uri[0] == '/')
90     {
91         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
92                 interfaces.empty(), m_clientWrapper.expired(), false, false);
93     }
94
95     if (uri[0] != '/')
96     {
97         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
98                 interfaces.empty(), m_clientWrapper.expired(), false, false);
99     }
100
101     // construct the devAddr from the pieces we have
102     m_devAddr.adapter = static_cast<OCTransportAdapter>(connectivityType >> CT_ADAPTER_SHIFT);
103     m_devAddr.flags = static_cast<OCTransportFlags>(connectivityType & CT_MASK_FLAGS);
104     size_t len = host.length();
105     if (len >= MAX_ADDR_STR_SIZE)
106     {
107         throw std::length_error("host address is too long.");
108     }
109
110     this->setHost(host);
111 }
112
113 OCResource::~OCResource()
114 {
115 }
116
117 void OCResource::setHost(const std::string& host)
118 {
119     size_t prefix_len;
120
121     if(host.compare(0, sizeof(COAP) - 1, COAP) == 0)
122     {
123         prefix_len = sizeof(COAP) - 1;
124     }
125     else if(host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
126     {
127         prefix_len = sizeof(COAPS) - 1;
128         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_SECURE);
129     }
130 #ifdef TCP_ADAPTER
131     else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
132     {
133         prefix_len = sizeof(COAP_TCP) - 1;
134         m_devAddr.adapter = static_cast<OCTransportAdapter>(m_devAddr.adapter & OC_ADAPTER_TCP);
135     }
136 #endif
137     else
138     {
139         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
140             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
141     }
142
143     // removed coap:// or coaps:// or coap+tcp://
144     std::string host_token = host.substr(prefix_len);
145
146     if(host_token[0] == '[')
147     {
148         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_IP_USE_V6);
149
150         size_t found = host_token.find(']');
151
152         if(found == std::string::npos || found == 0)
153         {
154             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
155                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
156         }
157         // extract the ipaddress
158         std::string ip6Addr = host_token.substr(1, found-1);
159         ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
160         m_devAddr.addr[ip6Addr.length()] = '\0';
161         //skip ']' and ':' characters in host string
162         host_token = host_token.substr(found + 2);
163     }
164     else
165     {
166         size_t found = host_token.find(':');
167
168         if(found == std::string::npos || found == 0)
169         {
170             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
171                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
172         }
173
174         std::string addrPart = host_token.substr(0, found);
175         addrPart.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
176         m_devAddr.addr[addrPart.length()] = '\0';
177         //skip ':' character in host string
178         host_token = host_token.substr(found + 1);
179     }
180
181     int port = std::stoi(host_token);
182
183     if( port < 0 || port > UINT16_MAX )
184     {
185         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
186             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
187     }
188
189     m_devAddr.port = static_cast<uint16_t>(port);
190
191 }
192
193 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
194                               GetCallback attributeHandler, QualityOfService QoS)
195 {
196     return checked_guard(m_clientWrapper.lock(),
197                             &IClientWrapper::GetResourceRepresentation,
198                             m_devAddr, m_uri,
199                             queryParametersMap, m_headerOptions,
200                             attributeHandler, QoS);
201 }
202
203 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
204                               GetCallback attributeHandler)
205 {
206     QualityOfService defaultQos = OC::QualityOfService::NaQos;
207     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
208     return result_guard(get(queryParametersMap, attributeHandler, defaultQos));
209 }
210
211 OCStackResult OCResource::get(const std::string& resourceType,
212                      const std::string& resourceInterface, const QueryParamsMap& queryParametersMap,
213                      GetCallback attributeHandler)
214 {
215     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
216     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
217
218     return result_guard(get(resourceType, resourceInterface, queryParametersMap, attributeHandler, defaultQoS));
219 }
220
221 OCStackResult OCResource::get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
222         QualityOfService QoS)
223 {
224     QueryParamsMap mapCpy(queryParametersMap);
225
226     if(!resourceType.empty())
227     {
228         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
229     }
230
231     if(!resourceInterface.empty())
232     {
233         mapCpy[OC::Key::INTERFACESKEY]= resourceInterface;
234     }
235
236     return result_guard(get(mapCpy, attributeHandler, QoS));
237 }
238
239 OCStackResult OCResource::put(const OCRepresentation& rep,
240                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler,
241                               QualityOfService QoS)
242 {
243     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation,
244                          m_devAddr, m_uri, rep, queryParametersMap,
245                          m_headerOptions, attributeHandler, QoS);
246 }
247
248 OCStackResult OCResource::put(const OCRepresentation& rep,
249                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
250 {
251     QualityOfService defaultQos = OC::QualityOfService::NaQos;
252     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
253     return result_guard(put(rep, queryParametersMap, attributeHandler, defaultQos));
254 }
255
256 OCStackResult OCResource::put(const std::string& resourceType,
257                               const std::string& resourceInterface, const OCRepresentation& rep,
258                               const QueryParamsMap& queryParametersMap,
259                               PutCallback attributeHandler)
260 {
261     QualityOfService defaultQos = OC::QualityOfService::NaQos;
262     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
263
264     return result_guard(put(resourceType, resourceInterface, rep, queryParametersMap,
265             attributeHandler, defaultQos));
266 }
267
268 OCStackResult OCResource::put(const std::string& resourceType,
269                               const std::string& resourceInterface, const OCRepresentation& rep,
270                               const QueryParamsMap& queryParametersMap,
271                               PutCallback attributeHandler,
272                               QualityOfService QoS)
273 {
274     QueryParamsMap mapCpy(queryParametersMap);
275
276     if(!resourceType.empty())
277     {
278         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
279     }
280
281     if(!resourceInterface.empty())
282     {
283         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
284     }
285
286     return result_guard(put(rep, mapCpy, attributeHandler, QoS));
287 }
288
289 OCStackResult OCResource::post(const OCRepresentation& rep,
290                                const QueryParamsMap& queryParametersMap, PostCallback attributeHandler,
291                                QualityOfService QoS)
292 {
293     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
294                          m_devAddr, m_uri, rep, queryParametersMap,
295                          m_headerOptions, attributeHandler, QoS);
296 }
297
298 OCStackResult OCResource::post(const OCRepresentation& rep,
299                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
300 {
301     QualityOfService defaultQos = OC::QualityOfService::NaQos;
302     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
303     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
304 }
305
306 OCStackResult OCResource::post(const std::string& resourceType,
307                                const std::string& resourceInterface, const OCRepresentation& rep,
308                                const QueryParamsMap& queryParametersMap,
309                                PostCallback attributeHandler)
310 {
311     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
312     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
313
314     return result_guard(post(resourceType, resourceInterface, rep, queryParametersMap, attributeHandler,
315             defaultQoS));
316 }
317
318 OCStackResult OCResource::post(const std::string& resourceType,
319                                const std::string& resourceInterface, const OCRepresentation& rep,
320                                const QueryParamsMap& queryParametersMap,
321                                PostCallback attributeHandler,
322                                QualityOfService QoS)
323 {
324     QueryParamsMap mapCpy(queryParametersMap);
325
326     if(!resourceType.empty())
327     {
328         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
329     }
330
331     if(!resourceInterface.empty())
332     {
333         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
334     }
335
336     return result_guard(post(rep, mapCpy, attributeHandler, QoS));
337 }
338
339 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler, QualityOfService QoS)
340 {
341     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
342                          m_devAddr, m_uri, m_headerOptions, deleteHandler, QoS);
343 }
344
345 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler)
346 {
347     QualityOfService defaultQos = OC::QualityOfService::NaQos;
348     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
349
350     return result_guard(deleteResource(deleteHandler, defaultQos));
351 }
352
353 OCStackResult OCResource::observe(ObserveType observeType,
354         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler,
355         QualityOfService QoS)
356 {
357     if(m_observeHandle != nullptr)
358     {
359         return result_guard(OC_STACK_INVALID_PARAM);
360     }
361
362     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
363                          observeType, &m_observeHandle, m_devAddr,
364                          m_uri, queryParametersMap, m_headerOptions,
365                          observeHandler, QoS);
366 }
367
368 OCStackResult OCResource::observe(ObserveType observeType,
369         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
370 {
371     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
372     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
373
374     return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
375 }
376
377 OCStackResult OCResource::cancelObserve()
378 {
379     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
380     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
381     return result_guard(cancelObserve(defaultQoS));
382 }
383
384 OCStackResult OCResource::cancelObserve(QualityOfService QoS)
385 {
386     if(m_observeHandle == nullptr)
387     {
388         return result_guard(OC_STACK_INVALID_PARAM);
389     }
390
391     OCStackResult result =  checked_guard(m_clientWrapper.lock(),
392             &IClientWrapper::CancelObserveResource,
393             m_observeHandle, "", m_uri, m_headerOptions, QoS);
394
395     if(result == OC_STACK_OK)
396     {
397         m_observeHandle = nullptr;
398     }
399
400     return result;
401 }
402
403 void OCResource::setHeaderOptions(const HeaderOptions& headerOptions)
404 {
405     m_headerOptions = headerOptions;
406 }
407
408 void OCResource::unsetHeaderOptions()
409 {
410     m_headerOptions.clear();
411 }
412
413 std::string OCResource::host() const
414 {
415     std::ostringstream ss;
416     if (m_devAddr.flags & OC_SECURE)
417     {
418         ss << COAPS;
419     }
420 #ifdef TCP_ADAPTER
421     else if (m_devAddr.adapter & OC_ADAPTER_TCP)
422     {
423         ss << COAP_TCP;
424     }
425 #endif
426     else
427     {
428         ss << COAP;
429     }
430     if (m_devAddr.flags & OC_IP_USE_V6)
431     {
432         ss << '[' << m_devAddr.addr << ']';
433     }
434     else
435     {
436         ss << m_devAddr.addr;
437     }
438     if (m_devAddr.port)
439     {
440         ss << ':' << m_devAddr.port;
441     }
442     return ss.str();
443 }
444
445 std::string OCResource::uri() const
446 {
447     return m_uri;
448 }
449
450 OCConnectivityType OCResource::connectivityType() const
451 {
452     return static_cast<OCConnectivityType>(
453            (m_devAddr.adapter << CT_ADAPTER_SHIFT) | (m_devAddr.flags & CT_MASK_FLAGS));
454 }
455
456 bool OCResource::isObservable() const
457 {
458     return m_isObservable;
459 }
460
461 std::vector<std::string> OCResource::getResourceTypes() const
462 {
463     return m_resourceTypes;
464 }
465
466 std::vector<std::string> OCResource::getResourceInterfaces(void) const
467 {
468     return m_interfaces;
469 }
470
471 OCResourceIdentifier OCResource::uniqueIdentifier() const
472 {
473     return m_resourceId;
474 }
475
476 std::string OCResource::sid() const
477 {
478     return this->uniqueIdentifier().m_representation;
479 }
480
481 bool OCResource::operator==(const OCResource &other) const
482 {
483     return m_resourceId == other.m_resourceId;
484 }
485
486 bool OCResource::operator!=(const OCResource &other) const
487 {
488     return m_resourceId != other.m_resourceId;
489 }
490
491 bool OCResource::operator<(const OCResource &other) const
492 {
493     return m_resourceId < other.m_resourceId;
494 }
495
496 bool OCResource::operator>(const OCResource &other) const
497 {
498     return m_resourceId > other.m_resourceId;
499 }
500
501 bool OCResource::operator<=(const OCResource &other) const
502 {
503     return m_resourceId <= other.m_resourceId;
504 }
505
506 bool OCResource::operator>=(const OCResource &other) const
507 {
508     return m_resourceId >= other.m_resourceId;
509 }
510
511 OCResourceIdentifier::OCResourceIdentifier(const std::string& wireServerIdentifier,
512         const std::string& resourceUri)
513     :m_representation(wireServerIdentifier), m_resourceUri(resourceUri)
514 {
515 }
516
517 std::ostream& operator <<(std::ostream& os, const OCResourceIdentifier& ri)
518 {
519     os << ri.m_representation<<ri.m_resourceUri;
520
521     return os;
522 }
523
524 bool OCResourceIdentifier::operator==(const OCResourceIdentifier &other) const
525 {
526     return m_representation == other.m_representation
527         && m_resourceUri == other.m_resourceUri;
528 }
529
530 bool OCResourceIdentifier::operator!=(const OCResourceIdentifier &other) const
531 {
532     return !(*this == other);
533 }
534
535 bool OCResourceIdentifier::operator<(const OCResourceIdentifier &other) const
536 {
537     return m_resourceUri < other.m_resourceUri
538         || (m_resourceUri == other.m_resourceUri &&
539                 m_representation < other.m_representation);
540 }
541
542 bool OCResourceIdentifier::operator>(const OCResourceIdentifier &other) const
543 {
544     return *this != other && !(*this<other);
545 }
546
547 bool OCResourceIdentifier::operator<=(const OCResourceIdentifier &other) const
548 {
549     return !(*this > other);
550 }
551
552 bool OCResourceIdentifier::operator>=(const OCResourceIdentifier &other) const
553 {
554     return !(*this < other);
555 }
556
557 } // namespace OC
558