Commit b517d1e7 authored by Mandeep Shetty's avatar Mandeep Shetty Committed by Jon A. Cruz

Modified discovery payload to be spec compliant.

The discovery oic/res payload had the device id "di" and "links"
being repeated for every resource. The payload itself was not structured
in a spec compliant way.

Plucked out di and links from every resource and put in the root map.
The format for the payload is "modelled" as JSON.
[
    {
        "di" : UUID,
        links :[
                    {
                        href, rt, if, policy        // Resource 1
                    },
                    {
                        href, rt, if, policy        // Resource 2
                    },
                    .
                    .
                    .
                ]
    }
]

Change-Id: I2c50a7cc1ee46df633810372e446ac92c5e496f5
Signed-off-by: default avatarMandeep Shetty <mandeep.shetty@intel.com>
Signed-off-by: default avatarJoseph Morrow <joseph.l.morrow@intel.com>
Signed-off-by: default avatarMandeep Shetty <mandeep.shetty@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4543Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: default avatarMarkus Jung <markus.jung85@gmail.com>
Reviewed-by: default avatarJon A. Cruz <jonc@osg.samsung.com>
(cherry picked from commit 69661b0c)
Reviewed-on: https://gerrit.iotivity.org/gerrit/4595
parent adac68d8
......@@ -200,7 +200,9 @@ static OCStackApplicationResult SecurePortDiscoveryCallback(void *ctx, OCDoHandl
//Verifying if the ID of the sender is an AMS service that this device trusts.
if(resPayload &&
memcmp(context->amsMgrContext->amsDeviceId.id, resPayload->sid,
memcmp(context->amsMgrContext->amsDeviceId.id,
((OCDiscoveryPayload*)clientResponse->payload)->sid,
// resPayload->sid,
sizeof(context->amsMgrContext->amsDeviceId.id)) != 0)
{
context->retVal = ACCESS_DENIED_AMS_SERVICE_ERROR;
......
......@@ -1017,7 +1017,6 @@ typedef struct OCRepPayload
typedef struct OCResourcePayload
{
char* uri;
uint8_t* sid;
OCStringLL* types;
OCStringLL* interfaces;
uint8_t bitmap;
......@@ -1111,6 +1110,9 @@ typedef struct OCResourceCollectionPayload
typedef struct
{
OCPayload base;
uint8_t* sid;
/** This structure holds the old /oic/res response. */
OCResourcePayload *resources;
/** This structure holds the collection response for the /oic/res. */
......
......@@ -158,15 +158,14 @@ static inline void OCPayloadLogDiscovery(LogLevel level, OCDiscoveryPayload* pay
OC_LOG(level, PL_TAG, "\tNO Resources");
return;
}
OC_LOG(level, PL_TAG, "\tSID:");
OC_LOG_BUFFER(level, PL_TAG, payload->sid, UUID_SIZE);
OCResourcePayload* res = payload->resources;
while(res)
{
OC_LOG_V(level, PL_TAG, "\tResource #%d", i);
OC_LOG_V(level, PL_TAG, "\tURI:%s", res->uri);
OC_LOG(level, PL_TAG, "\tSID:");
OC_LOG_BUFFER(level, PL_TAG, res->sid, UUID_SIZE);
OC_LOG(level, PL_TAG, "\tResource Types:");
OCStringLL* strll = res->types;
while(strll)
......
......@@ -393,17 +393,23 @@ void queryResource()
void collectUniqueResource(const OCClientResponse * clientResponse)
{
OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
OCDiscoveryPayload* pay = (OCDiscoveryPayload*) clientResponse->payload;
OCResourcePayload* res = pay->resources;
// Including the NUL terminator, length of UUID string of the form:
// "a62389f7-afde-00b6-cd3e-12b97d2fcf09"
# define UUID_LENGTH 37
char sidStr[UUID_LENGTH];
while(res) {
int ret = snprintf(sidStr, UUID_LENGTH,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
res->sid[0], res->sid[1], res->sid[2], res->sid[3],
res->sid[4], res->sid[5], res->sid[6], res->sid[7],
res->sid[8], res->sid[9], res->sid[10], res->sid[11],
res->sid[12], res->sid[13], res->sid[14], res->sid[15]
pay->sid[0], pay->sid[1], pay->sid[2], pay->sid[3],
pay->sid[4], pay->sid[5], pay->sid[6], pay->sid[7],
pay->sid[8], pay->sid[9], pay->sid[10], pay->sid[11],
pay->sid[12], pay->sid[13], pay->sid[14], pay->sid[15]
);
if (ret == UUID_LENGTH - 1)
......
......@@ -1353,13 +1353,12 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
}
pl->uri = OICStrdup(res->uri);
pl->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
if(!pl->uri || ! pl->sid)
if(!pl->uri)
{
FreeOCDiscoveryResource(pl);
return NULL;
}
memcpy(pl->sid, OCGetServerInstanceID(), UUID_SIZE);
// types
OCResourceType* typePtr = res->rsrcType;
......@@ -1574,7 +1573,6 @@ static void FreeOCDiscoveryResource(OCResourcePayload* payload)
}
OICFree(payload->uri);
OICFree(payload->sid);
OCFreeOCStringLL(payload->types);
OCFreeOCStringLL(payload->interfaces);
FreeOCDiscoveryResource(payload->next);
......@@ -1587,7 +1585,7 @@ void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
{
return;
}
OICFree(payload->sid);
FreeOCDiscoveryResource(payload->resources);
OICFree(payload);
}
......
......@@ -283,12 +283,50 @@ static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* o
}
else if (payload->resources)
{
/*
The format for the payload is "modelled" as JSON.
[ // rootArray
{ // rootMap
"di" : UUID, // device ID
links :[ // linksArray contains maps of resources
{
href, rt, if, policy // Resource 1
},
{
href, rt, if, policy // Resource 2
},
.
.
.
]
}
]
*/
CborEncoder rootMap = {};
size_t resourceCount = OCDiscoveryPayloadGetResourceCount(payload);
err = err | cbor_encoder_create_array(&encoder, &rootArray, resourceCount);
// Open the main root array
err = err | cbor_encoder_create_array(&encoder, &rootArray, 1);
// Open the root map in the root array
err = err | cbor_encoder_create_map(&rootArray, &rootMap, DISCOVERY_CBOR_RES_MAP_LEN);
// Insert Device ID into the root map
err = err | cbor_encode_text_string(&rootMap, OC_RSRVD_DEVICE_ID,
sizeof(OC_RSRVD_DEVICE_ID) - 1);
err = err | cbor_encode_byte_string(&rootMap, payload->sid, UUID_SIZE);
// Insert Links into the root map.
CborEncoder linkArray = {};
err = err | cbor_encode_text_string(&rootMap, OC_RSRVD_LINKS,
sizeof(OC_RSRVD_LINKS) - 1);
err = err | cbor_encoder_create_array(&rootMap, &linkArray, resourceCount);
for(size_t i = 0; i < resourceCount; ++i)
{
CborEncoder map;
CborEncoder resourceMapElement = {};
OCResourcePayload* resource = OCDiscoveryPayloadGetResource(payload, i);
if(!resource)
{
......@@ -296,97 +334,85 @@ static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* o
return OC_STACK_INVALID_PARAM;
}
err = err | cbor_encoder_create_map(&rootArray, &map, DISCOVERY_CBOR_RES_MAP_LEN);
// resource map inside the links array.
err = err | cbor_encoder_create_map(&linkArray, &resourceMapElement,
DISCOVERY_CBOR_LINKS_MAP_LEN);
// Below are insertions of the resource properties into the map.
// Uri
err = err | AddTextStringToMap(&resourceMapElement, OC_RSRVD_HREF,
sizeof(OC_RSRVD_HREF) - 1,
resource->uri);
// Resource Type
if (resource->types)
{
char* joinedTypes = OCStringLLJoin(resource->types);
if (joinedTypes)
{
err = err | cbor_encode_text_string(&resourceMapElement, OC_RSRVD_RESOURCE_TYPE,
sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
err = err | cbor_encode_text_string(&resourceMapElement, joinedTypes,
strlen(joinedTypes));
OICFree(joinedTypes);
}
else
{
return OC_STACK_NO_MEMORY;
}
}
// Interface Types
if (resource->interfaces)
{
char* joinedInterfaces = OCStringLLJoin(resource->interfaces);
if (joinedInterfaces)
{
err = err | cbor_encode_text_string(&resourceMapElement, OC_RSRVD_INTERFACE,
sizeof(OC_RSRVD_INTERFACE) - 1);
err = err | cbor_encode_text_string(&resourceMapElement, joinedInterfaces,
strlen(joinedInterfaces));
OICFree(joinedInterfaces);
}
else
{
return OC_STACK_NO_MEMORY;
}
}
// Policy
CborEncoder policyMap;
err = err | cbor_encode_text_string(&resourceMapElement, OC_RSRVD_POLICY,
sizeof(OC_RSRVD_POLICY) - 1);
err = err | cbor_encoder_create_map(&resourceMapElement, &policyMap, CborIndefiniteLength);
// Device ID
err = err | cbor_encode_text_string(&map, OC_RSRVD_DEVICE_ID,
sizeof(OC_RSRVD_DEVICE_ID) - 1);
err = err | cbor_encode_byte_string(&map, resource->sid, UUID_SIZE);
// Bitmap
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
sizeof(OC_RSRVD_BITMAP) - 1);
err = err | cbor_encode_uint(&policyMap, resource->bitmap);
if(resource->secure)
{
CborEncoder linkArray;
err = err | cbor_encode_text_string(&map, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) -1);
err = err | cbor_encoder_create_array(&map, &linkArray, CborIndefiniteLength);
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
sizeof(OC_RSRVD_SECURE) - 1);
err = err | cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
// Link Map
if(resource->port != 0)
{
CborEncoder linkMap;
err = err | cbor_encoder_create_map(&linkArray, &linkMap, DISCOVERY_CBOR_LINKS_MAP_LEN);
// Uri
err = err | AddTextStringToMap(&linkMap, OC_RSRVD_HREF,
sizeof(OC_RSRVD_HREF) - 1,
resource->uri);
// Resource Type
if (resource->types)
{
char* joinedTypes = OCStringLLJoin(resource->types);
if (joinedTypes)
{
err = err | cbor_encode_text_string(&linkMap, OC_RSRVD_RESOURCE_TYPE,
sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
err = err | cbor_encode_text_string(&linkMap, joinedTypes,
strlen(joinedTypes));
OICFree(joinedTypes);
}
else
{
return OC_STACK_NO_MEMORY;
}
}
// Interface Types
if (resource->interfaces)
{
char* joinedInterfaces = OCStringLLJoin(resource->interfaces);
if (joinedInterfaces)
{
err = err | cbor_encode_text_string(&linkMap, OC_RSRVD_INTERFACE,
sizeof(OC_RSRVD_INTERFACE) - 1);
err = err | cbor_encode_text_string(&linkMap, joinedInterfaces,
strlen(joinedInterfaces));
OICFree(joinedInterfaces);
}
else
{
return OC_STACK_NO_MEMORY;
}
}
// Policy
{
CborEncoder policyMap;
err = err | cbor_encode_text_string(&linkMap, OC_RSRVD_POLICY,
sizeof(OC_RSRVD_POLICY) - 1);
err = err | cbor_encoder_create_map(&linkMap, &policyMap, CborIndefiniteLength);
// Bitmap
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
sizeof(OC_RSRVD_BITMAP) - 1);
err = err | cbor_encode_uint(&policyMap, resource->bitmap);
if(resource->secure)
{
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
sizeof(OC_RSRVD_SECURE) - 1);
err = err | cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
if(resource->port != 0)
{
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
sizeof(OC_RSRVD_HOSTING_PORT) - 1);
err = err | cbor_encode_uint(&policyMap, resource->port);
}
}
err = err | cbor_encoder_close_container(&linkMap, &policyMap);
}
// Close
err = err | cbor_encoder_close_container(&linkArray, &linkMap);
err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
sizeof(OC_RSRVD_HOSTING_PORT) - 1);
err = err | cbor_encode_uint(&policyMap, resource->port);
}
err = err | cbor_encoder_close_container(&map, &linkArray);
}
err = err | cbor_encoder_close_container(&rootArray, &map);
err = err | cbor_encoder_close_container(&resourceMapElement, &policyMap);
// Finsihed encoding a resource, close the map.
err = err | cbor_encoder_close_container(&linkArray, &resourceMapElement);
}
// Close main array
// Close links array inside the root map.
err = err | cbor_encoder_close_container(&rootMap, &linkArray);
// close root map inside the root array.
err = err | cbor_encoder_close_container(&rootArray, &rootMap);
// Close the final root array.
err = err | cbor_encoder_close_container(&encoder, &rootArray);
}
......
......@@ -160,6 +160,8 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue*
bool err = false;
OCResourcePayload* resource = NULL;
uint16_t resourceCount = 0;
CborValue resourceMap = {};
OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
if(!out)
......@@ -167,275 +169,219 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue*
return OC_STACK_NO_MEMORY;
}
CborValue arrayVal;
err = err || cbor_value_enter_container(rootValue, &arrayVal);
// Root value is already inside the main root array
CborValue rootMap = {};
if (cbor_value_is_array(&arrayVal))
// Enter the main root map
err = err || cbor_value_enter_container(rootValue, &rootMap);
// Look for DI
CborValue curVal = {};
err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
if (CborNoError != err)
{
OCLinksPayload *linksPayload = NULL;
OCTagsPayload *tagsPayload = NULL;
while (cbor_value_is_container(&arrayVal))
{
linksPayload = NULL;
tagsPayload = NULL;
CborValue colResources;
CborError cborFindResult = cbor_value_enter_container(&arrayVal, &colResources);
if (CborNoError != cborFindResult)
{
goto cbor_error;
}
OC_LOG(ERROR, TAG, "Cbor find value failed.");
goto malformed_cbor;
}
size_t len;
err = cbor_value_dup_byte_string(&curVal, &(out->sid), &len, NULL);
if (OC_STACK_OK != OCTagsCborToPayload(&colResources, &tagsPayload))
{
OC_LOG(ERROR, TAG, "Tags cbor parsing failed.");
OCFreeTagsResource(tagsPayload);
goto cbor_error;
}
// Look for Links which will have an array as the value
err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &curVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor find value failed.");
goto malformed_cbor;
}
if (OC_STACK_OK != OCLinksCborToPayload(&colResources, &linksPayload))
{
OC_LOG(ERROR, TAG, "Links cbor parsing failed.");
OCFreeTagsResource(tagsPayload);
OCFreeLinksResource(linksPayload);
goto cbor_error;
}
// Enter the links array and start iterating through the array processing
// each resource which shows up as a map.
err = err || cbor_value_enter_container(&curVal, &resourceMap);
if (OC_STACK_OK != OCDiscoveryCollectionPayloadAddResource(out, tagsPayload, linksPayload))
{
OC_LOG(ERROR, TAG, "Memory allocation failed");
OCFreeLinksResource(linksPayload);
OCFreeTagsResource(tagsPayload);
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
if (CborNoError != cbor_value_advance(&arrayVal))
{
OC_LOG(ERROR, TAG, "Cbor value advanced failed.");
goto cbor_error;
}
}
}
if (cbor_value_is_map(&arrayVal))
while (cbor_value_is_map(&resourceMap))
{
size_t resourceCount = 0;
while (cbor_value_is_map(&arrayVal))
resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
if(!resource)
{
resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
if(!resource)
{
OC_LOG(ERROR, TAG, "Memory allocation failed");
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
CborValue curVal;
// DI
err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_DEVICE_ID, &curVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor find value failed.");
goto malformed_cbor;
}
size_t len;
err = cbor_value_dup_byte_string(&curVal, &(resource->sid), &len, NULL);
OC_LOG(ERROR, TAG, "Memory allocation failed");
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
// Uri
CborValue uriVal = {};
err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &uriVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding href type failed.");
goto malformed_cbor;
}
err = cbor_value_dup_text_string(&uriVal, &(resource->uri), &len, NULL);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding href value failed.");
goto malformed_cbor;
}
// ResourceTypes
CborValue rtVal = {};
err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &rtVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding rt type failed.");
goto malformed_cbor;
}
if (cbor_value_is_text_string(&rtVal))
{
char* input = NULL;
char* savePtr;
err = cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor di finding failed.");
OC_LOG(ERROR, TAG, "Cbor finding rt value failed.");
goto malformed_cbor;
}
// Links TAG
if (input)
{
CborValue linkArray;
err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_LINKS, &linkArray);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor links finding failed.");
goto malformed_cbor;
}
CborValue linkMap;
err = cbor_value_enter_container(&linkArray, &linkMap);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor entering map failed.");
goto malformed_cbor;
}
// Uri
err = cbor_value_map_find_value(&linkMap, OC_RSRVD_HREF, &curVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding href type failed.");
goto malformed_cbor;
}
err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding href value failed.");
goto malformed_cbor;
}
// ResourceTypes
CborValue rtVal;
err = cbor_value_map_find_value(&linkMap, OC_RSRVD_RESOURCE_TYPE, &rtVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding rt type failed.");
goto malformed_cbor;
}
if (cbor_value_is_text_string(&rtVal))
char* curPtr = strtok_r(input, " ", &savePtr);
while (curPtr)
{
char* input = NULL;
char* savePtr;
err = cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
if (CborNoError != err)
char* trimmed = InPlaceStringTrim(curPtr);
if (trimmed[0] !='\0')
{
OC_LOG(ERROR, TAG, "Cbor finding rt value failed.");
goto malformed_cbor;
}
if (input)
{
char* curPtr = strtok_r(input, " ", &savePtr);
while (curPtr)
if (!OCResourcePayloadAddResourceType(resource, trimmed))
{
char* trimmed = InPlaceStringTrim(curPtr);
if (trimmed[0] !='\0')
{
if (!OCResourcePayloadAddResourceType(resource, trimmed))
{
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
OICFree(resource);
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
}
curPtr = strtok_r(NULL, " ", &savePtr);
OICFree(resource->uri);
OCFreeOCStringLL(resource->types);
OICFree(resource);
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
OICFree(input);
}
curPtr = strtok_r(NULL, " ", &savePtr);
}
OICFree(input);
}
}
// Interface Types
CborValue ifVal;
err = cbor_value_map_find_value(&linkMap, OC_RSRVD_INTERFACE, &ifVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding if type failed.");
goto malformed_cbor;
}
if (!err && cbor_value_is_text_string(&ifVal))
{
char* input = NULL;
char* savePtr;
err = cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding if value failed.");
goto malformed_cbor;
}
if (input)
{
char* curPtr = strtok_r(input, " ", &savePtr);
// Interface Types
CborValue ifVal = {};
err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_INTERFACE, &ifVal);
if (CborNoError != err)
{
OC_LOG(ERROR, TAG, "Cbor finding if type failed.");
goto malformed_cbor;
}
if (!err && cbor_value_is_text_string(&ifVal))
{
char* input = NULL;
char* savePtr;
err = cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
if (CborNoError != err)
{
OC_LOG(ERROR