Commit e9d05107 authored by Srikrishna Gurugubelli's avatar Srikrishna Gurugubelli Committed by Dan Mihai

[IOT-1965] Introspection update to follow spec

Change-Id: I5e6c0d1a016e409429498835587c73d5ef0b7fea
Signed-off-by: default avatarSrikrishna Gurugubelli <srikguru@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19513Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarDan Mihai <Daniel.Mihai@microsoft.com>
parent ffdae2ee
......@@ -77,12 +77,6 @@ extern "C" {
/** KeepAlive URI.*/
#define OC_RSRVD_KEEPALIVE_URI "/oic/ping"
/** Introspection URI.*/
#define OC_RSRVD_INTROSPECTION_URI "/oic/introspection"
/** Introspection payload URI.*/
#define OC_RSRVD_INTROSPECTION_PAYLOAD_URI "/oic/introspection/payload"
/** Presence */
/** Presence URI through which the OIC devices advertise their presence.*/
......@@ -367,11 +361,8 @@ extern "C" {
/** Version property value.*/
#define OC_RSRVD_INTROSPECTION_VERSION_VALUE 1
/** Introspection payload data property name.*/
#define OC_RSRVD_INTROSPECTION_DATA_NAME "data"
/** Introspection persistent store name.*/
#define OC_INTROSPECTION_FILE_NAME "introspection.json"
#define OC_INTROSPECTION_FILE_NAME "introspection.dat"
/**
* These provide backward compatibility - their use is deprecated.
......@@ -1419,7 +1410,9 @@ typedef enum
/** The payload is an OCPresencePayload */
PAYLOAD_TYPE_PRESENCE,
/** The payload is an OCDiagnosticPayload */
PAYLOAD_TYPE_DIAGNOSTIC
PAYLOAD_TYPE_DIAGNOSTIC,
/** The payload is an OCIntrospectionPayload */
PAYLOAD_TYPE_INTROSPECTION
} OCPayloadType;
/**
......@@ -1585,6 +1578,12 @@ typedef struct
char* message;
} OCDiagnosticPayload;
typedef struct
{
OCPayload base;
OCByteString cborPayload;
} OCIntrospectionPayload;
/**
* Incoming requests handled by the server. Requests are passed in as a parameter to the
* OCEntityHandler callback API.
......
......@@ -86,8 +86,6 @@ extern "C"
#endif //MULTIPLE_OWNER
#define _80_SELECT_PROTOCOL_ 80
#define _81_SELECT_VERIF_METHOD_ 81
#define _91_SELECT_INTROSPECTION_METHOD_ 91
#define _92_SELECT_INTROSPECTION_PAYLOAD_METHOD_ 92
#define _99_EXIT_PRVN_CLT_ 99
#define ACL_RESRC_MAX_NUM 16
......@@ -2626,46 +2624,6 @@ const char* getResult(OCStackResult result)
}
}
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
OC_UNUSED(ctx);
OC_UNUSED(handle);
if (clientResponse == NULL)
{
OIC_LOG(INFO, TAG, "getReqCB received NULL clientResponse");
return OC_STACK_DELETE_TRANSACTION;
}
OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
OIC_LOG_V(INFO, TAG, "Payload Size: %d",
((OCRepPayload*)clientResponse->payload)->values->str);
OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
OIC_LOG(INFO, TAG, "=============> Get Response");
if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
{
OIC_LOG(INFO, TAG, "Received vendor specific options");
uint8_t i = 0;
OCHeaderOption* rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
{
if ((rcvdOptions[i]).protocolID == OC_COAP_ID)
{
OIC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
(rcvdOptions[i]).optionID);
OIC_LOG_BUFFER(INFO, TAG, rcvdOptions[i].optionData,
MAX_HEADER_OPTION_DATA_LENGTH);
}
}
}
g_doneCB = true; // flag done
return OC_STACK_DELETE_TRANSACTION;
}
int obtainUserSelectionForDeviceNumber(int numDevices)
{
int dev_num = -1;
......@@ -2687,111 +2645,6 @@ int obtainUserSelectionForDeviceNumber(int numDevices)
return dev_num;
}
void selectIntrospectionMethod()
{
OCStackResult ret;
OCCallbackData cbData;
OCDoHandle handle;
static OCDevAddr serverAddr;
cbData.cb = &getReqCB;
int dev_num = 1;
OCProvisionDev_t *device = NULL;
// check |own_list| for devices that can be used for introspection
if (!g_own_list || (1 > g_own_cnt))
{
printf(" > Owned Device List, to do introspection, is Empty\n");
printf(" > Please Register Unowned Devices first, with [20] Menu\n");
return;
}
if (g_own_cnt != 1)
{
// we have more than one option - ask user to select one
printf(" > Multiple devices found - select a device for Introspection\n");
dev_num = obtainUserSelectionForDeviceNumber(g_own_cnt);
}
device = getDevInst(g_own_list, dev_num);
if (device)
{
serverAddr = device->endpoint;
cbData.context = NULL;
cbData.cd = NULL;
OIC_LOG_V(INFO, TAG, "Performing Introspection");
g_doneCB = false;
ret = OCDoResource(&handle, OC_REST_GET, OC_RSRVD_INTROSPECTION_URI, &serverAddr,
NULL,
CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OIC_LOG_V(ERROR, TAG, "OCDoResource returned error %d with method", ret);
}
if (waitCallbackRet()) // input |g_doneCB| flag implicitly
{
OIC_LOG(ERROR, TAG, "selectIntrospectionMethod callback error");
}
}
else
{
OIC_LOG(ERROR, TAG, "Selected device does not exist");
}
}
void selectIntrospectionPayloadMethod()
{
OCStackResult ret;
OCCallbackData cbData;
OCDoHandle handle;
static OCDevAddr serverAddr;
cbData.cb = &getReqCB;
int dev_num = 1;
OCProvisionDev_t *device = NULL;
// check |own_list| for devices that can be used for introspection payload
if (!g_own_list || (1 > g_own_cnt))
{
printf(" > Owned Device List, to get introspection payload, is Empty\n");
printf(" > Please Register Unowned Devices first, with [20] Menu\n");
return;
}
if (g_own_cnt != 1)
{
// we have more than one option - ask user to select one
printf(" > Multiple devices found - select a device for Introspection payload\n");
dev_num = obtainUserSelectionForDeviceNumber(g_own_cnt);
}
device = getDevInst(g_own_list, dev_num);
if (device)
{
serverAddr = device->endpoint;
cbData.context = g_ctx;
cbData.cd = NULL;
OIC_LOG_V(INFO, TAG, "Performing Introspection Payload");
g_doneCB = false;
ret = OCDoResource(&handle, OC_REST_GET, OC_RSRVD_INTROSPECTION_PAYLOAD_URI, &serverAddr,
NULL,
CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OIC_LOG_V(ERROR, TAG, "OCDoResource returned error %d with method", ret);
}
if (waitCallbackRet()) // input |g_doneCB| flag implicitly
{
OIC_LOG(ERROR, TAG, "selectIntrospectionPayloadMethod callback error");
}
}
else
{
OIC_LOG(ERROR, TAG, "Selected device does not exist");
}
}
static void printUuid(const OicUuid_t* uid)
{
for(int i=0; i<UUID_LENGTH; )
......@@ -3006,10 +2859,6 @@ static void printMenu(void)
printf("** 81. Select verification method\n\n");
#endif
printf("** [I] SELECT INTROSPECTION OPTION\n");
printf("** 91. Select Get Introspection Resource\n");
printf("** 92. Select Get Introspection Payload\n\n");
printf("** [J] EXIT PROVISIONING CLIENT\n");
printf("** 99. Exit Provisionong Client\n\n");
......@@ -3232,12 +3081,6 @@ int main()
case _81_SELECT_VERIF_METHOD_:
selectVerifMethod();
break;
case _91_SELECT_INTROSPECTION_METHOD_:
selectIntrospectionMethod();
break;
case _92_SELECT_INTROSPECTION_PAYLOAD_METHOD_:
selectIntrospectionPayloadMethod();
break;
case _99_EXIT_PRVN_CLT_:
goto PMCLT_ERROR;
default:
......
......@@ -54,6 +54,12 @@ typedef struct PRESENCERESOURCE{
} PresenceResource;
#endif
/** Introspection URI.*/
#define OC_RSRVD_INTROSPECTION_URI_PATH "/introspection"
/** Introspection payload URI.*/
#define OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH "/introspection/payload"
/**
* Forward declarations
*/
......
......@@ -234,6 +234,10 @@ OCDiscoveryPayload* OCDiscoveryPayloadCreate();
OCSecurityPayload* OCSecurityPayloadCreate(const uint8_t* securityData, size_t size);
void OCSecurityPayloadDestroy(OCSecurityPayload* payload);
OCIntrospectionPayload* OCIntrospectionPayloadCreateFromCbor(const uint8_t* cborData,
size_t size);
void OCIntrospectionPayloadDestroy(OCIntrospectionPayload* payload);
#ifndef TCP_ADAPTER
void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
uint16_t securePort);
......
......@@ -81,8 +81,8 @@ sample_build_dir = samples_env.get(
'BUILD_DIR') + '/resource/csdk/stack/samples/linux/SimpleClientServer/'
introspectionJson = samples_env.Install(sample_build_dir,
sample_src_dir + 'introspection.json')
introspectionDat = samples_env.Install(sample_build_dir,
sample_src_dir + 'introspection.dat')
deviceProperties = samples_env.Install(sample_build_dir,
sample_src_dir + 'device_properties.dat')
......
This diff was suppressed by a .gitattributes entry.
......@@ -61,7 +61,6 @@ static int Introspection = 0;
static const char *DEVICE_DISCOVERY_QUERY = "%s/oic/d";
static const char *PLATFORM_DISCOVERY_QUERY = "%s/oic/p";
static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
static const char *INTROSPECTION_DISCOVERY_QUERY = "%s" OC_RSRVD_INTROSPECTION_URI;
//The following variable determines the interface protocol (IPv4, IPv6, etc)
//to be used for sending unicast messages. Default set to IP dual stack.
......@@ -69,7 +68,9 @@ static OCConnectivityType ConnType = CT_ADAPTER_IP;
static OCDevAddr serverAddr;
static char discoveryAddr[100];
static std::string coapServerResource = "/a/light";
static std::string coapIntrospectionResource = OC_RSRVD_INTROSPECTION_URI;
static std::string introspectionResType = "oic.wk.introspection";
int InitIntrospectionPayload(OCClientResponse * clientResponse);
#ifdef WITH_PRESENCE
// The handle for observe registration
......@@ -290,6 +291,16 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
}
}
}
switch (TestCase)
{
case TEST_INTROSPECTION:
InitIntrospectionPayload(clientResponse);
break;
default:
break;
}
return OC_STACK_DELETE_TRANSACTION;
}
......@@ -609,11 +620,77 @@ int InitGetRequestToUnavailableResource(OCQualityOfService qos)
getReqCB, NULL, 0));
}
int InitIntrospectionPayload(OCClientResponse * clientResponse)
{
std::ostringstream query;
std::string introspectionPayloadUrl;
OCRepPayload *introspectionInfo = (OCRepPayload*)clientResponse->payload;
OCRepPayloadValue *value = introspectionInfo->values;
while (value)
{
if (strcmp(value->name, "urlInfo") == 0)
{
break;
}
value = value->next;
}
if (value && (value->arr.dimensions[0] > 0))
{
OCRepPayloadValue *prop = value->arr.objArray[0]->values;
while (prop)
{
if (strcmp(prop->name, "url") == 0)
{
introspectionPayloadUrl = prop->str;
break;
}
prop = prop->next;
}
}
if (introspectionPayloadUrl.length() <= 0)
{
OIC_LOG(ERROR, TAG, "\nFailed to get introspection URL from payload");
return OC_STACK_ERROR;
}
else
{
query << introspectionPayloadUrl;
OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, OC_LOW_QOS,
getReqCB, NULL, 0));
}
}
int InitIntrospection(OCDiscoveryPayload* dis)
{
OC_UNUSED(dis);
OCResourcePayload* resource = (OCResourcePayload*)dis->resources;
bool found = false;
std::string introspectionUri;
while (resource && !found)
{
OCStringLL* resTypes = resource->types;
while (resTypes && !found)
{
if (strcmp(resTypes->value, introspectionResType.c_str()) == 0)
{
introspectionUri = resource->uri;
found = true;
}
resTypes = resTypes->next;
}
resource = resource->next;
}
if (introspectionUri.length() == 0)
{
OIC_LOG(ERROR, TAG, "Could not find URI for introspection");
}
std::ostringstream query;
query << coapIntrospectionResource;
query << introspectionUri;
OIC_LOG_V(INFO, TAG, "\nExecuting %s with query %s", __func__, query.str().c_str());
return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, OC_LOW_QOS,
getReqCB, NULL, 0));
......@@ -830,31 +907,6 @@ int InitDeviceDiscovery(OCQualityOfService qos)
return ret;
}
int InitIntrospectionDiscovery(OCQualityOfService qos)
{
OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
OCStackResult ret;
OCCallbackData cbData;
char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof(szQueryUri) - 1, INTROSPECTION_DISCOVERY_QUERY, discoveryAddr);
cbData.cb = DeviceDiscoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoRequest(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
(qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
&cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OIC_LOG(ERROR, TAG, "OCStack device error");
}
return ret;
}
int InitDiscovery(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions)
{
OCStackResult ret;
......
......@@ -65,6 +65,9 @@ void OCPayloadDestroy(OCPayload* payload)
case PAYLOAD_TYPE_SECURITY:
OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
break;
case PAYLOAD_TYPE_INTROSPECTION:
OCIntrospectionPayloadDestroy((OCIntrospectionPayload*)payload);
break;
default:
OIC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
OICFree(payload);
......@@ -1688,6 +1691,40 @@ void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
OICFree(payload);
}
OCIntrospectionPayload* OCIntrospectionPayloadCreateFromCbor(const uint8_t* cborData,
size_t size)
{
OCIntrospectionPayload* payload = NULL;
payload = (OCIntrospectionPayload*)OICCalloc(1, sizeof(OCIntrospectionPayload));
if (!payload)
{
return NULL;
}
payload->base.type = PAYLOAD_TYPE_INTROSPECTION;
payload->cborPayload.bytes = (uint8_t*)OICCalloc(1, size);
if (!payload->cborPayload.bytes)
{
OICFree(payload);
return NULL;
}
memcpy(payload->cborPayload.bytes, cborData, size);
payload->cborPayload.len = size;
return payload;
}
void OCIntrospectionPayloadDestroy(OCIntrospectionPayload* payload)
{
if (!payload)
{
return;
}
OICFree(payload->cborPayload.bytes);
OICFree(payload);
}
size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
{
size_t i = 0;
......
......@@ -58,6 +58,8 @@ static int64_t OCConvertDiagnosticPayload(OCDiagnosticPayload *payload, uint8_t
size_t *size);
static int64_t OCConvertSecurityPayload(OCSecurityPayload *payload, uint8_t *outPayload,
size_t *size);
static int64_t OCConvertIntrospectionPayload(OCIntrospectionPayload *payload, uint8_t *outPayload,
size_t *size);
static int64_t OCConvertSingleRepPayloadValue(CborEncoder *parent, const OCRepPayloadValue *value);
static int64_t OCConvertSingleRepPayload(CborEncoder *parent, const OCRepPayload *payload);
static int64_t OCConvertArray(CborEncoder *parent, const OCRepPayloadValueArray *valArray);
......@@ -95,6 +97,14 @@ OCStackResult OCConvertPayload(OCPayload* payload, OCPayloadFormat format,
curSize = securityPayloadSize;
}
}
if (PAYLOAD_TYPE_INTROSPECTION == payload->type)
{
size_t introspectionPayloadSize = ((OCIntrospectionPayload *)payload)->cborPayload.len;
if (introspectionPayloadSize > 0)
{
curSize = introspectionPayloadSize;
}
}
ret = OC_STACK_NO_MEMORY;
......@@ -115,7 +125,8 @@ OCStackResult OCConvertPayload(OCPayload* payload, OCPayloadFormat format,
if (err == CborNoError)
{
if ((curSize < INIT_SIZE) &&
(PAYLOAD_TYPE_SECURITY != payload->type))
(PAYLOAD_TYPE_SECURITY != payload->type) &&
(PAYLOAD_TYPE_INTROSPECTION != payload->type))
{
uint8_t *out2 = (uint8_t *)OICRealloc(out, curSize);
VERIFY_PARAM_NON_NULL(TAG, out2, "Failed to increase payload size");
......@@ -153,8 +164,11 @@ static int64_t OCConvertPayloadHelper(OCPayload* payload, OCPayloadFormat format
return OCConvertDiagnosticPayload((OCDiagnosticPayload*)payload, outPayload, size);
case PAYLOAD_TYPE_SECURITY:
return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size);
case PAYLOAD_TYPE_INTROSPECTION:
return OCConvertIntrospectionPayload((OCIntrospectionPayload*)payload,
outPayload, size);
default:
OIC_LOG_V(INFO,TAG, "ConvertPayload default %d", payload->type);
OIC_LOG_V(INFO, TAG, "ConvertPayload default %d", payload->type);
return CborErrorUnknownType;
}
}
......@@ -187,6 +201,15 @@ static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* out
return CborNoError;
}
static int64_t OCConvertIntrospectionPayload(OCIntrospectionPayload *payload,
uint8_t *outPayload, size_t *size)
{
memcpy(outPayload, payload->cborPayload.bytes, payload->cborPayload.len);
*size = payload->cborPayload.len;
return CborNoError;
}
static int64_t OCStringLLJoin(CborEncoder *map, char *type, OCStringLL *val)
{
uint16_t count = 0;
......
......@@ -290,11 +290,11 @@ OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
{
return OC_RESOURCE_TYPES_URI;
}
else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI) == 0)
else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI_PATH) == 0)
{
return OC_INTROSPECTION_URI;
}
else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH) == 0)
{
return OC_INTROSPECTION_PAYLOAD_URI;
}
......@@ -923,7 +923,7 @@ static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
return size;
}
OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
OCStackResult GetIntrospectionDataFromPS(uint8_t **data, size_t *size)
{
OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS IN");
......@@ -967,7 +967,7 @@ OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
{
*size = fileSize;
fsData[fileSize] = '\0';
*data = (char *)fsData;
*data = fsData;
fsData = NULL;
ret = OC_STACK_OK;
}
......@@ -987,45 +987,35 @@ exit:
}
OCStackResult BuildIntrospectionPayloadResponse(const OCResource *resourcePtr,
OCRepPayload** payload, OCDevAddr *devAddr)
OCPayload **payload, OCDevAddr *devAddr)
{
OC_UNUSED(resourcePtr);
OC_UNUSED(devAddr);
char *introspectionData = NULL;
uint8_t *introspectionData = NULL;
size_t size = 0;
OCStackResult ret = GetIntrospectionDataFromPS(&introspectionData, &size);
if (OC_STACK_OK == ret)
{
OCRepPayload *tempPayload = OCRepPayloadCreate();
OCIntrospectionPayload *tempPayload = OCIntrospectionPayloadCreateFromCbor(introspectionData, size);
if (tempPayload)
{
if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
{
*payload = tempPayload;
}
else
{
OCRepPayloadDestroy(tempPayload);
ret = OC_STACK_ERROR;
}
*payload = (OCPayload *)tempPayload;
}
else
{
ret = OC_STACK_NO_MEMORY;
OICFree(introspectionData);
}
}
if (ret != OC_STACK_OK)
{
OICFree(introspectionData);
}
return ret;
}
OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol, char *ep)
{
OCStackResult result = OC_STACK_OK;
char introspectionUrl[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
if (!urlInfoPayload)