[IOT-1575] Update to manage connection state of tcp session
authorhyuna0213.jo <hyuna0213.jo@samsung.com>
Mon, 7 Nov 2016 08:24:22 +0000 (17:24 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Mon, 12 Dec 2016 08:26:18 +0000 (08:26 +0000)
If network interface is down, the socket of the connecting/connected
state will be closed.

Change-Id: I9f9cda2e3ab5672c336ed165ec4f189ab846f054
Signed-off-by: hyuna0213.jo <hyuna0213.jo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14067
Reviewed-by: jihwan seo <jihwan.seo@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jaehong Jo <jaehong.jo@samsung.com>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
resource/csdk/connectivity/inc/catcpadapter.h
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c

index c719214..cb2a740 100644 (file)
@@ -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;
 
 /**
index a25ea76..ef277c7 100644 (file)
@@ -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);
             }