From d3c8a928c39f10b088be91bb356bca7e85e55237 Mon Sep 17 00:00:00 2001 From: omkar Date: Wed, 7 Jan 2015 17:00:38 -0800 Subject: [PATCH] Enabling Requests on Multiple Interfaces CA Updated sample apps to send Discovery messages over multiple interfaces. Unicast Messages are sent over WIFI. Added a new type "OC_ALL" for Multicast messages. Resource Discovery is not done in case of multicast device discovery. Change-Id: Ifb3364b986e588bd95ae255acaf913ffc7f49fcc Signed-off-by: omkar --- resource/csdk/stack/include/ocstack.h | 9 +- .../samples/linux/SimpleClientServer/occlient.cpp | 78 +++++++++++-- resource/csdk/stack/src/ocstack.c | 123 +++++++++++++++++---- resource/csdk/stack/src/oicgroup.c | 2 +- 4 files changed, 173 insertions(+), 39 deletions(-) diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h index 437d596..6fdfe57 100644 --- a/resource/csdk/stack/include/ocstack.h +++ b/resource/csdk/stack/include/ocstack.h @@ -138,10 +138,11 @@ typedef enum { * Adaptor types */ typedef enum { - OC_ETHERNET = (1 << 0), - OC_WIFI = (1 << 1), - OC_EDR = (1 << 2), - OC_LE = (1 << 3) + OC_ETHERNET = 0, + OC_WIFI, + OC_EDR, + OC_LE, + OC_ALL //Multicast message: send over all the interfaces. } OCConnectivityType; #endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp index e9e1228..4067497 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp @@ -34,6 +34,13 @@ static int TEST_CASE = 0; static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; static const char * TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core/d"; static const char * TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY = "coap://224.0.1.187:5683/oc/core/d"; +#ifdef CA_INT +static const char * MULTICAST_DEVICE_DISCOVERY_QUERY = "/oc/core/d"; +static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oc/core"; +//The following variable determines the interface (wifi, ethernet etc.) +//to be used for sending unicast messages. Default set to WIFI. +static OCConnectivityType CA_CONNTYPE = OC_WIFI; +#endif static std::string putPayload = "{\"state\":\"on\",\"power\":5}"; static std::string coapServerIP = "255.255.255.255"; static std::string coapServerPort = "5683"; @@ -62,8 +69,15 @@ void handleSigInt(int signum) { static void PrintUsage() { - OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3|4|5|6|7>"); +#ifdef CA_INT + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3|4|5|6|7> -c <0|1|2|3>"); +#else + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3|4|5|6|7>"); +#endif OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); +#ifdef CA_INT + OC_LOG(INFO, TAG, "-c <0|1|2|3> : Send unicast messages over Ethernet, WIFI, EDR or LE"); +#endif OC_LOG(INFO, TAG, "-t 1 : Discover Resources"); OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request"); OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Nonconfirmable Put Requests"); @@ -107,7 +121,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, #ifdef CA_INT ret = OCDoResource(&handle, method, query.str().c_str(), 0, (method == OC_REST_PUT) ? putPayload.c_str() : NULL, - (OC_WIFI), qos, &cbData, options, numOptions); + (CA_CONNTYPE), qos, &cbData, options, numOptions); #else ret = OCDoResource(&handle, method, query.str().c_str(), 0, (method == OC_REST_PUT) ? putPayload.c_str() : NULL, @@ -576,15 +590,30 @@ int InitDeviceDiscovery() strncpy(szQueryUri, TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY, (strlen(TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY) + 1)); } + else { +#ifdef CA_INT + strncpy(szQueryUri, MULTICAST_DEVICE_DISCOVERY_QUERY, + (strlen(MULTICAST_DEVICE_DISCOVERY_QUERY) + 1)); + +#else strncpy(szQueryUri, TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY, (strlen(TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY) + 1)); +#endif } #ifdef CA_INT - ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, (OC_WIFI), - OC_LOW_QOS, &cbData, NULL, 0); + if(UNICAST_DISCOVERY) + { + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, CA_CONNTYPE, + OC_LOW_QOS, &cbData, NULL, 0); + } + else + { + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, (OC_ALL), + OC_LOW_QOS, &cbData, NULL, 0); + } #else ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); #endif @@ -604,25 +633,34 @@ int InitDiscovery() OCDoHandle handle; /* Start a discovery query*/ char szQueryUri[64] = { 0 }; + if (UNICAST_DISCOVERY) { strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY); } else { - #ifdef CA_INT - // TODO-CA CA is using 5298 for MC. Why 5298? - strcpy(szQueryUri, "coap://224.0.1.187:5298/oc/core"); - #else +#ifdef CA_INT + strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY); +#else strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); - #endif +#endif } + cbData.cb = discoveryReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; #ifdef CA_INT - ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, (OC_ETHERNET | OC_WIFI), - OC_LOW_QOS, &cbData, NULL, 0); + if(UNICAST_DISCOVERY) + { + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, CA_CONNTYPE, + OC_LOW_QOS, &cbData, NULL, 0); + } + else + { + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, (OC_ALL), + OC_LOW_QOS, &cbData, NULL, 0); + } #else ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); #endif @@ -640,7 +678,11 @@ int main(int argc, char* argv[]) { uint8_t ifname[] = "eth0"; int opt; +#ifdef CA_INT + while ((opt = getopt(argc, argv, "u:t:c:")) != -1) +#else while ((opt = getopt(argc, argv, "u:t:")) != -1) +#endif { switch(opt) { @@ -650,6 +692,11 @@ int main(int argc, char* argv[]) { case 't': TEST_CASE = atoi(optarg); break; + #ifdef CA_INT + case 'c': + CA_CONNTYPE = OCConnectivityType(atoi(optarg)); + break; + #endif default: PrintUsage(); return -1; @@ -679,7 +726,14 @@ int main(int argc, char* argv[]) { return 0; } - InitDiscovery(); + if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_DEV_REQ) + { + InitDeviceDiscovery(); + } + else + { + InitDiscovery(); + } // Break from loop with Ctrl+C OC_LOG(INFO, TAG, "Entering occlient main loop..."); diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index c32deb9..b2c2c74 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -238,15 +238,76 @@ OCStackResult CAToOCStackResult(CAResponseResult_t caCode) return ret; } +OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType) +{ + OCStackResult ret = OC_STACK_OK; + + switch(ocConType) + { + case OC_ETHERNET: + *caConType = CA_ETHERNET; + break; + case OC_WIFI: + *caConType = CA_WIFI; + break; + case OC_EDR: + *caConType = CA_EDR; + break; + case OC_LE: + *caConType = CA_LE; + break; + case OC_ALL: + //TODO-CA Add other connectivity types as they are enabled + *caConType = (CA_WIFI|CA_ETHERNET); + break; + default: + ret = OC_STACK_INVALID_PARAM; + break; + } + return ret; +} + +OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType) +{ + OCStackResult ret = OC_STACK_OK; + + switch(caConType) + { + case CA_ETHERNET: + *ocConType = OC_ETHERNET; + break; + case CA_WIFI: + *ocConType = OC_WIFI; + break; + case CA_EDR: + *ocConType = OC_EDR; + break; + case CA_LE: + *ocConType = OC_LE; + break; + default: + ret = OC_STACK_INVALID_PARAM; + break; + } + return ret; +} + // update response.addr appropriately from endPoint.addressInfo -void UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint) +OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint) { struct sockaddr_in sa; + OCStackResult ret = OC_STACK_INVALID_PARAM; + //TODO-CA Check validity of the endPoint pointer inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr)); sa.sin_port = htons(endPoint->addressInfo.IP.port); static OCDevAddr address; memcpy((void*)&address.addr, &(sa), sizeof(sa)); - response->addr = &address; + if(response) + { + response->addr = &address; + ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType)); + } + return ret; } void HandlePresenceResponse(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo) @@ -258,7 +319,11 @@ void HandlePresenceResponse(const CARemoteEndpoint_t* endPoint, const CAResponse char * bufRes = responseInfo->info.payload; OCClientResponse *response = (OCClientResponse *) OCMalloc(sizeof(OCClientResponse)); - UpdateResponseAddr(response, endPoint); + OCStackResult result = UpdateResponseAddr(response, endPoint); + if(result != OC_STACK_OK) + { + goto exit; + } if(!bufRes) { @@ -335,8 +400,12 @@ void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_ OC_LOG(INFO, TAG, PCF("Calling into application address space")); OCClientResponse response; - UpdateResponseAddr(&response, endPoint); - response.connType = endPoint->connectivityType; + OCStackResult result = UpdateResponseAddr(&response, endPoint); + if(result != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint")); + return; + } response.result = CAToOCStackResult(responseInfo->result); response.resJSONPayload = (unsigned char*)responseInfo->info.payload; @@ -1182,6 +1251,9 @@ OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen) * OC_STACK_INVALID_CALLBACK - invalid callback function pointer * OC_STACK_INVALID_METHOD - invalid resource method * OC_STACK_INVALID_URI - invalid required or reference URI + * + * Note: IN case of CA, when using multicast, the required URI should not contain IP address. + * Instead, it just contains the URI to the resource such as "/oc/core". */ #ifdef CA_INT OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri, @@ -1349,17 +1421,6 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ result = OC_STACK_INVALID_PARAM; goto exit; } - // TODO-CA: Handle multi-cast scenario - // Create remote end point - caResult = CACreateRemoteEndpoint(newUri, conType, &endpoint); - // TODO-CA: Connectivity type should be passed to API - endpoint->connectivityType = conType; - - if (caResult != CA_STATUS_OK) - { - OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error")); - goto exit; - } // create token caResult = CAGenerateToken(&caToken); @@ -1399,21 +1460,38 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ requestInfo.info = requestData; + CAConnectivityType_t caConType; + + result = OCToCAConnectivityType(conType, &caConType); + if (result != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type")); + goto exit; + } + // send request - //TODO-CA Change This logic. Currently hardcoded to WIFI & ETHERNET - //Need to support other adapter types. - if(conType == (CA_WIFI | CA_ETHERNET)) + if(conType == OC_ALL) { - //TODO-CA remove hardcoded resource uri. Instead, extract it from newUri - grpEnd.connectivityType = conType; - grpEnd.resourceUri = "/oc/core"; + grpEnd.connectivityType = caConType; + + grpEnd.resourceUri = (CAURI_t) OICMalloc(uriLen + 1); + strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1)); caResult = CASendRequestToAll(&grpEnd, &requestInfo); } else { + caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint); + + if (caResult != CA_STATUS_OK) + { + OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error")); + goto exit; + } + caResult = CASendRequest(endpoint, &requestInfo); } + if (caResult != CA_STATUS_OK) { OC_LOG(ERROR, TAG, PCF("CASendRequest")); @@ -1456,6 +1534,7 @@ exit: } #ifdef CA_INT CADestroyRemoteEndpoint(endpoint); + OCFree(grpEnd.resourceUri); if (hdrOptionMemAlloc) { OCFree(requestData.options); diff --git a/resource/csdk/stack/src/oicgroup.c b/resource/csdk/stack/src/oicgroup.c index 5592ede..731c404 100644 --- a/resource/csdk/stack/src/oicgroup.c +++ b/resource/csdk/stack/src/oicgroup.c @@ -680,7 +680,7 @@ OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsign #ifdef CA_INT return OCDoResource(handle, OC_REST_PUT, targetUri, //temp->rsrcType->resourcetypename, - NULL, (char *) action, OC_WIFI | OC_ETHERNET, OC_NA_QOS, &cbdata, NULL, 0); + NULL, (char *) action, OC_WIFI, OC_NA_QOS, &cbdata, NULL, 0); #else return OCDoResource(handle, OC_REST_PUT, targetUri, //temp->rsrcType->resourcetypename, -- 2.7.4