From 9fd22b1c194ddbfc31acabe5d38b5fb0649eb2e6 Mon Sep 17 00:00:00 2001 From: "hyuna0213.jo" Date: Mon, 7 Nov 2016 17:24:22 +0900 Subject: [PATCH] [IOT-1575] Update to manage connection state of tcp session If network interface is down, the socket of the connecting/connected state will be closed. Change-Id: I9f9cda2e3ab5672c336ed165ec4f189ab846f054 Signed-off-by: hyuna0213.jo Reviewed-on: https://gerrit.iotivity.org/gerrit/14067 Reviewed-by: jihwan seo Tested-by: jenkins-iotivity Reviewed-by: Jaehong Jo Reviewed-by: Dan Mihai Reviewed-by: Ashok Babu Channa --- resource/csdk/connectivity/inc/catcpadapter.h | 11 ++++ .../connectivity/src/tcp_adapter/catcpserver.c | 70 ++++++++++++---------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/resource/csdk/connectivity/inc/catcpadapter.h b/resource/csdk/connectivity/inc/catcpadapter.h index c719214..cb2a740 100644 --- a/resource/csdk/connectivity/inc/catcpadapter.h +++ b/resource/csdk/connectivity/inc/catcpadapter.h @@ -45,6 +45,16 @@ typedef enum CAProtocol } CAProtocol_t; /** + * TCP Connection State. + */ +typedef enum +{ + CONNECTING = 0, + CONNECTED, + DISCONNECTED +} CATCPConnectionState_t; + +/** * TCP Session Information for IPv4 TCP transport */ typedef struct @@ -57,6 +67,7 @@ typedef struct unsigned char tlsdata[18437]; /**< tls data(rfc5246: TLSCiphertext max (2^14+2048+5)) */ size_t tlsLen; /**< received tls data length */ CAProtocol_t protocol; /**< application-level protocol */ + CATCPConnectionState_t state; /**< current tcp session state */ } CATCPSessionInfo_t; /** diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c b/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c index a25ea76..ef277c7 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpserver.c @@ -100,7 +100,7 @@ static void CAFindReadyMessage(); static void CASelectReturned(fd_set *readFds); static void CAReceiveMessage(int fd); static void CAReceiveHandler(void *data); -static int CATCPCreateSocket(int family, CATCPSessionInfo_t *tcpServerInfo); +static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *tcpServerInfo); #define CHECKFD(FD) \ if (FD > caglobals.tcp.maxfd) \ @@ -141,6 +141,7 @@ static CAResult_t CARecv(CATCPSessionInfo_t *item, size_t length, int flags) else if (0 == len) { OIC_LOG(INFO, TAG, "Received disconnect from peer. Close connection"); + item->state = DISCONNECTED; return CA_DESTINATION_DISCONNECTED; } @@ -245,7 +246,7 @@ static void CAFindReadyMessage() { CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); - if (svritem && 0 <= svritem->fd) + if (svritem && 0 <= svritem->fd && CONNECTED == svritem->state) { FD_SET(svritem->fd, &readFds); } @@ -351,6 +352,7 @@ static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock) svritem->fd = sockfd; svritem->sep.endpoint.flags = flag; svritem->sep.endpoint.adapter = CA_ADAPTER_TCP; + svritem->state = CONNECTED; CAConvertAddrToName((struct sockaddr_storage *)&clientaddr, clientlen, svritem->sep.endpoint.addr, &svritem->sep.endpoint.port); @@ -804,7 +806,7 @@ static void CAReceiveMessage(int fd) } } -static void CAWakeUpForReadFdsUpdate(const char *host) +static ssize_t CAWakeUpForReadFdsUpdate(const char *host) { if (caglobals.tcp.connectionFds[1] != -1) { @@ -818,7 +820,9 @@ static void CAWakeUpForReadFdsUpdate(const char *host) { OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno)); } + return len; } + return -1; } static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t port, @@ -860,7 +864,7 @@ static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t return CA_STATUS_OK; } -static int CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem) +static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem) { VERIFY_NON_NULL_RET(svritem, TAG, "svritem", -1); @@ -872,8 +876,9 @@ static int CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem) if (-1 == fd) { OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno)); - return -1; + return CA_SOCKET_OPERATION_FAILED; } + svritem->fd = fd; // #2. convert address from string to binary. struct sockaddr_storage sa = { .ss_family = family }; @@ -881,8 +886,7 @@ static int CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem) svritem->sep.endpoint.port, &sa); if (CA_STATUS_OK != res) { - close(fd); - return -1; + return CA_SOCKET_OPERATION_FAILED; } // #3. set socket length. @@ -902,13 +906,18 @@ static int CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem) OIC_LOG_V(ERROR, TAG, "failed to connect socket, %s", strerror(errno)); CALogSendStateInfo(svritem->sep.endpoint.adapter, svritem->sep.endpoint.addr, svritem->sep.endpoint.port, 0, false, strerror(errno)); - close(fd); - return -1; + return CA_SOCKET_OPERATION_FAILED; } OIC_LOG(DEBUG, TAG, "connect socket success"); - CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr); - return fd; + svritem->state = CONNECTED; + CHECKFD(svritem->fd); + ssize_t len = CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr); + if (-1 == len) + { + return CA_SOCKET_OPERATION_FAILED; + } + return CA_STATUS_OK; } static int CACreateAcceptSocket(int family, CASocket_t *sock) @@ -1336,18 +1345,9 @@ CATCPSessionInfo_t *CAConnectTCPSession(const CAEndpoint_t *endpoint) svritem->sep.endpoint.port = endpoint->port; svritem->sep.endpoint.flags = endpoint->flags; svritem->sep.endpoint.ifindex = endpoint->ifindex; + svritem->state = CONNECTING; - // #2. create the socket and connect to TCP server - int family = (svritem->sep.endpoint.flags & CA_IPV6) ? AF_INET6 : AF_INET; - int fd = CATCPCreateSocket(family, svritem); - if (-1 == fd) - { - OICFree(svritem); - return NULL; - } - - // #3. add TCP connection info to list - svritem->fd = fd; + // #2. add TCP connection info to list oc_mutex_lock(g_mutexObjectList); if (caglobals.tcp.svrlist) { @@ -1363,9 +1363,14 @@ CATCPSessionInfo_t *CAConnectTCPSession(const CAEndpoint_t *endpoint) } oc_mutex_unlock(g_mutexObjectList); - CHECKFD(fd); + // #3. create the socket and connect to TCP server + int family = (svritem->sep.endpoint.flags & CA_IPV6) ? AF_INET6 : AF_INET; + if (CA_STATUS_OK != CATCPCreateSocket(family, svritem)) + { + return NULL; + } - // pass the connection information to CA Common Layer. + // #4. pass the connection information to CA Common Layer. if (g_connectionCallback) { g_connectionCallback(&(svritem->sep.endpoint), true); @@ -1386,17 +1391,18 @@ CAResult_t CADisconnectTCPSession(CATCPSessionInfo_t *svritem, size_t index) close(svritem->fd); svritem->fd = -1; OIC_LOG(DEBUG, TAG, "close socket"); + svritem->state = (CONNECTED == svritem->state) ? DISCONNECTED : svritem->state; + + // pass the connection information to CA Common Layer. + if (g_connectionCallback && DISCONNECTED == svritem->state) + { + g_connectionCallback(&(svritem->sep.endpoint), false); + } } u_arraylist_remove(caglobals.tcp.svrlist, index); OICFree(svritem->data); svritem->data = NULL; - // pass the connection information to CA Common Layer. - if (g_connectionCallback) - { - g_connectionCallback(&(svritem->sep.endpoint), false); - } - OICFree(svritem); svritem = NULL; @@ -1406,6 +1412,7 @@ CAResult_t CADisconnectTCPSession(CATCPSessionInfo_t *svritem, size_t index) void CATCPDisconnectAll() { oc_mutex_lock(g_mutexObjectList); + uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); CATCPSessionInfo_t *svritem = NULL; for (size_t i = 0; i < length; i++) @@ -1417,9 +1424,10 @@ void CATCPDisconnectAll() close(svritem->fd); OICFree(svritem->data); svritem->data = NULL; + svritem->state = (CONNECTED == svritem->state) ? DISCONNECTED : svritem->state; // pass the connection information to CA Common Layer. - if (g_connectionCallback) + if (g_connectionCallback && DISCONNECTED == svritem->state) { g_connectionCallback(&(svritem->sep.endpoint), false); } -- 2.7.4