Added COAP over TCP feature for Arduino for Transport TCP
authorAbhishek Sharma <ce.abhishek@samsung.com>
Fri, 30 Oct 2015 09:09:24 +0000 (14:39 +0530)
committerJon A. Cruz <jon@joncruz.org>
Tue, 10 May 2016 05:43:54 +0000 (05:43 +0000)
Made changes  for arduino to support COAP over TCP for Transport TCP

Change-Id: Ifb9c30b1b324cf28c14abb3ebbcb292de31b1fda
Signed-off-by: koushik.girijala <g.koushik@samsung.com>
Signed-off-by: Abhishek Sharma <ce.abhishek@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/3985
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Abhishek Pandey <abhi.siso@samsung.com>
Reviewed-by: Jon A. Cruz <jon@joncruz.org>
13 files changed:
resource/csdk/connectivity/SConscript
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/inc/catcpadapter.h
resource/csdk/connectivity/inc/catcpinterface.h
resource/csdk/connectivity/lib/arduino/arduino_libraries.patch
resource/csdk/connectivity/lib/libcoap-4.1.1/SConscript
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/tcp_adapter/SConscript
resource/csdk/connectivity/src/tcp_adapter/arduino/SConscript [new file with mode: 0644]
resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.cpp [new file with mode: 0644]
resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.h [new file with mode: 0644]
resource/csdk/connectivity/src/tcp_adapter/arduino/catcpserver_eth.cpp [new file with mode: 0644]
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c

index 6ba8cd3..d533f71 100644 (file)
@@ -62,7 +62,7 @@ else:
                env.AppendUnique(CPPDEFINES = ['NO_IP_ADAPTER'])
 
        if with_tcp == True:
-               if target_os in ['linux', 'tizen', 'android']:
+               if target_os in ['linux', 'tizen', 'android', 'arduino']:
                        env.AppendUnique(CPPDEFINES = ['TCP_ADAPTER', 'WITH_TCP'])
                        print "CA Transport is TCP"
                else:
index a2a3fd3..aa36d61 100644 (file)
 #ifndef CA_COMMON_H_
 #define CA_COMMON_H_
 
+#ifndef WITH_ARDUINO
 #ifdef TCP_ADAPTER
 #define HAVE_SYS_POLL_H
 #endif
+#endif
 
 #include <stdint.h>
 #include <stdlib.h>
index e3da369..9e9fde5 100644 (file)
@@ -29,6 +29,7 @@
 #include "caadapterinterface.h"
 #include "cathreadpool.h"
 #include "cainterface.h"
+#include "pdu.h"
 
 #ifdef __cplusplus
 extern "C"
index 10dd685..a9463ab 100644 (file)
@@ -80,6 +80,34 @@ typedef void (*CATCPConnectionHandleCallback)(const char *addr, uint16_t port, b
  */
 void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback);
 
+#ifdef SINGLE_THREAD
+
+CAResult_t CATCPStartServer();
+
+/**
+ * Pull the Received Data.
+ */
+void CATCPPullData();
+
+/**
+ * Get TCP Header Details.
+ * @param[in]    recvBuffer   index of array list.
+ * @param[out]   transport    TCP Server address.
+ * @param[out]   headerlen    TCP Server port.
+ */
+void CAGetTCPHeaderDetails(unsigned char *recvBuffer, coap_transport_type *transport,
+                           size_t *headerlen);
+
+/**
+ * Get total length from CoAP over TCP header.
+ *
+ * @param[in]   recvBuffer    received header data.
+ * @param[in]   size          length of buffer.
+ * @return  total data length
+ */
+size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size);
+
+#else
 /**
  * set keepalive callback to notify connection information in TCP adapter.
  *
@@ -99,6 +127,8 @@ void CATCPSetKeepAliveCallback(CAKeepAliveConnectionCallback keepaliveHandler);
  */
 CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool);
 
+#endif
+
 /**
  * Stop TCP server.
  */
index 507aa99..7eb9718 100644 (file)
@@ -11,7 +11,53 @@ diff -rupN ./libraries/Ethernet/src/Ethernet.cpp ./arduino-1.5.8/libraries/Ether
  {
 -  static DhcpClass s_dhcp;
    _dhcp = &s_dhcp;
+   
+
+diff -rupN ./libraries/Ethernet/src/EthernetClient.cpp ./arduino-1.5.8/libraries/Ethernet/src/EthernetClient.cpp
+--- ./libraries/Ethernet/src/EthernetClient.cpp        2014-10-01 20:45:35.000000000 +0530
++++ ./arduino-1.5.8/libraries/Ethernet/src/EthernetClient.cpp  2015-02-05 15:51:09.000000000 +0530
+@@ -92,6 +92,16 @@ int EthernetClient::available() {
+   return 0;
+ }
  
++void EthernetClient::getTCPClientIP(uint8_t *addr) {
++  if (_sock != MAX_SOCK_NUM)
++    W5100.readSnDIPR(_sock, addr);
++}
++
++void EthernetClient::getTCPClientPort(uint16_t *port) {
++  if (_sock != MAX_SOCK_NUM)
++    W5100.readSnDPORT(_sock);
++}
++
+ int EthernetClient::read() {
+   uint8_t b;
+   if ( recv(_sock, &b, 1) > 0 )
+diff -rupN ./libraries/Ethernet/src/EthernetClient.h ./arduino-1.5.8/libraries/Ethernet/src/EthernetClient.h
+--- ./libraries/Ethernet/src/EthernetClient.h  2014-10-01 20:45:35.000000000 +0530
++++ ./arduino-1.5.8/libraries/Ethernet/src/EthernetClient.h    2015-02-05 15:51:09.000000000 +0530
+@@ -1,6 +1,6 @@
+ #ifndef ethernetclient_h
+ #define ethernetclient_h
+-#include "Arduino.h"  
++#include "Arduino.h"
+ #include "Print.h"
+ #include "Client.h"
+ #include "IPAddress.h"
+@@ -26,9 +26,11 @@ public:
+   virtual operator bool();
+   virtual bool operator==(const EthernetClient&);
+   virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); };
++  virtual void getTCPClientIP(uint8_t *addr);
++  virtual void getTCPClientPort(uint16_t *port);
+   friend class EthernetServer;
+-  
++
+   using Print::write;
+
+ private:
+
  
 diff -rupN ./libraries/Ethernet/src/utility/socket.cpp ./arduino-1.5.8/libraries/Ethernet/src/utility/socket.cpp
 --- ./libraries/Ethernet/src/utility/socket.cpp        2014-10-01 20:45:35.000000000 +0530
index bf892ec..03713c5 100644 (file)
@@ -37,7 +37,7 @@ if target_os not in ['windows', 'winrt']:
        libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections',
                        '-fdata-sections', '-fno-exceptions'])
 
-if target_os in ['linux', 'tizen', 'android', 'ios']:
+if target_os in ['linux', 'tizen', 'android', 'ios', 'arduino']:
        if with_tcp == True:
                libcoap_env.AppendUnique(CPPDEFINES = ['WITH_TCP'])
 
index 50a7b59..3c671a3 100644 (file)
@@ -131,6 +131,11 @@ if 'ALL' in ca_transport:
 
 if 'IP' in ca_transport:
        env.SConscript(os.path.join(ca_path, 'ip_adapter/SConscript'))
+       if ca_os == 'arduino':
+               if with_tcp:
+                       transports = [ 'ip_adapter', 'tcp_adapter']
+                       env.SConscript(dirs = [
+                               os.path.join(ca_path, d) for d in transports ])
 
 if 'BT' in ca_transport:
        env.SConscript(os.path.join(ca_path, 'bt_edr_adapter/SConscript'))
index df48527..7972635 100644 (file)
@@ -19,6 +19,8 @@ if target_os in ['linux', 'tizen', 'android']:
     common_files = [
         os.path.join(src_dir, 'catcpadapter.c'),
         os.path.join(src_dir, 'catcpserver.c') ]
+else :
+    common_files = [os.path.join(src_dir, 'catcpadapter.c')]
 
 # Get list of target-specific source file base names, i.e. no parent
 # directories prepended to the path.
diff --git a/resource/csdk/connectivity/src/tcp_adapter/arduino/SConscript b/resource/csdk/connectivity/src/tcp_adapter/arduino/SConscript
new file mode 100644 (file)
index 0000000..b9125ae
--- /dev/null
@@ -0,0 +1,14 @@
+#######################################################
+#       Build TCP adapter for Ardunino
+#######################################################
+
+Import('env', 'src_dir')
+import os.path
+
+env.AppendUnique(CPPPATH = [ os.path.join(src_dir, 'arduino') ])
+
+if env.get('SHIELD') == 'ETH':
+    src_files = [ 'catcpserver_eth.cpp' ,
+                  'catcpadapterutils_eth.cpp']
+
+Return('src_files')
diff --git a/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.cpp b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.cpp
new file mode 100644 (file)
index 0000000..7ecba20
--- /dev/null
@@ -0,0 +1,82 @@
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+#include "catcpadapterutils_eth.h"
+
+#include <Arduino.h>
+#include <Ethernet.h>
+#include <socket.h>
+#include <w5100.h>
+#include <EthernetUdp.h>
+#include <IPAddress.h>
+
+#include "logger.h"
+#include "cacommon.h"
+#include "caadapterinterface.h"
+#include "caadapterutils.h"
+
+#define TAG "IPU"
+
+CAResult_t CAArduinoGetAvailableTCPSocket(int *sockID)
+{
+    VERIFY_NON_NULL(sockID, TAG, "sockID");
+    //Is any socket available to work with ?
+    *sockID = 0;
+    for (int i = 1; i < MAX_SOCK_NUM; i++)
+    {
+        uint8_t state = W5100.readSnSR(i);
+        if (state == SnSR::CLOSED || state == SnSR::FIN_WAIT)
+        {
+            *sockID = i;
+            break;
+        }
+    }
+
+    if (*sockID == 0)
+    {
+        OIC_LOG(ERROR, TAG, "sockID 0");
+        return CA_SOCKET_OPERATION_FAILED;
+    }
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAArduinoInitTCPSocket(uint16_t *port, int *socketID)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL(port, TAG, "port");
+    VERIFY_NON_NULL(socketID, TAG, "socketID");
+
+    CAResult_t ret = CAArduinoGetAvailableTCPSocket(socketID);
+    if (ret != CA_STATUS_OK)
+    {
+        OIC_LOG(ERROR, TAG, "get sock fail");
+        return ret;
+    }
+
+    //Create a tcp socket on which to recv/send.
+    if (!socket(*socketID, SnMR::TCP, *port, 0))
+    {
+        OIC_LOG(ERROR, TAG, "sock fail");
+        return CA_STATUS_FAILED;
+    }
+    OIC_LOG_V(DEBUG, TAG, "socketId:%d", *socketID);
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
diff --git a/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.h b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.h
new file mode 100644 (file)
index 0000000..4ecbd84
--- /dev/null
@@ -0,0 +1,66 @@
+/* ****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file provides APIs ethernet client/server/network monitor modules.
+ */
+
+#ifndef CA_ETHERNET_ADAPTER_UTILS_
+#define CA_ETHERNET_ADAPTER_UTILS_
+
+#include <Arduino.h>
+#include <Ethernet.h>
+#include <socket.h>
+#include <w5100.h>
+#include <IPAddress.h>
+
+#include "logger.h"
+#include "cacommon.h"
+#include "caadapterinterface.h"
+#include "caipadapter.h"
+#include "caadapterutils.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Get available TCP socket.
+ * @param[out]   sockID         Available UDP socket ID.
+ * @return  ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAArduinoGetAvailableTCPSocket(int *sockID);
+
+/**
+ * Initialize Unicast TCP socket.
+ * @param[in/out]   port        Port to start the unicast server.
+ * @param[out]      socketID    Unicast socket ID.
+ * @return  ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAArduinoInitTCPSocket(uint16_t *port, int *socketID);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CA_ETHERNET_ADAPTER_UTILS_ */
+
diff --git a/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpserver_eth.cpp b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpserver_eth.cpp
new file mode 100644 (file)
index 0000000..3cc0e7d
--- /dev/null
@@ -0,0 +1,322 @@
+/* ****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <Arduino.h>
+#include <Ethernet.h>
+#include <SPI.h>
+#include <w5100.h>
+#include <IPAddress.h>
+
+#include "catcpadapterutils_eth.h"
+#include "catcpinterface.h"
+#include "pdu.h"
+#include "caadapterutils.h"
+#include "camutex.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "TCP_SERVER"
+
+/**
+ * Maximum CoAP over TCP header length
+ * to know the total data length.
+ */
+#define TCP_MAX_HEADER_LEN  6
+
+#define TCP_UNICAST_PORT  55556
+
+uint16_t tcpClientPort = 0;
+uint8_t tcpClientIP[4] = {0};
+
+/**
+ * Maintains the callback to be notified when data received from remote device.
+ */
+static CATCPPacketReceivedCallback g_packetReceivedCallback = NULL;
+
+/**
+ * Error callback to update error in TCP.
+ */
+static CATCPErrorHandleCallback g_TCPErrorHandler = NULL;
+
+static uint16_t g_unicastPort = 0;
+
+static int g_unicastSocket = -1;
+
+static EthernetServer server(TCP_UNICAST_PORT);
+
+/**
+ * @var g_receivedDataLen
+ * @brief Actual length of data received.
+ */
+static uint32_t g_receivedDataLen = 0;
+
+static void CATCPReadDataInternal();
+
+uint16_t CAGetTcpServerPortNum(const char *ipAddress, bool isSecured)
+{
+    return g_unicastPort;
+}
+
+void CATCPPullData()
+{
+    CATCPReadDataInternal();
+}
+
+CAResult_t CATCPStartServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    if (caglobals.tcp.started)
+    {
+        return CA_STATUS_OK;
+    }
+
+    if (!caglobals.tcp.ipv4tcpenabled)
+    {
+        caglobals.tcp.ipv4tcpenabled = true;    // only needed to run CA tests
+    }
+
+    uint8_t rawIPAddr[4] = {0};
+    char address[16] = {0};
+    W5100.getIPAddress(rawIPAddr);
+    int ret = snprintf(address, sizeof(address), "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2],
+                       rawIPAddr[3]);
+    if(0 > ret)
+    {
+        OIC_LOG(ERROR, TAG, "Error getting IP");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "address:%s", address);
+    int serverFD = 1;
+    g_unicastPort = TCP_UNICAST_PORT;
+
+    if (CAArduinoInitTCPSocket(&g_unicastPort, &serverFD) != CA_STATUS_OK)
+    {
+        OIC_LOG(DEBUG, TAG, "Init TCP Socket failed");
+        return CA_STATUS_FAILED;
+    }
+
+    listen(serverFD);
+    EthernetClass::_server_port[serverFD] = g_unicastPort;
+    g_unicastSocket = serverFD;
+    caglobals.ip.u4.port =  TCP_UNICAST_PORT;
+
+    caglobals.tcp.terminate = false;
+    caglobals.tcp.started = true;
+
+    OIC_LOG_V(DEBUG, TAG, "g_unicastPort: %u", g_unicastPort);
+    OIC_LOG_V(DEBUG, TAG, "g_unicastSocket: %d", g_unicastSocket);
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+void CATCPStopServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    caglobals.tcp.terminate = true;
+    caglobals.tcp.started = false;
+
+    if (-1 != g_unicastSocket)
+    {
+        close(g_unicastSocket);
+        g_unicastSocket = -1;
+    }
+
+    caglobals.ip.u4.port = 0;
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPSetPacketReceiveCallback(CATCPPacketReceivedCallback callback)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    g_packetReceivedCallback = callback;
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback)
+{
+    return;
+}
+
+void CATCPReadDataInternal()
+{
+    OIC_LOG(DEBUG, TAG, "CATCPReadDataInternal IN");
+    if (false == caglobals.tcp.started)
+    {
+        OIC_LOG(ERROR, TAG, "Server is not running");
+        return;
+    }
+
+    EthernetClient client = server.available();
+
+    if (client && client.connected())
+    {
+        client.getTCPClientIP(tcpClientIP);
+        client.getTCPClientPort(&tcpClientPort);
+        OIC_LOG_V(DEBUG, TAG, "Client ip is %d.%d.%d.%d , Port is : %d", tcpClientIP[0],
+                tcpClientIP[1], tcpClientIP[2], tcpClientIP[3], tcpClientPort);
+
+        OIC_LOG(DEBUG, TAG, "DATA Available");
+        unsigned char *recvBuffer = NULL;
+        size_t bufSize = TCP_MAX_HEADER_LEN;
+
+        recvBuffer = (unsigned char *) OICCalloc(1, bufSize);
+        if (!recvBuffer)
+        {
+            OIC_LOG(ERROR, TAG, "out of memory");
+        }
+
+        bool isHeaderChecked = false;
+        size_t totalLen = 0;
+        size_t totalReceivedLen = 0;
+
+        do
+        {
+            size_t bufferLen = 0;
+            if (client.available())
+            {
+                bufferLen = client.read(recvBuffer, bufSize);
+                totalReceivedLen += bufferLen;
+            }
+
+            if (!isHeaderChecked && totalReceivedLen)
+            {
+                coap_transport_type transport;
+                size_t headerLen;
+                CAGetTCPHeaderDetails(recvBuffer, &transport, &headerLen);
+                if (totalReceivedLen >= headerLen)
+                {
+                    // get actual data length from coap over tcp header
+                    totalLen = CAGetTotalLengthFromPacketHeader((const unsigned char *) recvBuffer,
+                                                                 bufferLen);
+                    bufSize = totalLen;
+                    unsigned char *newBuf = (unsigned char *) OICRealloc(recvBuffer, bufSize);
+                    if (NULL == newBuf)
+                    {
+                        OIC_LOG(ERROR, TAG, "out of memory");
+                        OICFree(recvBuffer);
+                        return;
+                    }
+
+                    recvBuffer = newBuf;
+                    isHeaderChecked = true;
+                }
+            }
+
+            if (totalLen == totalReceivedLen)
+            {
+                CASecureEndpoint_t ep =
+                    {.endpoint = {.adapter = CA_ADAPTER_TCP, .port = tcpClientPort}};
+
+                IPAddress clientIP = tcpClientIP;
+                int ret = snprintf(ep.endpoint.addr, sizeof(ep.endpoint.addr), "%d.%d.%d.%d",
+                                   clientIP[0], clientIP[1], clientIP[2], clientIP[3]);
+                if(0 > ret)
+                {
+                    OIC_LOG(ERROR, TAG, "Error parsing client IP");
+                    OICFree(recvBuffer);
+                    return;
+                }
+
+                OIC_LOG_V(DEBUG, TAG, "Client ip is %d.%d.%d.%d", clientIP[0],
+                          clientIP[1], clientIP[2], clientIP[3]);
+                if (g_packetReceivedCallback)
+                {
+                    g_packetReceivedCallback(&ep, recvBuffer, totalLen);
+                }
+
+                OIC_LOG_V(DEBUG, TAG, "received data len:%d", totalLen);
+                break;
+            }
+        } while (!totalLen || totalLen > totalReceivedLen);
+
+        OICFree(recvBuffer);
+
+        OIC_LOG(DEBUG, TAG, "OUT");
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "NoData");
+    }
+    return;
+}
+
+CAResult_t CAGetTCPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(info, TAG, "info is NULL");
+    VERIFY_NON_NULL(size, TAG, "size is NULL");
+
+    return CA_NOT_SUPPORTED;
+}
+
+static void sendData(const CAEndpoint_t *endpoint,
+                     const void *data, size_t dlen)
+{
+    uint16_t port = endpoint->port;
+    uint8_t ipAddr[4] = { 0 };
+    uint16_t parsedPort = 0;
+    if (CAParseIPv4AddressInternal(endpoint->addr, ipAddr, sizeof(ipAddr),
+                                   &parsedPort) != CA_STATUS_OK)
+    {
+        OIC_LOG(ERROR, TAG, "parse fail");
+        return;
+    }
+
+    if (dlen > 65535) // Max value for uint16_t
+    {
+        // This will never happen as max buffer size we are dealing with is COAP_MAX_PDU_SIZE
+        OIC_LOG(ERROR, TAG, "Size exceeded");
+        return;
+    }
+
+    uint32_t ret = send(g_unicastSocket, (const uint8_t *)data, (uint16_t)dlen);
+    if (ret <= 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendData failed: %d", ret);
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
+                   bool isMulticast)
+{
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+    if (!isMulticast)
+    {
+        if (caglobals.tcp.ipv4tcpenabled && (endpoint->adapter & CA_ADAPTER_TCP))
+        {
+            sendData(endpoint, data, datalen);
+        }
+    }
+}
\ No newline at end of file
index 6ea9c36..d2fda2c 100644 (file)
@@ -233,7 +233,9 @@ CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
+#ifndef SINGLE_THREAD
     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
+#endif
 
     g_networkChangeCallback = netCallback;
     g_connectionChangeCallback = connCallback;
@@ -241,7 +243,9 @@ CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
     g_errorCallback = errorCallback;
 
     CAInitializeTCPGlobals();
+#ifndef SINGLE_THREAD
     caglobals.tcp.threadpool = handle;
+#endif
 
     CATCPSetConnectionChangedCallback(CATCPConnectionHandler);
     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
@@ -268,6 +272,9 @@ CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
 
 CAResult_t CAStartTCP()
 {
+    OIC_LOG(DEBUG, TAG, "IN");
+
+#ifndef SINGLE_THREAD
     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
     {
         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
@@ -282,11 +289,21 @@ CAResult_t CAStartTCP()
         return CA_STATUS_FAILED;
     }
 
+#else
+    CAResult_t ret = CATCPStartServer();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(DEBUG, TAG, "CATCPStartServer failed[%d]", ret);
+        return ret;
+    }
+#endif
+
     return CA_STATUS_OK;
 }
 
 CAResult_t CAStartTCPListeningServer()
 {
+#ifndef SINGLE_THREAD
     if (!caglobals.server)
     {
         caglobals.server = true;    // only needed to run CA tests
@@ -298,6 +315,7 @@ CAResult_t CAStartTCPListeningServer()
         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
         return ret;
     }
+#endif
 
     return CA_STATUS_OK;
 }
@@ -354,7 +372,13 @@ static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
                              const void *data, uint32_t dataLength)
 {
+    OIC_LOG(DEBUG, TAG, "IN");
+#ifndef SINGLE_THREAD
     return CAQueueTCPData(false, endpoint, data, dataLength);
+#else
+    CATCPSendData(endpoint, data, dataLength, false);
+    return dataLength;
+#endif
 }
 
 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
@@ -365,15 +389,21 @@ int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
 
 CAResult_t CAReadTCPData()
 {
+    OIC_LOG(DEBUG, TAG, "IN");
+#ifdef SINGLE_THREAD
+    CATCPPullData();
+#endif
     return CA_STATUS_OK;
 }
 
 CAResult_t CAStopTCP()
 {
+#ifndef SINGLE_THREAD
     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
     {
         CAQueueingThreadStop(g_sendQueueHandle);
     }
+#endif
 
     CATCPStopServer();
 
@@ -387,7 +417,9 @@ void CATerminateTCP()
 {
     CATCPSetPacketReceiveCallback(NULL);
 
+#ifndef SINGLE_THREAD
     CATCPDeinitializeQueueHandles();
+#endif
 }
 
 void CATCPSendDataThread(void *threadData)
@@ -461,3 +493,55 @@ void CADataDestroyer(void *data, uint32_t size)
 
     CAFreeTCPData(TCPData);
 }
+
+#ifdef SINGLE_THREAD
+size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size)
+{
+    OIC_LOG(DEBUG, TAG, "IN - CAGetTotalLengthFromHeader");
+
+    if (NULL == recvBuffer || !size)
+    {
+        OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
+        return 0;
+    }
+
+    coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+            ((unsigned char *)recvBuffer)[0] >> 4);
+    size_t optPaylaodLen = coap_get_length_from_header((unsigned char *)recvBuffer,
+                                                        transport);
+    size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
+
+    OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
+    OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
+    OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
+
+    OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
+    return headerLen + optPaylaodLen;
+}
+
+void CAGetTCPHeaderDetails(unsigned char* recvBuffer, coap_transport_type *transport,
+                           size_t *headerlen)
+{
+    if (NULL == recvBuffer)
+    {
+        OIC_LOG(ERROR, TAG, "recvBuffer is NULL");
+        return;
+    }
+
+    if (NULL == transport)
+    {
+        OIC_LOG(ERROR, TAG, "transport is NULL");
+        return;
+    }
+
+    if (NULL == headerlen)
+    {
+        OIC_LOG(ERROR, TAG, "headerlen is NULL");
+        return;
+    }
+
+    *transport = coap_get_tcp_header_type_from_initbyte(
+        ((unsigned char *)recvBuffer)[0] >> 4);
+    *headerlen = coap_get_tcp_header_length_for_transport(*transport);
+}
+#endif