Fixed error on Host copying
[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
105     this->setHost(host);
106 }
107
108 OCResource::~OCResource()
109 {
110 }
111
112 void OCResource::setHost(const std::string& host)
113 {
114     size_t prefix_len;
115
116     if(host.compare(0, sizeof(COAP) - 1, COAP) == 0)
117     {
118         prefix_len = sizeof(COAP) - 1;
119     }
120     else if(host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
121     {
122         prefix_len = sizeof(COAPS) - 1;
123         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_SECURE);
124     }
125 #ifdef TCP_ADAPTER
126     else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
127     {
128         prefix_len = sizeof(COAP_TCP) - 1;
129         m_devAddr.adapter = static_cast<OCTransportAdapter>(m_devAddr.adapter & OC_ADAPTER_TCP);
130     }
131 #endif
132     else
133     {
134         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
135             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
136     }
137
138     // removed coap:// or coaps:// or coap+tcp://
139     std::string host_token = host.substr(prefix_len);
140
141     if(host_token[0] == '[')
142     {
143         m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_IP_USE_V6);
144
145         size_t found = host_token.find(']');
146
147         if(found == std::string::npos || found == 0)
148         {
149             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
150                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
151         }
152         // extract the ipaddress
153         std::string ip6Addr = host_token.substr(1, found-1);
154
155         if (ip6Addr.length() >= MAX_ADDR_STR_SIZE)
156         {
157             throw std::length_error("host address is too long.");
158         }
159
160         ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
161         m_devAddr.addr[ip6Addr.length()] = '\0';
162         //skip ']' and ':' characters in host string
163         host_token = host_token.substr(found + 2);
164     }
165     else
166     {
167         size_t found = host_token.find(':');
168
169         if(found == std::string::npos || found == 0)
170         {
171             throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
172                 m_interfaces.empty(), m_clientWrapper.expired(), false, false);
173         }
174
175         std::string addrPart = host_token.substr(0, found);
176
177         if (addrPart.length() >= MAX_ADDR_STR_SIZE)
178         {
179             throw std::length_error("host address is too long.");
180         }
181
182         addrPart.copy(m_devAddr.addr, sizeof(m_devAddr.addr));
183         m_devAddr.addr[addrPart.length()] = '\0';
184         //skip ':' character in host string
185         host_token = host_token.substr(found + 1);
186     }
187
188     int port = std::stoi(host_token);
189
190     if( port < 0 || port > UINT16_MAX )
191     {
192         throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
193             m_interfaces.empty(), m_clientWrapper.expired(), false, false);
194     }
195
196     m_devAddr.port = static_cast<uint16_t>(port);
197
198 }
199
200 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
201                               GetCallback attributeHandler, QualityOfService QoS)
202 {
203     return checked_guard(m_clientWrapper.lock(),
204                             &IClientWrapper::GetResourceRepresentation,
205                             m_devAddr, m_uri,
206                             queryParametersMap, m_headerOptions,
207                             attributeHandler, QoS);
208 }
209
210 OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
211                               GetCallback attributeHandler)
212 {
213     QualityOfService defaultQos = OC::QualityOfService::NaQos;
214     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
215     return result_guard(get(queryParametersMap, attributeHandler, defaultQos));
216 }
217
218 OCStackResult OCResource::get(const std::string& resourceType,
219                      const std::string& resourceInterface, const QueryParamsMap& queryParametersMap,
220                      GetCallback attributeHandler)
221 {
222     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
223     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
224
225     return result_guard(get(resourceType, resourceInterface, queryParametersMap, attributeHandler, defaultQoS));
226 }
227
228 OCStackResult OCResource::get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
229         QualityOfService QoS)
230 {
231     QueryParamsMap mapCpy(queryParametersMap);
232
233     if(!resourceType.empty())
234     {
235         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
236     }
237
238     if(!resourceInterface.empty())
239     {
240         mapCpy[OC::Key::INTERFACESKEY]= resourceInterface;
241     }
242
243     return result_guard(get(mapCpy, attributeHandler, QoS));
244 }
245
246 OCStackResult OCResource::put(const OCRepresentation& rep,
247                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler,
248                               QualityOfService QoS)
249 {
250     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation,
251                          m_devAddr, m_uri, rep, queryParametersMap,
252                          m_headerOptions, attributeHandler, QoS);
253 }
254
255 OCStackResult OCResource::put(const OCRepresentation& rep,
256                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
257 {
258     QualityOfService defaultQos = OC::QualityOfService::NaQos;
259     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
260     return result_guard(put(rep, queryParametersMap, attributeHandler, defaultQos));
261 }
262
263 OCStackResult OCResource::put(const std::string& resourceType,
264                               const std::string& resourceInterface, const OCRepresentation& rep,
265                               const QueryParamsMap& queryParametersMap,
266                               PutCallback attributeHandler)
267 {
268     QualityOfService defaultQos = OC::QualityOfService::NaQos;
269     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
270
271     return result_guard(put(resourceType, resourceInterface, rep, queryParametersMap,
272             attributeHandler, defaultQos));
273 }
274
275 OCStackResult OCResource::put(const std::string& resourceType,
276                               const std::string& resourceInterface, const OCRepresentation& rep,
277                               const QueryParamsMap& queryParametersMap,
278                               PutCallback attributeHandler,
279                               QualityOfService QoS)
280 {
281     QueryParamsMap mapCpy(queryParametersMap);
282
283     if(!resourceType.empty())
284     {
285         mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType;
286     }
287
288     if(!resourceInterface.empty())
289     {
290         mapCpy[OC::Key::INTERFACESKEY]=resourceInterface;
291     }
292
293     return result_guard(put(rep, mapCpy, attributeHandler, QoS));
294 }
295
296 OCStackResult OCResource::post(const OCRepresentation& rep,
297                                const QueryParamsMap& queryParametersMap, PostCallback attributeHandler,
298                                QualityOfService QoS)
299 {
300     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
301                          m_devAddr, m_uri, rep, queryParametersMap,
302                          m_headerOptions, attributeHandler, QoS);
303 }
304
305 OCStackResult OCResource::post(const OCRepresentation& rep,
306                               const QueryParamsMap& queryParametersMap, PutCallback attributeHandler)
307 {
308     QualityOfService defaultQos = OC::QualityOfService::NaQos;
309     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
310     return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
311 }
312
313 OCStackResult OCResource::post(const std::string& resourceType,
314                                const std::string& resourceInterface, const OCRepresentation& rep,
315                                const QueryParamsMap& queryParametersMap,
316                                PostCallback attributeHandler)
317 {
318     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
319     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
320
321     return result_guard(post(resourceType, resourceInterface, rep, queryParametersMap, attributeHandler,
322             defaultQoS));
323 }
324
325 OCStackResult OCResource::post(const std::string& resourceType,
326                                const std::string& resourceInterface, const OCRepresentation& rep,
327                                const QueryParamsMap& queryParametersMap,
328                                PostCallback 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(post(rep, mapCpy, attributeHandler, QoS));
344 }
345
346 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler, QualityOfService QoS)
347 {
348     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
349                          m_devAddr, m_uri, m_headerOptions, deleteHandler, QoS);
350 }
351
352 OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler)
353 {
354     QualityOfService defaultQos = OC::QualityOfService::NaQos;
355     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
356
357     return result_guard(deleteResource(deleteHandler, defaultQos));
358 }
359
360 OCStackResult OCResource::observe(ObserveType observeType,
361         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler,
362         QualityOfService QoS)
363 {
364     if(m_observeHandle != nullptr)
365     {
366         return result_guard(OC_STACK_INVALID_PARAM);
367     }
368
369     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
370                          observeType, &m_observeHandle, m_devAddr,
371                          m_uri, queryParametersMap, m_headerOptions,
372                          observeHandler, QoS);
373 }
374
375 OCStackResult OCResource::observe(ObserveType observeType,
376         const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
377 {
378     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
379     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
380
381     return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
382 }
383
384 OCStackResult OCResource::cancelObserve()
385 {
386     QualityOfService defaultQoS = OC::QualityOfService::NaQos;
387     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
388     return result_guard(cancelObserve(defaultQoS));
389 }
390
391 OCStackResult OCResource::cancelObserve(QualityOfService QoS)
392 {
393     if(m_observeHandle == nullptr)
394     {
395         return result_guard(OC_STACK_INVALID_PARAM);
396     }
397
398     OCStackResult result =  checked_guard(m_clientWrapper.lock(),
399             &IClientWrapper::CancelObserveResource,
400             m_observeHandle, "", m_uri, m_headerOptions, QoS);
401
402     if(result == OC_STACK_OK)
403     {
404         m_observeHandle = nullptr;
405     }
406
407     return result;
408 }
409
410 std::string OCResource::host() const
411 {
412     std::ostringstream ss;
413     if (m_devAddr.flags & OC_SECURE)
414     {
415         ss << COAPS;
416     }
417 #ifdef TCP_ADAPTER
418     else if (m_devAddr.adapter & OC_ADAPTER_TCP)
419     {
420         ss << COAP_TCP;
421     }
422 #endif
423     else
424     {
425         ss << COAP;
426     }
427     if (m_devAddr.flags & OC_IP_USE_V6)
428     {
429         ss << '[' << m_devAddr.addr << ']';
430     }
431     else
432     {
433         ss << m_devAddr.addr;
434     }
435     if (m_devAddr.port)
436     {
437         ss << ':' << m_devAddr.port;
438     }
439     return ss.str();
440 }
441
442 std::string OCResource::uri() const
443 {
444     return m_uri;
445 }
446
447 OCConnectivityType OCResource::connectivityType() const
448 {
449     return static_cast<OCConnectivityType>(
450            (m_devAddr.adapter << CT_ADAPTER_SHIFT) | (m_devAddr.flags & CT_MASK_FLAGS));
451 }
452
453 bool OCResource::isObservable() const
454 {
455     return m_isObservable;
456 }
457
458 OCResourceIdentifier OCResource::uniqueIdentifier() const
459 {
460     return m_resourceId;
461 }
462
463 std::string OCResource::sid() const
464 {
465     return this->uniqueIdentifier().m_representation;
466 }
467
468 bool OCResource::operator==(const OCResource &other) const
469 {
470     return m_resourceId == other.m_resourceId;
471 }
472
473 bool OCResource::operator!=(const OCResource &other) const
474 {
475     return m_resourceId != other.m_resourceId;
476 }
477
478 bool OCResource::operator<(const OCResource &other) const
479 {
480     return m_resourceId < other.m_resourceId;
481 }
482
483 bool OCResource::operator>(const OCResource &other) const
484 {
485     return m_resourceId > other.m_resourceId;
486 }
487
488 bool OCResource::operator<=(const OCResource &other) const
489 {
490     return m_resourceId <= other.m_resourceId;
491 }
492
493 bool OCResource::operator>=(const OCResource &other) const
494 {
495     return m_resourceId >= other.m_resourceId;
496 }
497
498 OCResourceIdentifier::OCResourceIdentifier(const std::string& wireServerIdentifier,
499         const std::string& resourceUri)
500     :m_representation(wireServerIdentifier), m_resourceUri(resourceUri)
501 {
502 }
503
504 std::ostream& operator <<(std::ostream& os, const OCResourceIdentifier& ri)
505 {
506     os << ri.m_representation<<ri.m_resourceUri;
507
508     return os;
509 }
510
511 bool OCResourceIdentifier::operator==(const OCResourceIdentifier &other) const
512 {
513     return m_representation == other.m_representation
514         && m_resourceUri == other.m_resourceUri;
515 }
516
517 bool OCResourceIdentifier::operator!=(const OCResourceIdentifier &other) const
518 {
519     return !(*this == other);
520 }
521
522 bool OCResourceIdentifier::operator<(const OCResourceIdentifier &other) const
523 {
524     return m_resourceUri < other.m_resourceUri
525         || (m_resourceUri == other.m_resourceUri &&
526                 m_representation < other.m_representation);
527 }
528
529 bool OCResourceIdentifier::operator>(const OCResourceIdentifier &other) const
530 {
531     return *this != other && !(*this<other);
532 }
533
534 bool OCResourceIdentifier::operator<=(const OCResourceIdentifier &other) const
535 {
536     return !(*this > other);
537 }
538
539 bool OCResourceIdentifier::operator>=(const OCResourceIdentifier &other) const
540 {
541     return !(*this < other);
542 }
543
544 } // namespace OC
545