replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / src / OCRepresentation.cpp
index 315f83b..3d42719 100644 (file)
 
 #include <boost/lexical_cast.hpp>
 #include <algorithm>
+#include <iomanip>
 #include "ocpayload.h"
 #include "ocrandom.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include "ocstack.h"
 
 namespace OC
 {
+    static const char COAP[] = "coap://";
+    static const char COAPS[] = "coaps://";
+    static const char COAP_TCP[] = "coap+tcp://";
 
     void MessageContainer::setPayload(const OCPayload* rep)
     {
+        if (rep == nullptr)
+        {
+            return;
+        }
+
         switch(rep->type)
         {
             case PAYLOAD_TYPE_REPRESENTATION:
                 setPayload(reinterpret_cast<const OCRepPayload*>(rep));
                 break;
-            case PAYLOAD_TYPE_DEVICE:
-                setPayload(reinterpret_cast<const OCDevicePayload*>(rep));
-                break;
-            case PAYLOAD_TYPE_PLATFORM:
-                setPayload(reinterpret_cast<const OCPlatformPayload*>(rep));
-                break;
             default:
                 throw OC::OCException("Invalid Payload type in setPayload");
                 break;
         }
     }
 
-    void MessageContainer::setPayload(const OCDevicePayload* payload)
-    {
-        OCRepresentation rep;
-        rep.setUri(payload->uri);
-        char uuidString[UUID_STRING_SIZE];
-        if(payload->sid && RAND_UUID_OK == OCConvertUuidToString(payload->sid, uuidString))
-        {
-            rep[OC_RSRVD_DEVICE_ID] = std::string(uuidString);
-        }
-        else
-        {
-            rep[OC_RSRVD_DEVICE_ID] = std::string();
-        }
-        rep[OC_RSRVD_DEVICE_NAME] = payload->deviceName ?
-            std::string(payload->deviceName) :
-            std::string();
-        rep[OC_RSRVD_SPEC_VERSION] = payload->specVersion ?
-            std::string(payload->specVersion) :
-            std::string();
-        rep[OC_RSRVD_DATA_MODEL_VERSION] = payload->dataModelVersion ?
-            std::string(payload->dataModelVersion) :
-            std::string();
-        m_reps.push_back(std::move(rep));
-    }
-
-    void MessageContainer::setPayload(const OCPlatformPayload* payload)
-    {
-        OCRepresentation rep;
-        rep.setUri(payload->uri);
-
-        rep[OC_RSRVD_PLATFORM_ID] = payload->info.platformID ?
-            std::string(payload->info.platformID) :
-            std::string();
-        rep[OC_RSRVD_MFG_NAME] = payload->info.manufacturerName ?
-            std::string(payload->info.manufacturerName) :
-            std::string();
-        rep[OC_RSRVD_MFG_URL] = payload->info.manufacturerUrl ?
-            std::string(payload->info.manufacturerUrl) :
-            std::string();
-        rep[OC_RSRVD_MODEL_NUM] = payload->info.modelNumber ?
-            std::string(payload->info.modelNumber) :
-            std::string();
-        rep[OC_RSRVD_MFG_DATE] = payload->info.dateOfManufacture ?
-            std::string(payload->info.dateOfManufacture) :
-            std::string();
-        rep[OC_RSRVD_PLATFORM_VERSION] = payload->info.platformVersion ?
-            std::string(payload->info.platformVersion) :
-            std::string();
-        rep[OC_RSRVD_OS_VERSION] = payload->info.operatingSystemVersion ?
-            std::string(payload->info.operatingSystemVersion) :
-            std::string();
-        rep[OC_RSRVD_HARDWARE_VERSION] = payload->info.hardwareVersion ?
-            std::string(payload->info.hardwareVersion) :
-            std::string();
-        rep[OC_RSRVD_FIRMWARE_VERSION] = payload->info.firmwareVersion ?
-            std::string(payload->info.firmwareVersion) :
-            std::string();
-        rep[OC_RSRVD_SUPPORT_URL] = payload->info.supportUrl ?
-            std::string(payload->info.supportUrl) :
-            std::string();
-        rep[OC_RSRVD_SYSTEM_TIME] = payload->info.systemTime ?
-            std::string(payload->info.systemTime) :
-            std::string();
-
-        m_reps.push_back(std::move(rep));
-    }
-
     void MessageContainer::setPayload(const OCRepPayload* payload)
     {
         const OCRepPayload* pl = payload;
-        while(pl)
+        while (pl)
         {
             OCRepresentation cur;
             cur.setPayload(pl);
@@ -142,7 +79,7 @@ namespace OC
         OCRepPayload* root = nullptr;
         for(const auto& r : representations())
         {
-            if(!root)
+            if (!root)
             {
                 root = r.getPayload();
             }
@@ -292,11 +229,13 @@ namespace OC
         ((int64_t*)array)[pos] = item;
     }
 
+#if !(defined(_MSC_VER) || defined(__APPLE__))
     template<>
     void get_payload_array::copy_to_array(std::_Bit_reference br, void* array, size_t pos)
     {
         ((bool*)array)[pos] = static_cast<bool>(br);
     }
+#endif
 
     template<>
     void get_payload_array::copy_to_array(std::string item, void* array, size_t pos)
@@ -317,6 +256,24 @@ namespace OC
     }
 
     template<>
+    void get_payload_array::copy_to_array(OCByteString item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(OCByteString &item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(const OCByteString &item, void *array, size_t pos)
+    {
+        ((OCByteString *)array)[pos] = item;
+    }
+
+    template<>
     void get_payload_array::copy_to_array(OC::OCRepresentation item, void* array, size_t pos)
     {
         ((OCRepPayload**)array)[pos] = item.getPayload();
@@ -351,6 +308,10 @@ namespace OC
                         (char**)vis.array,
                         vis.dimensions);
                 break;
+            case AttributeType::OCByteString:
+                OCRepPayloadSetByteStringArrayAsOwner(payload, item.attrname().c_str(),
+                                                      (OCByteString *)vis.array, vis.dimensions);
+                break;
             case AttributeType::OCRepresentation:
                 OCRepPayloadSetPropObjectArrayAsOwner(payload, item.attrname().c_str(),
                         (OCRepPayload**)vis.array, vis.dimensions);
@@ -364,7 +325,7 @@ namespace OC
     OCRepPayload* OCRepresentation::getPayload() const
     {
         OCRepPayload* root = OCRepPayloadCreate();
-        if(!root)
+        if (!root)
         {
             throw std::bad_alloc();
         }
@@ -402,6 +363,9 @@ namespace OC
                     OCRepPayloadSetPropString(root, val.attrname().c_str(),
                             static_cast<std::string>(val).c_str());
                     break;
+                case AttributeType::OCByteString:
+                    OCRepPayloadSetPropByteString(root, val.attrname().c_str(), val.getValue<OCByteString>());
+                    break;
                 case AttributeType::OCRepresentation:
                     OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(),
                             static_cast<OCRepresentation>(val).getPayload());
@@ -409,6 +373,11 @@ namespace OC
                 case AttributeType::Vector:
                     getPayloadArray(root, val);
                     break;
+                case AttributeType::Binary:
+                    OCRepPayloadSetPropByteString(root, val.attrname().c_str(),
+                            OCByteString{const_cast<uint8_t*>(val.getValue<std::vector<uint8_t>>().data()),
+                            val.getValue<std::vector<uint8_t>>().size()});
+                    break;
                 default:
                     throw std::logic_error(std::string("Getpayload: Not Implemented") +
                             std::to_string((int)val.type()));
@@ -421,11 +390,11 @@ namespace OC
 
     size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
     {
-        if(dimensions[0] == 0)
+        if (dimensions[0] == 0)
         {
             throw std::logic_error("invalid calcArrayDepth");
         }
-        else if(dimensions[1] == 0)
+        else if (dimensions[1] == 0)
         {
             return 1;
         }
@@ -472,6 +441,19 @@ namespace OC
             return std::string{};
         }
     }
+
+    template<>
+    OCByteString OCRepresentation::payload_array_helper_copy<OCByteString>(
+        size_t index, const OCRepPayloadValue *pl)
+    {
+        OCByteString result {NULL, 0};
+        if (pl->arr.ocByteStrArray[index].len)
+        {
+            result = (pl->arr.ocByteStrArray[index]);
+        }
+        return result;
+    }
+
     template<>
     OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
             size_t index, const OCRepPayloadValue* pl)
@@ -487,7 +469,7 @@ namespace OC
     template<typename T>
     void OCRepresentation::payload_array_helper(const OCRepPayloadValue* pl, size_t depth)
     {
-        if(depth == 1)
+        if (depth == 1)
         {
             std::vector<T> val(pl->arr.dimensions[0]);
 
@@ -555,6 +537,9 @@ namespace OC
             case OCREP_PROP_STRING:
                 payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
                 break;
+            case OCREP_PROP_BYTE_STRING:
+                payload_array_helper<OCByteString>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
             case OCREP_PROP_OBJECT:
                 payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
                 break;
@@ -613,6 +598,12 @@ namespace OC
                 case OCREP_PROP_ARRAY:
                     setPayloadArray(val);
                     break;
+                case OCREP_PROP_BYTE_STRING:
+                    setValue(val->name,
+                            std::vector<uint8_t>
+                            (val->ocByteStr.bytes, val->ocByteStr.bytes + val->ocByteStr.len)
+                            );
+                    break;
                 default:
                     throw std::logic_error(std::string("Not Implemented!") +
                             std::to_string((int)val->type));
@@ -641,6 +632,51 @@ namespace OC
     {
         m_children = children;
     }
+
+    void OCRepresentation::setDevAddr(const OCDevAddr& devAddr)
+    {
+        std::ostringstream ss;
+        if (devAddr.flags & OC_SECURE)
+        {
+            ss << COAPS;
+        }
+        else if (devAddr.adapter & OC_ADAPTER_TCP)
+        {
+            ss << COAP_TCP;
+        }
+        else
+        {
+            ss << COAP;
+        }
+        if (devAddr.flags & OC_IP_USE_V6)
+        {
+            char addressEncoded[128] = {0};
+
+            OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
+                                                             sizeof(addressEncoded),
+                                                             devAddr.addr);
+            if (OC_STACK_OK != result)
+            {
+                throw OC::OCException("Invalid address in setDevAddr");
+            }
+            ss << '[' << addressEncoded << ']';
+        }
+        else
+        {
+            ss << devAddr.addr;
+        }
+        if (devAddr.port)
+        {
+            ss << ':' << devAddr.port;
+        }
+        m_host = ss.str();
+    }
+
+    const std::string OCRepresentation::getHost() const
+    {
+        return m_host;
+    }
+
     void OCRepresentation::setUri(const char* uri)
     {
         m_uri = uri ? uri : "";
@@ -686,6 +722,16 @@ namespace OC
         m_interfaces = resourceInterfaces;
     }
 
+    const std::vector<std::string>& OCRepresentation::getDataModelVersions() const
+    {
+        return m_dataModelVersions;
+    }
+
+    void OCRepresentation::addDataModelVersion(const std::string& str)
+    {
+        m_dataModelVersions.push_back(str);
+    }
+
     bool OCRepresentation::hasAttribute(const std::string& str) const
     {
         return m_values.find(str) != m_values.end();
@@ -699,18 +745,19 @@ namespace OC
         // child of a default or link item.
         // Our values array is only printed in the if we are the child of a Batch resource,
         // the parent in a 'default' situation, or not in a child/parent relationship.
-        if(!m_uri.empty())
+        if (!m_uri.empty())
         {
             return false;
         }
         else if ((m_interfaceType == InterfaceType::None
                         || m_interfaceType==InterfaceType::DefaultChild
                         || m_interfaceType==InterfaceType::LinkChild)
-                    && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+                    && (m_resourceTypes.size()>0 || m_interfaces.size()>0
+                        || m_dataModelVersions.size()>0))
         {
             return false;
         }
-        else if((m_interfaceType == InterfaceType::None
+        else if ((m_interfaceType == InterfaceType::None
                         || m_interfaceType == InterfaceType::BatchChild
                         || m_interfaceType == InterfaceType::DefaultParent)
                     && m_values.size()>0)
@@ -718,7 +765,7 @@ namespace OC
             return false;
         }
 
-        if(m_children.size() > 0)
+        if (m_children.size() > 0)
         {
             return false;
         }
@@ -745,7 +792,7 @@ namespace OC
     {
         auto x = m_values.find(str);
 
-        if(m_values.end() != x)
+        if (m_values.end() != x)
         {
             return x->second.which() == AttributeValueNullIndex;
         }
@@ -777,12 +824,17 @@ namespace OC
             case AttributeType::String:
                 os << "String";
                 break;
+            case AttributeType::OCByteString:
+                os << "OCByteString";
+                break;
             case AttributeType::OCRepresentation:
                 os << "OCRepresentation";
                 break;
             case AttributeType::Vector:
                 os << "Vector";
                 break;
+            case AttributeType::Binary:
+                os<< "Binary";
         }
         return os;
     }
@@ -820,27 +872,45 @@ namespace OC
         // contains the inner most vector-type
         typedef T base_type;
         // contains the AttributeType for this item
-        constexpr static AttributeType enum_type =
+        BOOST_STATIC_CONSTEXPR AttributeType enum_type =
             AttributeTypeConvert<T>::type;
         // contains the AttributeType for this base-type
-        constexpr static AttributeType enum_base_type =
+        BOOST_STATIC_CONSTEXPR AttributeType enum_base_type =
             AttributeTypeConvert<T>::type;
         // depth of the vector
-        constexpr static size_t depth = 0;
+        BOOST_STATIC_CONSTEXPR size_t depth = 0;
     };
 
     template<typename T>
-    struct type_info<T, typename std::enable_if<is_vector<T>::value>::type>
+    struct type_info<
+        T,
+        typename std::enable_if<
+            is_vector<T>::value &&
+            !std::is_same<uint8_t, typename T::value_type>::value
+        >::type
+    >
     {
         typedef T type;
         typedef typename type_info<typename T::value_type>::base_type base_type;
-        constexpr static AttributeType enum_type = AttributeType::Vector;
-        constexpr static AttributeType enum_base_type =
+        BOOST_STATIC_CONSTEXPR AttributeType enum_type = AttributeType::Vector;
+        BOOST_STATIC_CONSTEXPR AttributeType enum_base_type =
             type_info<typename T::value_type>::enum_base_type;
-        constexpr static size_t depth = 1 +
+        BOOST_STATIC_CONSTEXPR size_t depth = 1 +
             type_info<typename T::value_type>::depth;
     };
 
+    // special case for binary data, which is a std::vector<uint8_t>
+    template<>
+    struct type_info<std::vector<uint8_t>, void>
+    {
+        typedef std::vector<uint8_t> type;
+        typedef std::vector<uint8_t> base_type;
+        BOOST_STATIC_CONSTEXPR AttributeType enum_type = AttributeType::Binary;
+        BOOST_STATIC_CONSTEXPR AttributeType enum_base_type = AttributeType::Binary;
+        BOOST_STATIC_CONSTEXPR size_t depth = 0;
+    };
+
+
     struct type_introspection_visitor : boost::static_visitor<>
     {
         AttributeType type;
@@ -967,7 +1037,7 @@ namespace OC
     OCRepresentation::iterator& OCRepresentation::iterator::operator++()
     {
         m_iterator++;
-        if(m_iterator != m_item.m_values.end())
+        if (m_iterator != m_item.m_values.end())
         {
             m_item.m_attrName = m_iterator->first;
         }
@@ -981,7 +1051,7 @@ namespace OC
     OCRepresentation::const_iterator& OCRepresentation::const_iterator::operator++()
     {
         m_iterator++;
-        if(m_iterator != m_item.m_values.end())
+        if (m_iterator != m_item.m_values.end())
         {
             m_item.m_attrName = m_iterator->first;
         }
@@ -1050,6 +1120,24 @@ namespace OC
         str = "(null)";
     }
 
+    template <>
+    void to_string_visitor::operator()(std::vector<uint8_t> const &item)
+    {
+        std::ostringstream stream;
+        for (size_t i = 0; i < item.size(); i++ )
+        {
+            stream << "\\x" << std::hex << (int) item[i];
+        }
+        str = stream.str();
+    }
+
+    template<>
+    void to_string_visitor::operator()(OCByteString const &item)
+    {
+        std::vector<uint8_t> v(item.bytes, item.bytes + item.len);
+        operator()(v);
+    }
+
     template<>
     void to_string_visitor::operator()(OCRepresentation const& /*item*/)
     {
@@ -1059,7 +1147,7 @@ namespace OC
     std::string OCRepresentation::getValueToString(const std::string& key) const
     {
         auto x = m_values.find(key);
-        if(x != m_values.end())
+        if (x != m_values.end())
         {
             to_string_visitor vis;
             boost::apply_visitor(vis, x->second);
@@ -1082,4 +1170,3 @@ namespace OC
         return os;
     }
 }
-