From: Jaewook Jung Date: Thu, 6 Oct 2016 10:35:27 +0000 (+0900) Subject: added filter to handle an IP loopback message in CA directly X-Git-Tag: 1.3.0~1049^2~20 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e3c156d2bb5ccc71dd2b1d4abb0844a99a4d2eb5;p=platform%2Fupstream%2Fiotivity.git added filter to handle an IP loopback message in CA directly If IoTivity stack sends a message to itself, which means the loopback, it is unnecessary to let them go through the socket layer. Especially it is a waste when the large payload will be sent by block-wise transfer. So I made CA layer to handle the loopback message directly. Change-Id: I2b8e5217575df391dd4ab66d924a3a24c2584915 Signed-off-by: Jaewook Jung Reviewed-on: https://gerrit.iotivity.org/gerrit/12887 Tested-by: jenkins-iotivity Reviewed-by: Phil Coval Reviewed-by: Hyuna Jo Reviewed-by: Jaehong Jo Reviewed-by: Dan Mihai --- diff --git a/resource/csdk/connectivity/inc/cainterfacecontroller.h b/resource/csdk/connectivity/inc/cainterfacecontroller.h index 0dbd673..fa15c25 100644 --- a/resource/csdk/connectivity/inc/cainterfacecontroller.h +++ b/resource/csdk/connectivity/inc/cainterfacecontroller.h @@ -161,6 +161,12 @@ CAResult_t CAStopListeningServerAdapters(); CAResult_t CAStartDiscoveryServerAdapters(); /** + * Check whether the endpoint is my own or not. + * @return true or false. + */ +bool CAIsLocalEndpoint(const CAEndpoint_t *ep); + +/** * Terminates the adapters which are initialized during the initialization. */ void CATerminateAdapters(); diff --git a/resource/csdk/connectivity/inc/caipadapter.h b/resource/csdk/connectivity/inc/caipadapter.h index 7ca9267..829b043 100644 --- a/resource/csdk/connectivity/inc/caipadapter.h +++ b/resource/csdk/connectivity/inc/caipadapter.h @@ -134,6 +134,12 @@ CAResult_t CAReadIPData(); CAResult_t CAStopIP(); /** + * Check whether the endpoint is my own or not. + * @return true or false. + */ +bool CAIPIsLocalEndpoint(const CAEndpoint_t *ep); + +/** * Terminate the IP connectivity adapter. * Configuration information will be deleted from further use. */ diff --git a/resource/csdk/connectivity/src/cainterfacecontroller.c b/resource/csdk/connectivity/src/cainterfacecontroller.c index fbc0364..42ad155 100644 --- a/resource/csdk/connectivity/src/cainterfacecontroller.c +++ b/resource/csdk/connectivity/src/cainterfacecontroller.c @@ -752,6 +752,19 @@ CAResult_t CAStartDiscoveryServerAdapters() return result; } +bool CAIsLocalEndpoint(const CAEndpoint_t *ep) +{ +#ifdef IP_ADAPTER + if (ep->adapter & CA_ADAPTER_IP) + { + return CAIPIsLocalEndpoint(ep); + } +#endif /* IP_ADAPTER */ + + //TODO: implement for the other adapters(EDR/LE/NFC) + return false; +} + void CATerminateAdapters() { for (uint32_t index = 0; index < g_numberOfAdapters; index++) diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c index 847b96f..1f3fe86 100644 --- a/resource/csdk/connectivity/src/camessagehandler.c +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -999,6 +999,13 @@ CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg OICFree(data); #else + if (SEND_TYPE_UNICAST == data->type && CAIsLocalEndpoint(data->remoteEndpoint)) + { + OIC_LOG(DEBUG, TAG, + "This is a loopback message. Transfer it to the receive queue directly"); + CAQueueingThreadAddData(&g_receiveThread, data, sizeof(CAData_t)); + return CA_STATUS_OK; + } #ifdef WITH_BWT if (CAIsSupportedBlockwiseTransfer(endpoint->adapter)) { diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 6f167c0..ba23056 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c @@ -62,6 +62,11 @@ static CAQueueingThread_t *g_sendQueueHandle = NULL; #endif /** + * List of the endpoint that has a stack-owned IP address. + */ +static u_arraylist_t *g_ownIpEndpointList = NULL; + +/** * Network Packet Received Callback to CA. */ static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL; @@ -83,6 +88,8 @@ static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength); #endif +static void CAUpdateStoredIPAddressInfo(CANetworkStatus_t status); + #ifndef SINGLE_THREAD static CAResult_t CAIPInitializeQueueHandles(); @@ -108,11 +115,20 @@ CAResult_t CAIPInitializeQueueHandles() return CA_STATUS_OK; } + g_ownIpEndpointList = u_arraylist_create(); + if (!g_ownIpEndpointList) + { + OIC_LOG(ERROR, TAG, "Memory allocation failed! (g_ownIpEndpointList)"); + return CA_MEMORY_ALLOC_FAILED; + } + // Create send message queue g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t)); if (!g_sendQueueHandle) { - OIC_LOG(ERROR, TAG, "Memory allocation failed!"); + OIC_LOG(ERROR, TAG, "Memory allocation failed! (g_sendQueueHandle)"); + u_arraylist_free(&g_ownIpEndpointList); + g_ownIpEndpointList = NULL; return CA_MEMORY_ALLOC_FAILED; } @@ -123,6 +139,8 @@ CAResult_t CAIPInitializeQueueHandles() OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread"); OICFree(g_sendQueueHandle); g_sendQueueHandle = NULL; + u_arraylist_free(&g_ownIpEndpointList); + g_ownIpEndpointList = NULL; return CA_STATUS_FAILED; } @@ -134,12 +152,16 @@ void CAIPDeinitializeQueueHandles() CAQueueingThreadDestroy(g_sendQueueHandle); OICFree(g_sendQueueHandle); g_sendQueueHandle = NULL; + u_arraylist_free(&g_ownIpEndpointList); + g_ownIpEndpointList = NULL; } #endif // SINGLE_THREAD void CAIPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status) { + CAUpdateStoredIPAddressInfo(status); + if (g_networkChangeCallback) { g_networkChangeCallback(adapter, status); @@ -150,6 +172,40 @@ void CAIPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status) } } +static void CAUpdateStoredIPAddressInfo(CANetworkStatus_t status) +{ + if (CA_INTERFACE_UP == status) + { + OIC_LOG(DEBUG, TAG, "IP adapter status is on. Store the own IP address info"); + + CAEndpoint_t *eps = NULL; + uint32_t numOfEps = 0; + + CAResult_t res = CAGetIPInterfaceInformation(&eps, &numOfEps); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CAGetIPInterfaceInformation failed"); + return; + } + + for (size_t i = 0; i < numOfEps; i++) + { + u_arraylist_add(g_ownIpEndpointList, (void *)&eps[i]); + } + } + else // CA_INTERFACE_DOWN + { + OIC_LOG(DEBUG, TAG, "IP adapter status is off. Remove the own IP address info"); + + uint32_t len = u_arraylist_length(g_ownIpEndpointList); + for (uint32_t i = len; i > 0; i--) + { + CAEndpoint_t *ep = u_arraylist_remove(g_ownIpEndpointList, i - 1); + OICFree(ep); + } + } +} + #ifdef __WITH_DTLS__ static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength) { @@ -161,7 +217,6 @@ static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t } #endif - void CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data, size_t dataLength) { @@ -176,6 +231,31 @@ void CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data, } } +bool CAIPIsLocalEndpoint(const CAEndpoint_t *ep) +{ + char addr[MAX_ADDR_STR_SIZE_CA]; + OICStrcpy(addr, MAX_ADDR_STR_SIZE_CA, ep->addr); + + // drop the zone ID if the address of endpoint is IPv6. ifindex will be checked instead. + if ((ep->flags & CA_IPV6) && strchr(addr, '%')) + { + strtok(addr, "%"); + } + + size_t len = u_arraylist_length(g_ownIpEndpointList); + for (size_t i = 0; i < len; i++) + { + CAEndpoint_t *ownIpEp = u_arraylist_get(g_ownIpEndpointList, i); + if (!strcmp(addr, ownIpEp->addr) && ep->port == ownIpEp->port + && ep->ifindex == ownIpEp->ifindex) + { + return true; + } + } + + return false; +} + void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength, CAResult_t result) {