CA API to retrieve the some internal values in TCP socket 25/211025/2
authorAmit Singh <amit.s.r@samsung.com>
Tue, 16 Jul 2019 14:59:13 +0000 (20:29 +0530)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Thu, 1 Aug 2019 23:22:12 +0000 (08:22 +0900)
https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/537/commits/cebbe139c44e3001a7a4ad4a09a80ceb2478ecbd
(cherry-picked from cebbe139c44e3001a7a4ad4a09a80ceb2478ecbd)

Change-Id: Ibb9139afc3e2da1b88288c1f6a14c8676b23adbf
Signed-off-by: Amit Singh <amit.s.r@samsung.com>
Signed-off-by: Kush Agrawal <kush.agrawal@samsung.com>
Signed-off-by: Sudipto Bal <sudipto.bal@samsung.com>
resource/csdk/connectivity/api/cautilinterface.h
resource/csdk/connectivity/inc/catcpadapter.h
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c
resource/csdk/connectivity/util/src/cautilinterface.c

index 28fc94e..8bd3a27 100644 (file)
@@ -61,6 +61,71 @@ typedef struct
     CMConfigureInfo_t cmInfo;
 } CAUtilConfig_t;
 
+#define MAX_IP_LENGTH 46
+
+typedef struct
+{
+    /* These 4 values are Kernel dependent and can be extracted only when Kernel is
+    built with enabling to monitor these values*/
+    u_int32_t tcpi_snd_nxt;
+    u_int32_t tcpi_rcv_nxt;
+    u_int32_t tcpi_rcv_wnd;
+    u_int8_t tcpi_rcv_wscale;
+    /*....*/
+    u_int8_t tcpi_src_addr[MAX_IP_LENGTH];
+    u_int32_t tcpi_src_port;
+    u_int8_t tcpi_dst_addr[MAX_IP_LENGTH];
+    u_int32_t tcpi_dst_port;
+    u_int32_t ip_version;
+    void* info;
+} TCPHeaderInfo;
+
+typedef struct
+{
+    u_int8_t tcpi_state;
+    u_int8_t tcpi_ca_state;
+    u_int8_t tcpi_retransmits;
+    u_int8_t tcpi_probes;
+    u_int8_t tcpi_backoff;
+    u_int8_t tcpi_options;
+    u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+
+    /* TCP Keep Alive Offload */
+    u_int32_t tcpi_snd_nxt;
+    u_int32_t tcpi_rcv_nxt;
+    u_int32_t tcpi_rcv_wnd;
+
+    u_int32_t tcpi_rto;
+    u_int32_t tcpi_ato;
+    u_int32_t tcpi_snd_mss;
+    u_int32_t tcpi_rcv_mss;
+
+    u_int32_t tcpi_unacked;
+    u_int32_t tcpi_sacked;
+    u_int32_t tcpi_lost;
+    u_int32_t tcpi_retrans;
+    u_int32_t tcpi_fackets;
+
+    /* Times. */
+    u_int32_t tcpi_last_data_sent;
+    u_int32_t tcpi_last_ack_sent;
+    u_int32_t tcpi_last_data_recv;
+    u_int32_t tcpi_last_ack_recv;
+
+    /* Metrics. */
+    u_int32_t tcpi_pmtu;
+    u_int32_t tcpi_rcv_ssthresh;
+    u_int32_t tcpi_rtt;
+    u_int32_t tcpi_rttvar;
+    u_int32_t tcpi_snd_ssthresh;
+    u_int32_t tcpi_snd_cwnd;
+    u_int32_t tcpi_advmss;
+    u_int32_t tcpi_reordering;
+    u_int32_t tcpi_rcv_rtt;
+    u_int32_t tcpi_rcv_space;
+    u_int32_t tcpi_total_retrans;
+} TCPInfo;
+
 /**
  * Callback function type for connection status changes delivery.
  * @param[out]   info           Remote endpoint information.
@@ -359,6 +424,7 @@ void CAUtilSkipTCPCloseOnInterfaceDown(bool state);
 
 CAResult_t CAUtilStartGattServer();
 CAResult_t CAUtilStopGattServer();
+CAResult_t CAGetTCPIPHeader(CATransportAdapter_t adapter, int flag, TCPHeaderInfo* info);
 
 #ifdef __cplusplus
 } /* extern "C" */
index 00f1cf3..9b17ff7 100644 (file)
@@ -30,6 +30,7 @@
 #include "cathreadpool.h"
 #include "cainterface.h"
 #include <coap/pdu.h>
+#include "cautilinterface.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -204,6 +205,12 @@ CAResult_t CAStopTCP();
  */
 void CATerminateTCP();
 
+/**
+ * Gets TCP Header Information
+ * @return  ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAGetTCPIPHeaderInfo(CATransportFlags_t flag, TCPHeaderInfo* tcpHeaderInfo);
+
 #ifdef TCP_ADAPTER
 /**
  * Set connection status changes callback to process KeepAlive.
@@ -211,6 +218,8 @@ void CATerminateTCP();
  * @param[in]   ConnHandler     Connection status changes callback.
  */
 void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectionCallback ConnHandler);
+
+
 #endif
 
 #ifdef __cplusplus
index ea55c74..c97c5c2 100644 (file)
  *
  ******************************************************************/
 
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
 
 #ifndef __STDC_FORMAT_MACROS
 #define __STDC_FORMAT_MACROS
@@ -39,6 +46,7 @@
 #include "caremotehandler.h"
 #include "logger.h"
 #include "oic_malloc.h"
+
 #ifdef __WITH_TLS__
 #include "ca_adapter_net_ssl.h"
 #endif
@@ -63,6 +71,9 @@ typedef struct
 
 #define CA_TCP_SELECT_TIMEOUT 10
 
+#define CA_IPV4_VERSION 4
+
+#define CA_IPV6_VERSION 6
 /**
  * Mutex to synchronize TCP adapter access.
  */
@@ -815,6 +826,149 @@ void CADataDestroyer(void *data, uint32_t size)
     CAFreeTCPData(TCPData);
 }
 
+void CAGetTCPLocalIP(CATransportFlags_t flag, char* localIP)
+{
+    //int targetPort;
+    char targetIP[MAX_IP_LENGTH];
+    memset(&targetIP, 0x00, sizeof(targetIP));
+    struct ifaddrs *ifp = NULL;
+    struct ifaddrs *ifa = NULL;
+
+    if (-1 == getifaddrs(&ifp)) {
+        return;
+    }
+
+    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
+    {
+        if (!ifa->ifa_addr) {
+            continue;
+        }
+        int family = ifa->ifa_addr->sa_family;
+
+        if (CA_IPV6 & flag) {
+            if ((ifa->ifa_flags & IFF_LOOPBACK) || AF_INET6 != family) {
+                continue;
+            }
+            struct sockaddr_in6 *in = (struct sockaddr_in6*) ifa->ifa_addr;
+            inet_ntop(AF_INET6, &in->sin6_addr, targetIP, MAX_IP_LENGTH);
+            //targetPort = ntohs(in->sin6_port);
+        } else if (CA_IPV4 & flag) {
+            if ((ifa->ifa_flags & IFF_LOOPBACK) || AF_INET != family) {
+                continue;
+            }
+            struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr;
+            inet_ntop(AF_INET, &in->sin_addr, targetIP, MAX_IP_LENGTH);
+            //targetPort = ntohs(in->sin_port);
+        }
+        break;
+    }
+
+    strncpy(localIP, targetIP, MAX_IP_LENGTH);
+       //*localport = targetPort;
+    OIC_LOG_V(DEBUG, TAG, "src_addr = %s", localIP);
+}
+
+int CAGetSocketInformation(u_int8_t* destIP, u_int32_t *destPort){
+
+    oc_mutex_lock(g_mutexAdapter);
+    uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+    for (size_t i = 0; i < length; i++)
+    {
+        CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(
+                caglobals.tcp.svrlist, i);
+        if (!svritem)
+        {
+            continue;
+        }
+
+        if (svritem->state == CONNECTED)
+        {
+            strncpy((char *)destIP, svritem->sep.endpoint.addr, MAX_IP_LENGTH);
+            *destPort = svritem->sep.endpoint.port;
+            OIC_LOG_V(INFO, TAG, "Dest Ip : %s, Dest Port : %d", destIP, *destPort);
+            oc_mutex_unlock(g_mutexAdapter);
+            return svritem->fd;
+        }
+    }
+    oc_mutex_unlock(g_mutexAdapter);
+    return -1;
+}
+
+CAResult_t CAGetTCPIPHeaderInfo(CATransportFlags_t flag, TCPHeaderInfo* tcpHeaderInfo)
+{
+    CAResult_t res = CA_STATUS_OK;
+    VERIFY_NON_NULL(tcpHeaderInfo, TAG, "tcpHeaderInfo");
+
+    TCPInfo info;
+    int len = sizeof(info);
+
+    OIC_LOG_V(INFO, TAG, "Flags passed is = %d", flag);
+    int socket_fd;
+    //Get socketfd, destination ip and port.
+    socket_fd = CAGetSocketInformation(tcpHeaderInfo->tcpi_dst_addr, &(tcpHeaderInfo->tcpi_dst_port));
+    if(socket_fd == -1){
+        OIC_LOG(ERROR, TAG, "getsocket Failed");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(INFO, TAG, "Socket Interface is = %d", socket_fd);
+    OIC_LOG_V(INFO, TAG, "Port Number is = %d", tcpHeaderInfo->tcpi_dst_port);
+
+    if (getsockopt(socket_fd, SOL_TCP, TCP_INFO, (void *)&info, (socklen_t *)&len) == 0)
+    {
+        OIC_LOG(DEBUG, TAG, "getsockopt Success");
+        unsigned int source_port = 0;
+        struct sockaddr address;
+        socklen_t source_len = sizeof(address);;
+        char source_ip[MAX_IP_LENGTH];
+        bzero(&source_ip, MAX_IP_LENGTH);
+
+        // Get Local Ip and Port
+        if (CA_IPV6 & flag) {
+            struct sockaddr_in6 *sourceAddrInfo;
+            getsockname(socket_fd, &address, &source_len);
+            sourceAddrInfo = (struct sockaddr_in6*)&address;
+            inet_ntop(AF_INET6, &sourceAddrInfo->sin6_addr, source_ip, sizeof(source_ip));
+            source_port = ntohs(sourceAddrInfo->sin6_port);
+            tcpHeaderInfo->ip_version = CA_IPV6_VERSION;
+        } else if (CA_IPV4 & flag) {
+            struct sockaddr_in *sourceAddrInfo;
+            getsockname(socket_fd, &address, &source_len);
+            sourceAddrInfo = (struct sockaddr_in*)&address;
+            inet_ntop(AF_INET, &sourceAddrInfo->sin_addr, source_ip, sizeof(source_ip));
+            source_port = ntohs(sourceAddrInfo->sin_port);
+            tcpHeaderInfo->ip_version = CA_IPV4_VERSION;
+        }
+
+        //GET Local IP and port
+        strncpy((char *)tcpHeaderInfo->tcpi_src_addr, source_ip, MAX_IP_LENGTH);
+        tcpHeaderInfo->tcpi_src_port = source_port;
+        tcpHeaderInfo->tcpi_rcv_nxt = info.tcpi_rcv_nxt;
+        tcpHeaderInfo->tcpi_snd_nxt = info.tcpi_snd_nxt;
+        tcpHeaderInfo->tcpi_rcv_wnd = info.tcpi_rcv_wnd;
+        tcpHeaderInfo->tcpi_rcv_wscale = info.tcpi_rcv_wscale;
+    }
+    else {
+        OIC_LOG(INFO, TAG, "getsockopt Fail");
+        OIC_LOG_V(INFO, TAG, "getsockopt error %s", strerror(errno));
+        res = CA_SOCKET_OPERATION_FAILED;
+    }
+
+    OIC_LOG(INFO, TAG, "========tcpHeaderInfo=========");
+    OIC_LOG_V(INFO, TAG, "src_addr = %s", tcpHeaderInfo->tcpi_src_addr);
+    OIC_LOG_V(INFO, TAG, "src_port = %d", tcpHeaderInfo->tcpi_src_port);
+    OIC_LOG_V(INFO, TAG, "dst_addr = %s", tcpHeaderInfo->tcpi_dst_addr);
+    OIC_LOG_V(INFO, TAG, "dst_port = %d", tcpHeaderInfo->tcpi_dst_port);
+    OIC_LOG_V(INFO, TAG, "version = %d", tcpHeaderInfo->ip_version);
+    OIC_LOG_V(INFO, TAG, "seq_num = 0x%02x", tcpHeaderInfo->tcpi_snd_nxt);
+    OIC_LOG_V(INFO, TAG, "ack_num = 0x%02x", tcpHeaderInfo->tcpi_rcv_nxt);
+    OIC_LOG_V(INFO, TAG, "wnd = 0x%02x", tcpHeaderInfo->tcpi_rcv_wnd);
+    OIC_LOG_V(INFO, TAG, "wscale = %d", tcpHeaderInfo->tcpi_rcv_wscale);
+    OIC_LOG(INFO, TAG, "========================");
+
+    return res;
+}
+
 #ifdef SINGLE_THREAD
 size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size)
 {
index 4724dfc..d009987 100644 (file)
@@ -499,3 +499,19 @@ CAResult_t CAUtilStopGattServer()
 #endif
        return res;
 }
+
+CAResult_t CAGetTCPIPHeader(CATransportAdapter_t adapter, int flag, TCPHeaderInfo* info)
+{
+    CAResult_t res = CA_STATUS_OK;
+#ifdef TCP_ADAPTER
+    if (CA_ADAPTER_TCP & adapter) {
+        res = CAGetTCPIPHeaderInfo(flag,info);
+    }
+    else
+        res = CA_NOT_SUPPORTED;
+#else
+    res = CA_NOT_SUPPORTED;
+    OIC_LOG(DEBUG, TAG, "Not supported!");
+#endif
+    return res;
+}