#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);
OCRepPayload* root = nullptr;
for(const auto& r : representations())
{
- if(!root)
+ if (!root)
{
root = r.getPayload();
}
struct get_payload_array: boost::static_visitor<>
{
template<typename T>
- void operator()(T& arr)
+ void operator()(T& /*arr*/)
{
throw std::logic_error("Invalid calc_dimensions_visitor type");
}
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
dimTotal = calcDimTotal(dimensions);
array = (void*)OICMalloc(dimTotal * root_size);
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
for(size_t i = 0; i < arr.size(); ++i)
{
dimensions[1] = std::max(dimensions[1], arr[i].size());
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
for(size_t i = 0; i < arr.size(); ++i)
{
dimensions[1] = std::max(dimensions[1], arr[i].size());
((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)
+ {
+ ((char**)array)[pos] = OICStrdup(item.c_str());
+ }
+
+ template<>
+ void get_payload_array::copy_to_array(std::string& item, void* array, size_t pos)
+ {
+ ((char**)array)[pos] = OICStrdup(item.c_str());
+ }
template<>
void get_payload_array::copy_to_array(const std::string& item, void* array, size_t pos)
}
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();
(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);
OCRepPayload* OCRepresentation::getPayload() const
{
OCRepPayload* root = OCRepPayloadCreate();
- if(!root)
+ if (!root)
{
throw std::bad_alloc();
}
OCRepPayloadSetPropInt(root, val.attrname().c_str(), static_cast<int>(val));
break;
case AttributeType::Double:
- OCRepPayloadSetPropDouble(root, val.attrname().c_str(), val);
+ OCRepPayloadSetPropDouble(root, val.attrname().c_str(),
+ val.getValue<double>());
break;
case AttributeType::Boolean:
- OCRepPayloadSetPropBool(root, val.attrname().c_str(), val);
+ OCRepPayloadSetPropBool(root, val.attrname().c_str(), val.getValue<bool>());
break;
case AttributeType::String:
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());
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()));
}
}
- OCRepPayload* cur = root;
- for(auto& child : this->getChildren())
- {
- cur->next = child.getPayload();
- cur = cur->next;
- }
-
return root;
}
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;
}
std::string OCRepresentation::payload_array_helper_copy<std::string>(
size_t index, const OCRepPayloadValue* pl)
{
- return std::string(pl->arr.strArray[index]);
+ if (pl->arr.strArray[index])
+ {
+ return std::string(pl->arr.strArray[index]);
+ }
+ else
+ {
+ 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)
{
OCRepresentation r;
- r.setPayload(pl->arr.objArray[index]);
+ if (pl->arr.objArray[index])
+ {
+ r.setPayload(pl->arr.objArray[index]);
+ }
return r;
}
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]);
std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
{
- val[i].reserve(pl->arr.dimensions[1]);
+ val[i].resize(pl->arr.dimensions[1]);
for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
{
val[i][j] = payload_array_helper_copy<T>(
}
else if (depth == 3)
{
- std::vector<std::vector<std::vector<T>>> val;
+ std::vector<std::vector<std::vector<T>>> val(pl->arr.dimensions[0]);
for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
{
- val[i].reserve(pl->arr.dimensions[1]);
+ val[i].resize(pl->arr.dimensions[1]);
for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
{
- val[i][j].reserve(pl->arr.dimensions[2]);
+ val[i][j].resize(pl->arr.dimensions[2]);
for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
{
val[i][j][k] = payload_array_helper_copy<T>(
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;
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));
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 : "";
+ }
+
void OCRepresentation::setUri(const std::string& uri)
{
m_uri = uri;
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();
// 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)
return false;
}
- if(m_children.size() > 0)
+ if (m_children.size() > 0)
{
return false;
}
{
auto x = m_values.find(str);
- if(m_values.end() != x)
+ if (m_values.end() != x)
{
return x->second.which() == AttributeValueNullIndex;
}
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;
}
// 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;
type(AttributeType::Null), base_type(AttributeType::Null), depth(0){}
template <typename T>
- void operator()(T const& item)
+ void operator()(T const& /*item*/)
{
type = type_info<T>::enum_type;
base_type = type_info<T>::enum_base_type;
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;
}
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;
}
}
template<>
- void to_string_visitor::operator()(NullType const& item)
+ void to_string_visitor::operator()(NullType const& /*item*/)
{
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)
+ void to_string_visitor::operator()(OCRepresentation const& /*item*/)
{
str = "OC::OCRepresentation";
}
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);
return os;
}
}
-