From a55d7c1c54bea2a4284b1f402fbeba1eb4de74e7 Mon Sep 17 00:00:00 2001 From: Abhishek Sharma Date: Fri, 30 Oct 2015 14:39:24 +0530 Subject: [PATCH] Added COAP over TCP feature for Arduino for Transport TCP Made changes for arduino to support COAP over TCP for Transport TCP Change-Id: Ifb9c30b1b324cf28c14abb3ebbcb292de31b1fda Signed-off-by: koushik.girijala Signed-off-by: Abhishek Sharma Reviewed-on: https://gerrit.iotivity.org/gerrit/3985 Tested-by: jenkins-iotivity Reviewed-by: Abhishek Pandey Reviewed-by: Jon A. Cruz --- resource/csdk/connectivity/SConscript | 2 +- resource/csdk/connectivity/api/cacommon.h | 2 + resource/csdk/connectivity/inc/catcpadapter.h | 1 + resource/csdk/connectivity/inc/catcpinterface.h | 30 ++ .../lib/arduino/arduino_libraries.patch | 46 +++ .../csdk/connectivity/lib/libcoap-4.1.1/SConscript | 2 +- resource/csdk/connectivity/src/SConscript | 5 + .../csdk/connectivity/src/tcp_adapter/SConscript | 2 + .../src/tcp_adapter/arduino/SConscript | 14 + .../tcp_adapter/arduino/catcpadapterutils_eth.cpp | 82 ++++++ .../tcp_adapter/arduino/catcpadapterutils_eth.h | 66 +++++ .../src/tcp_adapter/arduino/catcpserver_eth.cpp | 322 +++++++++++++++++++++ .../connectivity/src/tcp_adapter/catcpadapter.c | 84 ++++++ 13 files changed, 656 insertions(+), 2 deletions(-) create mode 100644 resource/csdk/connectivity/src/tcp_adapter/arduino/SConscript create mode 100644 resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.cpp create mode 100644 resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.h create mode 100644 resource/csdk/connectivity/src/tcp_adapter/arduino/catcpserver_eth.cpp diff --git a/resource/csdk/connectivity/SConscript b/resource/csdk/connectivity/SConscript index 6ba8cd3..d533f71 100644 --- a/resource/csdk/connectivity/SConscript +++ b/resource/csdk/connectivity/SConscript @@ -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: diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h index a2a3fd3..aa36d61 100644 --- a/resource/csdk/connectivity/api/cacommon.h +++ b/resource/csdk/connectivity/api/cacommon.h @@ -26,9 +26,11 @@ #ifndef CA_COMMON_H_ #define CA_COMMON_H_ +#ifndef WITH_ARDUINO #ifdef TCP_ADAPTER #define HAVE_SYS_POLL_H #endif +#endif #include #include diff --git a/resource/csdk/connectivity/inc/catcpadapter.h b/resource/csdk/connectivity/inc/catcpadapter.h index e3da369..9e9fde5 100644 --- a/resource/csdk/connectivity/inc/catcpadapter.h +++ b/resource/csdk/connectivity/inc/catcpadapter.h @@ -29,6 +29,7 @@ #include "caadapterinterface.h" #include "cathreadpool.h" #include "cainterface.h" +#include "pdu.h" #ifdef __cplusplus extern "C" diff --git a/resource/csdk/connectivity/inc/catcpinterface.h b/resource/csdk/connectivity/inc/catcpinterface.h index 10dd685..a9463ab 100644 --- a/resource/csdk/connectivity/inc/catcpinterface.h +++ b/resource/csdk/connectivity/inc/catcpinterface.h @@ -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. */ diff --git a/resource/csdk/connectivity/lib/arduino/arduino_libraries.patch b/resource/csdk/connectivity/lib/arduino/arduino_libraries.patch index 507aa99..7eb9718 100644 --- a/resource/csdk/connectivity/lib/arduino/arduino_libraries.patch +++ b/resource/csdk/connectivity/lib/arduino/arduino_libraries.patch @@ -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 diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/SConscript b/resource/csdk/connectivity/lib/libcoap-4.1.1/SConscript index bf892ec..03713c5 100644 --- a/resource/csdk/connectivity/lib/libcoap-4.1.1/SConscript +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/SConscript @@ -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']) diff --git a/resource/csdk/connectivity/src/SConscript b/resource/csdk/connectivity/src/SConscript index 50a7b59..3c671a3 100644 --- a/resource/csdk/connectivity/src/SConscript +++ b/resource/csdk/connectivity/src/SConscript @@ -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')) diff --git a/resource/csdk/connectivity/src/tcp_adapter/SConscript b/resource/csdk/connectivity/src/tcp_adapter/SConscript index df48527..7972635 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/SConscript +++ b/resource/csdk/connectivity/src/tcp_adapter/SConscript @@ -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 index 0000000..b9125ae --- /dev/null +++ b/resource/csdk/connectivity/src/tcp_adapter/arduino/SConscript @@ -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 index 0000000..7ecba20 --- /dev/null +++ b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.cpp @@ -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 +#include +#include +#include +#include +#include + +#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 index 0000000..4ecbd84 --- /dev/null +++ b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpadapterutils_eth.h @@ -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 +#include +#include +#include +#include + +#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 index 0000000..3cc0e7d --- /dev/null +++ b/resource/csdk/connectivity/src/tcp_adapter/arduino/catcpserver_eth.cpp @@ -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 +#include + +#include +#include +#include +#include +#include + +#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 diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c index 6ea9c36..d2fda2c 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c @@ -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 -- 2.7.4