The TCP port number discovery based UDP multicast message
authorhyuna0213.jo <hyuna0213.jo@samsung.com>
Thu, 31 Mar 2016 08:21:06 +0000 (17:21 +0900)
committerJon A. Cruz <jon@joncruz.org>
Wed, 27 Apr 2016 06:00:46 +0000 (06:00 +0000)
The TCP port number will be part of the discovery payload.
so the response to the UDP multicast message, should be an UDP unicast
reply containing the TCP port number if TCP adapter is activated.
After receiving the discovery response, the client can use TCP port
number to communicate with the server via CoAP/TCP.

- added tcp port value in policy of discovery payload
- the dynamic use of tcp server port in TCP adapter
- TCP adapter changes to support IPv6

Change-Id: Ie93361abec0287f0f600a791a58e41cf5b381892
Signed-off-by: hyuna0213.jo <hyuna0213.jo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/7483
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jon@joncruz.org>
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocpayloadparse.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocstack.c
resource/include/OCSerialization.h

index 464f24b..a2a3fd3 100644 (file)
@@ -514,6 +514,8 @@ typedef struct
     struct tcpsockets
     {
         void *threadpool;       /**< threadpool between Initialize and Start */
+        CASocket_t ipv4;        /**< IPv4 accept socket */
+        CASocket_t ipv6;        /**< IPv6 accept socket */
         void *svrlist;          /**< unicast IPv4 TCP server information*/
         int selectTimeout;      /**< in seconds */
         int listenBacklog;      /**< backlog counts*/
@@ -523,6 +525,7 @@ typedef struct
         bool started;           /**< the TCP adapter has started */
         bool terminate;         /**< the TCP adapter needs to stop */
         bool ipv4tcpenabled;    /**< IPv4 TCP enabled by OCInit flags */
+        bool ipv6tcpenabled;    /**< IPv6 TCP enabled by OCInit flags */
     } tcp;
 #endif
 } CAGlobals_t;
index 1108877..64aa5d7 100644 (file)
@@ -202,6 +202,10 @@ void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectedCallback ConnHandler,
 
 static void CAInitializeTCPGlobals()
 {
+    caglobals.tcp.ipv4.fd = -1;
+    caglobals.tcp.ipv4.port = 0;
+    caglobals.tcp.ipv6.fd = -1;
+    caglobals.tcp.ipv6.port = 0;
     caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
     caglobals.tcp.svrlist = NULL;
@@ -217,6 +221,7 @@ static void CAInitializeTCPGlobals()
     }
 
     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
+    caglobals.tcp.ipv6tcpenabled = flags & CA_IPV6;
 }
 
 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
index b486540..b266815 100644 (file)
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/select.h>
 #include <sys/ioctl.h>
+#include <sys/poll.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <sys/types.h>
 #include <fcntl.h>
-#include <sys/select.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <errno.h>
-#include <sys/poll.h>
 
 #ifndef WITH_ARDUINO
 #include <sys/socket.h>
 #define TCP_MAX_HEADER_LEN  6
 
 /**
- * Accept server file descriptor.
- */
-static int g_acceptServerFD = -1;
-
-/**
  * Mutex to synchronize device object list.
  */
 static ca_mutex g_mutexObjectList = NULL;
@@ -95,8 +89,8 @@ static CAResult_t CATCPCreateMutex();
 static void CATCPDestroyMutex();
 static CAResult_t CATCPCreateCond();
 static void CATCPDestroyCond();
-static CAResult_t CACreateAcceptSocket();
-static void CAAcceptConnection();
+static int CACreateAcceptSocket(int family, CASocket_t *sock);
+static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock);
 static void CAFindReadyMessage();
 static void CASelectReturned(fd_set *readFds, int ret);
 static void CAReceiveMessage(int fd);
@@ -178,9 +172,13 @@ static void CAFindReadyMessage()
 
     FD_ZERO(&readFds);
 
-    if (-1 != g_acceptServerFD)
+    if (-1 != caglobals.tcp.ipv4.fd)
+    {
+        FD_SET(caglobals.tcp.ipv4.fd, &readFds);
+    }
+    if (-1 != caglobals.tcp.ipv6.fd)
     {
-        FD_SET(g_acceptServerFD, &readFds);
+        FD_SET(caglobals.tcp.ipv6.fd, &readFds);
     }
     if (-1 != caglobals.tcp.shutdownFds[0])
     {
@@ -223,11 +221,16 @@ static void CAFindReadyMessage()
 
 static void CASelectReturned(fd_set *readFds, int ret)
 {
-    (void)ret;
+    VERIFY_NON_NULL_VOID(readFds, TAG, "readFds is NULL");
 
-    if (g_acceptServerFD != -1 && FD_ISSET(g_acceptServerFD, readFds))
+    if (caglobals.tcp.ipv4.fd != -1 && FD_ISSET(caglobals.tcp.ipv4.fd, readFds))
+    {
+        CAAcceptConnection(CA_IPV4, &caglobals.tcp.ipv4);
+        return;
+    }
+    else if (caglobals.tcp.ipv6.fd != -1 && FD_ISSET(caglobals.tcp.ipv6.fd, readFds))
     {
-        CAAcceptConnection();
+        CAAcceptConnection(CA_IPV6, &caglobals.tcp.ipv6);
         return;
     }
     else if (-1 != caglobals.tcp.connectionFds[0] &&
@@ -264,13 +267,14 @@ static void CASelectReturned(fd_set *readFds, int ret)
     }
 }
 
-static void CAAcceptConnection()
+static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock)
 {
+    VERIFY_NON_NULL_VOID(sock, TAG, "sock is NULL");
+
     struct sockaddr_storage clientaddr;
     socklen_t clientlen = sizeof (struct sockaddr_in);
 
-    int sockfd = accept(g_acceptServerFD, (struct sockaddr *)&clientaddr,
-                        &clientlen);
+    int sockfd = accept(sock->fd, (struct sockaddr *)&clientaddr, &clientlen);
     if (-1 != sockfd)
     {
         CATCPSessionInfo_t *svritem =
@@ -283,6 +287,7 @@ static void CAAcceptConnection()
         }
 
         svritem->fd = sockfd;
+        svritem->sep.endpoint.flags = flag;
         CAConvertAddrToName((struct sockaddr_storage *)&clientaddr, clientlen,
                             (char *) &svritem->sep.endpoint.addr, &svritem->sep.endpoint.port);
 
@@ -397,94 +402,171 @@ static void CAWakeUpForReadFdsUpdate(const char *host)
     }
 }
 
+static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t port,
+                                         struct sockaddr_storage *sockaddr)
+{
+    struct addrinfo *addrs = NULL;
+    struct addrinfo hints = { .ai_family = family,
+                              .ai_protocol   = IPPROTO_TCP,
+                              .ai_socktype = SOCK_STREAM,
+                              .ai_flags = AI_NUMERICHOST };
+
+    int r = getaddrinfo(host, NULL, &hints, &addrs);
+    if (r)
+    {
+        if (EAI_SYSTEM == r)
+        {
+            OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: errno %s", strerror(errno));
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: %s", gai_strerror(r));
+        }
+        freeaddrinfo(addrs);
+        return CA_STATUS_FAILED;
+    }
+    // assumption: in this case, getaddrinfo will only return one addrinfo
+    // or first is the one we want.
+    if (addrs[0].ai_family == AF_INET6)
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
+        ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
+    }
+    else
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
+        ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
+    }
+    freeaddrinfo(addrs);
+    return CA_STATUS_OK;
+}
+
 static int CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem)
 {
-    // create tcp socket
+    // #1. create tcp socket.
     int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
     if (-1 == fd)
     {
         OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
-        goto exit;
+        return -1;
     }
 
+    // #2. convert address from string to binary.
     struct sockaddr_storage sa = { .ss_family = family };
-    CAConvertNameToAddr(svritem->sep.endpoint.addr, svritem->sep.endpoint.port, &sa);
-    socklen_t socklen = sizeof (struct sockaddr_in);
+    CAResult_t res = CATCPConvertNameToAddr(family, svritem->sep.endpoint.addr,
+                                            svritem->sep.endpoint.port, &sa);
+    if (CA_STATUS_OK != res)
+    {
+        close(fd);
+        return -1;
+    }
 
-    // connect to TCP server
-    int ret = connect(fd, (struct sockaddr *)&sa, socklen);
-    if (0 == ret)
+    // #3. set socket length.
+    socklen_t socklen;
+    if (sa.ss_family == AF_INET6)
     {
-        OIC_LOG(DEBUG, TAG, "connect socket success");
-        CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr);
+        struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sa;
+        if (!sock6->sin6_scope_id)
+        {
+            sock6->sin6_scope_id = svritem->sep.endpoint.interface;
+        }
+        socklen = sizeof(struct sockaddr_in6);
     }
     else
     {
-        OIC_LOG(ERROR, TAG, "failed to connect socket");
-        goto exit;
+        socklen = sizeof(struct sockaddr_in);
     }
 
-    return fd;
-
-exit:
-    if (fd >= 0)
+    // #4. connect to remote server device.
+    if (connect(fd, (struct sockaddr *)&sa, socklen) < 0)
     {
+        OIC_LOG_V(ERROR, TAG, "failed to connect socket, %s", strerror(errno));
         close(fd);
+        return -1;
     }
-    return -1;
+
+    OIC_LOG(DEBUG, TAG, "connect socket success");
+    CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr);
+    return fd;
 }
 
-static CAResult_t CACreateAcceptSocket()
+static int CACreateAcceptSocket(int family, CASocket_t *sock)
 {
-    if (g_acceptServerFD != -1)
+    VERIFY_NON_NULL_RET(sock, TAG, "sock", -1);
+
+    if (sock->fd != -1)
     {
         OIC_LOG(DEBUG, TAG, "accept socket created already");
-        return CA_STATUS_OK;
+        return sock->fd;
     }
 
-    int reuse = 1;
-    struct sockaddr_in server = { .sin_addr.s_addr = INADDR_ANY,
-                                  .sin_family = AF_INET,
-                                  .sin_port = htons(SERVER_PORT),
-                                  .sin_zero = { 0 } };
+    socklen_t socklen;
+    struct sockaddr_storage server = { .ss_family = family };
 
-    g_acceptServerFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (g_acceptServerFD < 0)
+    int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
+    if (fd < 0)
     {
         OIC_LOG(ERROR, TAG, "Failed to create socket");
         goto exit;
     }
 
-    if (-1 == setsockopt(g_acceptServerFD, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
+    if (family == AF_INET6)
+    {
+        // the socket is re‐stricted to sending and receiving IPv6 packets only.
+        int on = 1;
+        if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
+            goto exit;
+        }
+        ((struct sockaddr_in6 *)&server)->sin6_port = htons(sock->port);
+        socklen = sizeof (struct sockaddr_in6);
+    }
+    else
+    {
+        ((struct sockaddr_in *)&server)->sin_port = htons(sock->port);
+        socklen = sizeof (struct sockaddr_in);
+    }
+
+    int reuse = 1;
+    if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
     {
         OIC_LOG(ERROR, TAG, "setsockopt SO_REUSEADDR");
         goto exit;
     }
 
-    int serverlen = sizeof(server);
-    if (-1 == bind(g_acceptServerFD, (struct sockaddr *)&server, serverlen))
+    if (-1 == bind(fd, (struct sockaddr *)&server, socklen))
     {
-        OIC_LOG(ERROR, TAG, "bind() error");
+        OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
         goto exit;
     }
 
-    if (listen(g_acceptServerFD, caglobals.tcp.listenBacklog) != 0)
+    if (listen(fd, caglobals.tcp.listenBacklog) != 0)
     {
         OIC_LOG(ERROR, TAG, "listen() error");
         goto exit;
     }
 
-    CHECKFD(g_acceptServerFD);
+    if (!sock->port)  // return the assigned port
+    {
+        if (-1 == getsockname(fd, (struct sockaddr *)&server, &socklen))
+        {
+            OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno));
+            goto exit;
+        }
+        sock->port = ntohs(family == AF_INET6 ?
+                      ((struct sockaddr_in6 *)&server)->sin6_port :
+                      ((struct sockaddr_in *)&server)->sin_port);
+    }
 
-    return CA_STATUS_OK;
+    return fd;
 
 exit:
-    if (g_acceptServerFD >= 0)
+    if (fd >= 0)
     {
-        close(g_acceptServerFD);
-        g_acceptServerFD = -1;
+        close(fd);
     }
-    return CA_STATUS_FAILED;
+    return -1;
 }
 
 static void CAInitializePipe(int *fds)
@@ -529,6 +611,10 @@ CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool)
     {
         caglobals.tcp.ipv4tcpenabled = true;    // only needed to run CA tests
     }
+    if (!caglobals.tcp.ipv6tcpenabled)
+    {
+        caglobals.tcp.ipv6tcpenabled = true;    // only needed to run CA tests
+    }
 
     CAResult_t res = CATCPCreateMutex();
     if (CA_STATUS_OK == res)
@@ -550,12 +636,15 @@ CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool)
 
     if (caglobals.server)
     {
-        res = CACreateAcceptSocket();
-        if (CA_STATUS_OK != res)
-        {
-            OIC_LOG(ERROR, TAG, "failed to create accept socket");
-            return res;
-        }
+        caglobals.tcp.ipv4.fd = CACreateAcceptSocket(AF_INET, &caglobals.tcp.ipv4);
+        CHECKFD(caglobals.tcp.ipv4.fd);
+        caglobals.tcp.ipv6.fd = CACreateAcceptSocket(AF_INET6, &caglobals.tcp.ipv6);
+        CHECKFD(caglobals.tcp.ipv6.fd);
+
+        OIC_LOG_V(DEBUG, TAG, "IPv4 socket fd=%d, port=%d",
+                  caglobals.tcp.ipv4.fd, caglobals.tcp.ipv4.port);
+        OIC_LOG_V(DEBUG, TAG, "IPv6 socket fd=%d, port=%d",
+                  caglobals.tcp.ipv6.fd, caglobals.tcp.ipv6.port);
     }
 
     // create pipe for fast shutdown
@@ -609,10 +698,16 @@ void CATCPStopServer()
     // mutex unlock
     ca_mutex_unlock(g_mutexObjectList);
 
-    if (-1 != g_acceptServerFD)
+    if (-1 != caglobals.tcp.ipv4.fd)
+    {
+        close(caglobals.tcp.ipv4.fd);
+        caglobals.tcp.ipv4.fd = -1;
+    }
+
+    if (-1 != caglobals.tcp.ipv6.fd)
     {
-        close(g_acceptServerFD);
-        g_acceptServerFD = -1;
+        close(caglobals.tcp.ipv6.fd);
+        caglobals.tcp.ipv6.fd = -1;
     }
 
     CATCPDisconnectAll();
@@ -666,8 +761,8 @@ static size_t CACheckPayloadLength(const void *data, size_t dlen)
     return payloadLen;
 }
 
-static void sendData(const CAEndpoint_t *endpoint,
-                     const void *data, size_t dlen)
+static void sendData(const CAEndpoint_t *endpoint, const void *data,
+                     size_t dlen, const char *fam)
 {
     // #1. get TCP Server object from list
     size_t index = 0;
@@ -723,7 +818,7 @@ static void sendData(const CAEndpoint_t *endpoint,
         remainLen -= len;
     } while (remainLen > 0);
 
-    OIC_LOG_V(INFO, TAG, "unicast ipv4tcp sendTo is successful: %zu bytes", dlen);
+    OIC_LOG_V(INFO, TAG, "unicast %stcp sendTo is successful: %zu bytes", fam, dlen);
 }
 
 void CATCPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
@@ -734,9 +829,13 @@ void CATCPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
 
     if (!isMulticast)
     {
-        if (caglobals.tcp.ipv4tcpenabled && (endpoint->adapter & CA_ADAPTER_TCP))
+        if (caglobals.tcp.ipv6tcpenabled && (endpoint->flags & CA_IPV6))
         {
-            sendData(endpoint, data, datalen);
+            sendData(endpoint, data, datalen, "ipv6");
+        }
+        if (caglobals.tcp.ipv4tcpenabled && (endpoint->flags & CA_IPV4))
+        {
+            sendData(endpoint, data, datalen, "ipv4");
         }
     }
 }
@@ -762,41 +861,41 @@ CATCPSessionInfo_t *CAConnectTCPSession(const CAEndpoint_t *endpoint)
     }
     memcpy(svritem->sep.endpoint.addr, endpoint->addr, sizeof(svritem->sep.endpoint.addr));
     svritem->sep.endpoint.port = endpoint->port;
+    svritem->sep.endpoint.flags = endpoint->flags;
+    svritem->sep.endpoint.interface = endpoint->interface;
 
     // #2. create the socket and connect to TCP server
-    if (caglobals.tcp.ipv4tcpenabled)
+    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;
+    ca_mutex_lock(g_mutexObjectList);
+    if (caglobals.tcp.svrlist)
     {
-        int fd = CATCPCreateSocket(AF_INET, svritem);
-        if (-1 == fd)
+        bool res = u_arraylist_add(caglobals.tcp.svrlist, svritem);
+        if (!res)
         {
+            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+            close(svritem->fd);
             OICFree(svritem);
+            ca_mutex_unlock(g_mutexObjectList);
             return NULL;
         }
+    }
+    ca_mutex_unlock(g_mutexObjectList);
 
-        // #3. add TCP connection info to list
-        svritem->fd = fd;
-        ca_mutex_lock(g_mutexObjectList);
-        if (caglobals.tcp.svrlist)
-        {
-            bool res = u_arraylist_add(caglobals.tcp.svrlist, svritem);
-            if (!res)
-            {
-                OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
-                close(svritem->fd);
-                OICFree(svritem);
-                ca_mutex_unlock(g_mutexObjectList);
-                return NULL;
-            }
-        }
-        ca_mutex_unlock(g_mutexObjectList);
-
-        CHECKFD(fd);
+    CHECKFD(fd);
 
-        // pass the connection information to RI for keepalive.
-        if (g_keepaliveCallback)
-        {
-            g_keepaliveCallback(svritem->sep.endpoint.addr, svritem->sep.endpoint.port, true);
-        }
+    // pass the connection information to RI for keepalive.
+    if (g_keepaliveCallback)
+    {
+        g_keepaliveCallback(svritem->sep.endpoint.addr, svritem->sep.endpoint.port, true);
     }
 
     return svritem;
@@ -848,8 +947,7 @@ void CATCPDisconnectAll()
     ca_mutex_unlock(g_mutexObjectList);
 }
 
-CATCPSessionInfo_t *CAGetTCPSessionInfoFromEndpoint(const CAEndpoint_t *endpoint,
-                                                    size_t *index)
+CATCPSessionInfo_t *CAGetTCPSessionInfoFromEndpoint(const CAEndpoint_t *endpoint, size_t *index)
 {
     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", NULL);
     VERIFY_NON_NULL_RET(index, TAG, "index is NULL", NULL);
@@ -867,7 +965,8 @@ CATCPSessionInfo_t *CAGetTCPSessionInfoFromEndpoint(const CAEndpoint_t *endpoint
 
         if (!strncmp(svritem->sep.endpoint.addr, endpoint->addr,
                      sizeof(svritem->sep.endpoint.addr))
-                && (svritem->sep.endpoint.port == endpoint->port))
+                && (svritem->sep.endpoint.port == endpoint->port)
+                && (svritem->sep.endpoint.flags & endpoint->flags))
         {
             *index = i;
             return svritem;
index 8354eb9..fdcaf15 100755 (executable)
@@ -223,7 +223,7 @@ OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData);
 void OCSecurityPayloadDestroy(OCSecurityPayload* payload);
 
 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
-        uint16_t port);
+                                   uint16_t securePort, uint16_t tcpPort);
 void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res);
 bool OCResourcePayloadAddStringLL(OCStringLL **payload, const char* type);
 
index b992d7e..61b5438 100644 (file)
@@ -197,6 +197,9 @@ extern "C" {
 /** Port. */
 #define OC_RSRVD_HOSTING_PORT           "port"
 
+/** TCP Port. */
+#define OC_RSRVD_TCP_PORT               "tcp"
+
 /** For Server instance ID.*/
 #define OC_RSRVD_SERVER_INSTANCE_ID     "sid"
 
@@ -386,10 +389,10 @@ typedef enum
     OC_FLAG_SECURE     = (1 << 4),
 
     /** IPv4 & IPv6 auto-selection is the default.*/
-    /** IP adapter only.*/
+    /** IP & TCP adapter only.*/
     OC_IP_USE_V6       = (1 << 5),
 
-    /** IP adapter only.*/
+    /** IP & TCP adapter only.*/
     OC_IP_USE_V4       = (1 << 6),
 
     /** internal use only.*/
@@ -1070,6 +1073,9 @@ typedef struct OCResourcePayload
     uint8_t bitmap;
     bool secure;
     uint16_t port;
+#ifdef TCP_ADAPTER
+    uint16_t tcpPort;
+#endif
     struct OCResourcePayload* next;
 } OCResourcePayload;
 
index 5486e9b..0cccc05 100755 (executable)
@@ -1350,7 +1350,8 @@ OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, si
     return NULL;
 }
 
-static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
+static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t securePort,
+                                         uint16_t tcpPort)
 {
     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
     if (!pl)
@@ -1445,15 +1446,17 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
 
     pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
-    pl->port = port;
-
+    pl->port = securePort;
+#ifdef TCP_ADAPTER
+    pl->tcpPort = tcpPort;
+#endif
     return pl;
 }
 
 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
-        uint16_t port)
+                                   uint16_t securePort, uint16_t tcpPort)
 {
-    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
+    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, securePort, tcpPort));
 }
 
 bool OCResourcePayloadAddStringLL(OCStringLL **stringLL, const char *value)
index c187f71..ae90763 100644 (file)
@@ -360,6 +360,14 @@ static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload *payload, uint8_t *o
                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure port value");
             }
 
+#ifdef TCP_ADAPTER
+            err |= cbor_encode_text_string(&policyMap, OC_RSRVD_TCP_PORT,
+                                           sizeof(OC_RSRVD_TCP_PORT) - 1);
+            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port tag");
+            err |= cbor_encode_uint(&policyMap, resource->tcpPort);
+            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port value");
+#endif
+
             err |= cbor_encoder_close_container(&linkMap, &policyMap);
             VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing policy map");
 
index 65a3c06..f577a17 100755 (executable)
@@ -353,6 +353,16 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *
                 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
             }
 
+#ifdef TCP_ADAPTER
+            // TCP Port
+            err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
+            if (cbor_value_is_valid(&curVal))
+            {
+                err = cbor_value_get_int(&curVal, (int *)&resource->tcpPort);
+                VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
+            }
+#endif
+
             err = cbor_value_advance(&resourceMap);
             VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
 
index 3c0ee58..c5053cc 100755 (executable)
@@ -111,6 +111,29 @@ static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
     return OC_STACK_OK;
 }
 
+#ifdef TCP_ADAPTER
+/* This method will retrieve the tcp port */
+static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port)
+{
+    uint16_t p = 0;
+
+    if (endpoint->adapter == OC_ADAPTER_IP)
+    {
+        if (endpoint->flags & OC_IP_USE_V4)
+        {
+            p = caglobals.tcp.ipv4.port;
+        }
+        else if (endpoint->flags & OC_IP_USE_V6)
+        {
+            p = caglobals.tcp.ipv6.port;
+        }
+    }
+
+    *port = p;
+    return OC_STACK_OK;
+}
+#endif
+
 /*
  * Function will extract 0, 1 or 2 filters from query.
  * More than 2 filters or unsupported filters will result in error.
@@ -291,21 +314,29 @@ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
     {
         return OC_STACK_INVALID_PARAM;
     }
-    uint16_t port = 0;
+    uint16_t securePort = 0;
     if (resourcePtr->resourceProperties & OC_SECURE)
     {
-       if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
+       if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
        {
-           port = 0;
+           securePort = 0;
        }
     }
 
     if (rdResponse)
     {
-        port = devAddr->port;
+        securePort = devAddr->port;
     }
 
-    OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
+    uint16_t tcpPort = 0;
+#ifdef TCP_ADAPTER
+    if (GetTCPPortInfo(devAddr, &tcpPort) != OC_STACK_OK)
+    {
+        tcpPort = 0;
+    }
+#endif
+
+    OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort);
     return OC_STACK_OK;
 }
 
index 3caafba..e8ce987 100644 (file)
@@ -2296,7 +2296,15 @@ static OCStackResult ParseRequestUri(const char *fullUri,
             {
                 colon = close + 1;
             }
-            adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+
+            if (istcp)
+            {
+                adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
+            }
+            else
+            {
+                adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+            }
             flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
         }
         else
@@ -2308,14 +2316,15 @@ static OCStackResult ParseRequestUri(const char *fullUri,
                 end = (colon && colon < slash) ? colon : slash;
 
                 if (istcp)
-                {   // coap over tcp
+                {
+                    // coap over tcp
                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
                 }
                 else
                 {
                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
-                    flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
                 }
+                flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
             }
             else
             {   // MAC address
index c9526f1..aa154bc 100644 (file)
@@ -83,6 +83,23 @@ namespace OC
                                         StringLLToVector(res->types),
                                         StringLLToVector(res->interfaces)
                                         )));
+
+#ifdef TCP_ADAPTER
+                            if (res->tcpPort != 0)
+                            {
+                                OCDevAddr tcpDevAddr = m_devAddr;
+                                tcpDevAddr.port = res->tcpPort;
+                                tcpDevAddr.adapter = OC_ADAPTER_TCP;
+                                m_resources.push_back(std::shared_ptr<OC::OCResource>(
+                                            new OC::OCResource(m_clientWrapper, tcpDevAddr,
+                                                std::string(res->uri),
+                                                std::string(payload->sid),
+                                                (res->bitmap & OC_OBSERVABLE) == OC_OBSERVABLE,
+                                                StringLLToVector(res->types),
+                                                StringLLToVector(res->interfaces)
+                                                )));
+                            }
+#endif
                         }
                         res = res->next;
                     }