[IOT-1965] Introspection update to follow spec 13/19513/4
authorSrikrishna Gurugubelli <srikguru@microsoft.com>
Mon, 1 May 2017 16:52:49 +0000 (09:52 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Thu, 4 May 2017 14:06:26 +0000 (14:06 +0000)
Change-Id: I5e6c0d1a016e409429498835587c73d5ef0b7fea
Signed-off-by: Srikrishna Gurugubelli <srikguru@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19513
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
13 files changed:
resource/csdk/include/octypes.h
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/samples/linux/SimpleClientServer/SConscript
resource/csdk/stack/samples/linux/SimpleClientServer/introspection.dat [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocstack.c
resource/examples/light_introspection.dat [new file with mode: 0644]
resource/examples/lightserver.cpp

index 2ba1f9b..117ef7e 100644 (file)
@@ -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.
index 3f2fde5..5fce3ad 100644 (file)
@@ -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:
index e008cb0..df4a172 100644 (file)
@@ -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
  */
index 5565710..1312b2c 100644 (file)
@@ -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);
index d827b34..9737de5 100644 (file)
@@ -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')
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/introspection.dat b/resource/csdk/stack/samples/linux/SimpleClientServer/introspection.dat
new file mode 100644 (file)
index 0000000..5bafcf8
--- /dev/null
@@ -0,0 +1 @@
+¿gswaggerc2.0dinfo¿etitleqmy_example_devicegversionqmy device versionÿgschemes\9fdhttpÿhconsumes\9fpapplication/jsonÿhproduces\9fpapplication/jsonÿepaths¿g/switch¿cget¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿdpost¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿ¿dnamedbodybindbodyhrequiredôfschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿÿk/brightness¿cget¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿÿiresponses¿c200¿kdescription`fschema¿d$refx\18#/definitions/Brightnessÿÿÿÿdpost¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿ¿dnamedbodybindbodyhrequiredôfschema¿d$refx\18#/definitions/Brightnessÿÿÿiresponses¿c200¿kdescription`fschema¿d$refx\18#/definitions/Brightnessÿÿÿÿÿÿkdefinitions¿lBinarySwitch¿dtypefobjecthrequired\9fbidÿjproperties¿evalue¿dtypegbooleankdescriptiontStatus of the switchÿbrt¿dtypeearrayeitems\9f¿dtypefstringimaxLength\18@ÿÿhminItems\ 1kdescriptionmResource TypehreadOnlyõgdefault\9fsoic.r.switch.binaryÿÿbif¿dtypeearraykdescriptionx,The interface set supported by this resourcehreadOnlyõeitems¿dtypefstringdenum\9fooic.if.baselinehoic.if.aÿÿÿap¿dtypegintegerkdescriptionx-Bitmap indicating observable and discoverablehreadOnlyõÿan¿dtypefstringkdescriptionx\1dFriendly name of the resourcehreadOnlyõÿbid¿dtypefstringkdescriptionx%Instance ID of this specific resourcehreadOnlyõÿerange¿dtypeearraykdescriptionx&The valid range for the value PropertyhreadOnlyõhminItems\ 2hmaxItems\ 2eitems¿dtypefnumberÿÿÿÿjBrightness¿dtypefobjecthrequired\9fbidÿjproperties¿ibrighness¿dtypegintegerkdescriptionx*Current sensed or set value for Brightnessÿbrt¿dtypeearrayeitems\9f¿dtypefstringimaxLength\18@ÿÿhminItems\ 1kdescriptionmResource TypehreadOnlyõgdefault\9fvoic.r.light.brightnessÿÿbif¿dtypeearraykdescriptionx,The interface set supported by this resourcehreadOnlyõeitems¿dtypefstringdenum\9fooic.if.baselinehoic.if.aÿÿÿap¿dtypegintegerkdescriptionx-Bitmap indicating observable and discoverablehreadOnlyõÿan¿dtypefstringkdescriptionx\1dFriendly name of the resourcehreadOnlyõÿbid¿dtypefstringkdescriptionx%Instance ID of this specific resourcehreadOnlyõÿerange¿dtypeearraykdescriptionx&The valid range for the value PropertyhreadOnlyõhminItems\ 2hmaxItems\ 2eitems¿dtypefnumberÿÿÿÿÿÿ
\ No newline at end of file
index 9c2deae..e0dade0 100755 (executable)
@@ -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;
index c7a1f7b..eaf5973 100644 (file)
@@ -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;
index 1d261b4..394f25c 100755 (executable)
@@ -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;
index 47002c8..98e41ff 100755 (executable)
@@ -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)
     {
@@ -1034,7 +1024,9 @@ OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
         goto exit;
     }
 
-    if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
+    snprintf(introspectionUrl, sizeof(introspectionUrl), "%s%s", ep, OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH);
+
+    if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, introspectionUrl))
     {
         OIC_LOG(ERROR, TAG, "Failed to add url");
         result = OC_STACK_ERROR;
@@ -1068,70 +1060,25 @@ exit:
     return urlInfoPayload;
 }
 
-OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
-{
-    OCStringLL* cur = *protoLL;
-    // Check if protocol is already in list
-    while (cur)
-    {
-        if (strcmp(cur->value, protocol) == 0)
-        {
-            break;
-        }
-        cur = cur->next;
-    }
-    if (cur)
-    {
-        // The intent of the protocol list is to collect all unique protocols available on this
-        // endpoint. Set an error that can be used to skip processing this protocol further as
-        // it already exists in the list.
-        return OC_STACK_INVALID_PARAM;
-    }
-    else
-    {
-        cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
-        if (!cur)
-        {
-            return OC_STACK_NO_MEMORY;
-        }
-    }
-
-    cur->value = OICStrdup(protocol);
-    if (!cur->value)
-    {
-        OICFree(cur);
-        return OC_STACK_NO_MEMORY;
-    }
-
-    cur->next = *protoLL;
-    *protoLL = cur;
-    return OC_STACK_OK;
-}
-
-void FreeProtocolLL(OCStringLL *protoLL)
-{
-    OCStringLL* cur = protoLL;
-    while (cur)
-    {
-        OCStringLL *temp = cur;
-        cur = cur->next;
-        OICFree(temp->value);
-        OICFree(temp);
-    }
-}
-
 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
     OCRepPayload** payload, OCDevAddr *devAddr)
 {
-    OC_UNUSED(devAddr);
-
     size_t dimensions[3] = { 0, 0, 0 };
     OCRepPayload *tempPayload = NULL;
     OCRepPayload **urlInfoPayload = NULL;
-    OCStringLL *protoLL = NULL;
     OCStackResult ret = OC_STACK_OK;
     OCResourceType *resType = NULL;
     OCResourceInterface *resInterface = NULL;
+    CAEndpoint_t *caEps = NULL;
+    size_t nCaEps = 0;
+    CAResult_t caResult = CA_STATUS_OK;
+    OCResource *payloadResPtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH);
+
+    if (!payloadResPtr)
+    {
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
     if (!resourcePtr)
     {
@@ -1183,94 +1130,75 @@ OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourc
         goto exit;
     }
 
-    // Figure out which protocols this endpoint supports
-    if (resourcePtr->endpointType & OC_COAP)
-    {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
-        {
-            dimensions[0]++;
-        }
-    }
-    if (resourcePtr->endpointType & OC_COAPS)
-    {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
-        {
-            dimensions[0]++;
-        }
-    }
-#ifdef TCP_ADAPTER
-    if (resourcePtr->endpointType & OC_COAP_TCP)
-    {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
-        {
-            dimensions[0]++;
-        }
-    }
-    if (resourcePtr->endpointType & OC_COAPS_TCP)
+    caResult = CAGetNetworkInformation(&caEps, &nCaEps);
+    if (CA_STATUS_FAILED == caResult)
     {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
-        {
-            dimensions[0]++;
-        }
-    }
-#endif
-#ifdef HTTP_ADAPTER
-    if (resourcePtr->endpointType & OC_HTTP)
-    {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
-        {
-            dimensions[0]++;
-        }
-    }
-    if (resourcePtr->endpointType & OC_HTTPS)
-    {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
-        {
-            dimensions[0]++;
-        }
+        OIC_LOG(ERROR, TAG, "CAGetNetworkInformation failed!");
+        ret = OC_STACK_ERROR;
+        goto exit;
     }
-#endif
-#ifdef EDR_ADAPTER
-    if (resourcePtr->endpointType & OC_COAP_RFCOMM)
+
+    // Add a urlInfo object for each endpoint supported
+    urlInfoPayload = (OCRepPayload **)OICMalloc(nCaEps * sizeof(OCRepPayload));
+    if (!urlInfoPayload)
     {
-        if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
-        {
-            dimensions[0]++;
-        }
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory for urlInfo ");
+        ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
-#endif
-    // Add a urlInfo object for each protocol supported
-    urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
-    if (urlInfoPayload)
+
+    if (caEps && nCaEps && devAddr)
     {
-        OCStringLL *proto = protoLL;
-        size_t i = 0;
-        while (proto)
+        if ((OC_ADAPTER_IP | OC_ADAPTER_TCP) & (devAddr->adapter))
         {
-            urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
-            if (!urlInfoPayload[i])
+            for (size_t i = 0; i < nCaEps; i++)
             {
-                OIC_LOG(ERROR, TAG, "Unable to build urlInfo object for protocol");
-                ret = OC_STACK_ERROR;
-                goto exit;
+                CAEndpoint_t *info = caEps + i;
+                char *proto = NULL;
+
+                // consider IP or TCP adapter for payload that is visible to the client
+                if (((CA_ADAPTER_IP | CA_ADAPTER_TCP) & info->adapter) && 
+                    (info->ifindex == devAddr->ifindex))
+                {
+                    OCTpsSchemeFlags matchedTps = OC_NO_TPS;
+                    if (OC_STACK_OK != OCGetMatchedTpsFlags(info->adapter,
+                                                            info->flags,
+                                                            &matchedTps))
+                    {
+                        ret = OC_STACK_ERROR;
+                        goto exit;
+                    }
+
+                    if ((payloadResPtr->endpointType) & matchedTps)
+                    {
+                        ret = OCConvertTpsToString(matchedTps, &proto);
+                        if (ret != OC_STACK_OK)
+                        {
+                            goto exit;
+                        }
+
+                        char *epStr = OCCreateEndpointStringFromCA(&caEps[i]);
+                        urlInfoPayload[dimensions[0]] = BuildUrlInfoWithProtocol(proto, epStr);
+                        dimensions[0] = dimensions[0] + 1;
+                        if (!urlInfoPayload[i])
+                        {
+                            OIC_LOG(ERROR, TAG, "Unable to build urlInfo object for protocol");
+                            ret = OC_STACK_ERROR;
+                            goto exit;
+                        }
+                    }
+                }
             }
-            proto = proto->next;
-            i++;
-        }
-        if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
-                                                   OC_RSRVD_INTROSPECTION_URL_INFO,
-                                                   urlInfoPayload,
-                                                   dimensions))
-        {
-            OIC_LOG(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
-            ret = OC_STACK_ERROR;
-            goto exit;
         }
     }
-    else
+
+    if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
+        OC_RSRVD_INTROSPECTION_URL_INFO,
+        urlInfoPayload,
+        dimensions))
     {
-        OIC_LOG(ERROR, TAG, "Unable to allocate memory for urlInfo ");
-        ret = OC_STACK_NO_MEMORY;
+        OIC_LOG(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
+        ret = OC_STACK_ERROR;
         goto exit;
     }
 
@@ -1291,7 +1219,6 @@ exit:
             OICFree(urlInfoPayload);
         }
     }
-    FreeProtocolLL(protoLL);
 
     return OC_STACK_OK;
 }
@@ -1949,7 +1876,7 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
     else if (OC_INTROSPECTION_URI == virtualUriInRequest)
     {
         // Received request for introspection
-        OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
+        OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI_PATH);
         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
         discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
         OIC_LOG(INFO, TAG, "Request is for Introspection");
@@ -1957,9 +1884,9 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
     else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
     {
         // Received request for introspection payload
-        OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
+        OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH);
         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
-        discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
+        discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, &payload, &request->devAddr);
         OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
     }
     /**
index 1c27a24..18d2ff9 100644 (file)
@@ -1744,14 +1744,6 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
                     {
                         type = PAYLOAD_TYPE_REPRESENTATION;
                     }
-                    else if (strcmp(cbNode->requestUri, OC_RSRVD_INTROSPECTION_URI) == 0)
-                    {
-                        type = PAYLOAD_TYPE_REPRESENTATION;
-                    }
-                    else if (strcmp(cbNode->requestUri, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
-                    {
-                        type = PAYLOAD_TYPE_REPRESENTATION;
-                    }
 #ifdef ROUTING_GATEWAY
                     else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0)
                     {
@@ -5072,7 +5064,7 @@ OCStackResult initResources()
         result = OCCreateResource(&introspectionResource,
                                   OC_RSRVD_RESOURCE_TYPE_INTROSPECTION,
                                   OC_RSRVD_INTERFACE_DEFAULT,
-                                  OC_RSRVD_INTROSPECTION_URI,
+                                  OC_RSRVD_INTROSPECTION_URI_PATH,
                                   NULL,
                                   NULL,
                                   OC_DISCOVERABLE);
@@ -5088,10 +5080,10 @@ OCStackResult initResources()
         result = OCCreateResource(&introspectionPayloadResource,
                                   OC_RSRVD_RESOURCE_TYPE_INTROSPECTION_PAYLOAD,
                                   OC_RSRVD_INTERFACE_DEFAULT,
-                                  OC_RSRVD_INTROSPECTION_PAYLOAD_URI,
+                                  OC_RSRVD_INTROSPECTION_PAYLOAD_URI_PATH,
                                   NULL,
                                   NULL,
-                                  OC_OBSERVABLE);
+                                  0);
         if (result == OC_STACK_OK)
         {
             result = BindResourceInterfaceToResource((OCResource *)introspectionPayloadResource,
diff --git a/resource/examples/light_introspection.dat b/resource/examples/light_introspection.dat
new file mode 100644 (file)
index 0000000..5bafcf8
--- /dev/null
@@ -0,0 +1 @@
+¿gswaggerc2.0dinfo¿etitleqmy_example_devicegversionqmy device versionÿgschemes\9fdhttpÿhconsumes\9fpapplication/jsonÿhproduces\9fpapplication/jsonÿepaths¿g/switch¿cget¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿdpost¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿ¿dnamedbodybindbodyhrequiredôfschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿÿk/brightness¿cget¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿÿiresponses¿c200¿kdescription`fschema¿d$refx\18#/definitions/Brightnessÿÿÿÿdpost¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿ¿dnamedbodybindbodyhrequiredôfschema¿d$refx\18#/definitions/Brightnessÿÿÿiresponses¿c200¿kdescription`fschema¿d$refx\18#/definitions/Brightnessÿÿÿÿÿÿkdefinitions¿lBinarySwitch¿dtypefobjecthrequired\9fbidÿjproperties¿evalue¿dtypegbooleankdescriptiontStatus of the switchÿbrt¿dtypeearrayeitems\9f¿dtypefstringimaxLength\18@ÿÿhminItems\ 1kdescriptionmResource TypehreadOnlyõgdefault\9fsoic.r.switch.binaryÿÿbif¿dtypeearraykdescriptionx,The interface set supported by this resourcehreadOnlyõeitems¿dtypefstringdenum\9fooic.if.baselinehoic.if.aÿÿÿap¿dtypegintegerkdescriptionx-Bitmap indicating observable and discoverablehreadOnlyõÿan¿dtypefstringkdescriptionx\1dFriendly name of the resourcehreadOnlyõÿbid¿dtypefstringkdescriptionx%Instance ID of this specific resourcehreadOnlyõÿerange¿dtypeearraykdescriptionx&The valid range for the value PropertyhreadOnlyõhminItems\ 2hmaxItems\ 2eitems¿dtypefnumberÿÿÿÿjBrightness¿dtypefobjecthrequired\9fbidÿjproperties¿ibrighness¿dtypegintegerkdescriptionx*Current sensed or set value for Brightnessÿbrt¿dtypeearrayeitems\9f¿dtypefstringimaxLength\18@ÿÿhminItems\ 1kdescriptionmResource TypehreadOnlyõgdefault\9fvoic.r.light.brightnessÿÿbif¿dtypeearraykdescriptionx,The interface set supported by this resourcehreadOnlyõeitems¿dtypefstringdenum\9fooic.if.baselinehoic.if.aÿÿÿap¿dtypegintegerkdescriptionx-Bitmap indicating observable and discoverablehreadOnlyõÿan¿dtypefstringkdescriptionx\1dFriendly name of the resourcehreadOnlyõÿbid¿dtypefstringkdescriptionx%Instance ID of this specific resourcehreadOnlyõÿerange¿dtypeearraykdescriptionx&The valid range for the value PropertyhreadOnlyõhminItems\ 2hmaxItems\ 2eitems¿dtypefnumberÿÿÿÿÿÿ
\ No newline at end of file
index 0c58e99..860f725 100644 (file)
@@ -391,7 +391,7 @@ FILE* server_fopen(const char* path, const char* mode)
 {
     if (0 == strcmp(path, OC_INTROSPECTION_FILE_NAME))
     {
-        return fopen("light_introspection.json", mode);
+        return fopen("light_introspection.dat", mode);
     }
     else
     {