1 /* ****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
28 #include <IPAddress.h>
30 #include "catcpadapterutils_eth.h"
31 #include "catcpinterface.h"
33 #include "caadapterutils.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
39 * Logging tag for module name.
41 #define TAG "TCP_SERVER"
44 * Maximum CoAP over TCP header length
45 * to know the total data length.
47 #define TCP_MAX_HEADER_LEN 6
49 #define TCP_UNICAST_PORT 55556
51 uint16_t tcpClientPort = 0;
52 uint8_t tcpClientIP[4] = {0};
55 * Maintains the callback to be notified when data received from remote device.
57 static CATCPPacketReceivedCallback g_packetReceivedCallback = NULL;
60 * Error callback to update error in TCP.
62 static CATCPErrorHandleCallback g_TCPErrorHandler = NULL;
64 static uint16_t g_unicastPort = 0;
66 static int g_unicastSocket = -1;
68 static EthernetServer server(TCP_UNICAST_PORT);
71 * @var g_receivedDataLen
72 * @brief Actual length of data received.
74 static uint32_t g_receivedDataLen = 0;
76 static void CATCPReadDataInternal();
78 uint16_t CAGetTcpServerPortNum(const char *ipAddress, bool isSecured)
85 CATCPReadDataInternal();
88 CAResult_t CATCPStartServer()
90 OIC_LOG(DEBUG, TAG, "IN");
92 if (caglobals.tcp.started)
97 if (!caglobals.tcp.ipv4tcpenabled)
99 caglobals.tcp.ipv4tcpenabled = true; // only needed to run CA tests
102 uint8_t rawIPAddr[4] = {0};
103 char address[16] = {0};
104 W5100.getIPAddress(rawIPAddr);
105 int ret = snprintf(address, sizeof(address), "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2],
109 OIC_LOG(ERROR, TAG, "Error getting IP");
110 return CA_STATUS_FAILED;
113 OIC_LOG_V(DEBUG, TAG, "address:%s", address);
115 g_unicastPort = TCP_UNICAST_PORT;
117 if (CAArduinoInitTCPSocket(&g_unicastPort, &serverFD) != CA_STATUS_OK)
119 OIC_LOG(DEBUG, TAG, "Init TCP Socket failed");
120 return CA_STATUS_FAILED;
124 EthernetClass::_server_port[serverFD] = g_unicastPort;
125 g_unicastSocket = serverFD;
126 caglobals.ip.u4.port = TCP_UNICAST_PORT;
128 caglobals.tcp.terminate = false;
129 caglobals.tcp.started = true;
131 OIC_LOG_V(DEBUG, TAG, "g_unicastPort: %u", g_unicastPort);
132 OIC_LOG_V(DEBUG, TAG, "g_unicastSocket: %d", g_unicastSocket);
133 OIC_LOG(DEBUG, TAG, "OUT");
137 void CATCPStopServer()
139 OIC_LOG(DEBUG, TAG, "IN");
140 caglobals.tcp.terminate = true;
141 caglobals.tcp.started = false;
143 if (-1 != g_unicastSocket)
145 close(g_unicastSocket);
146 g_unicastSocket = -1;
149 caglobals.ip.u4.port = 0;
150 OIC_LOG(DEBUG, TAG, "OUT");
153 void CATCPSetPacketReceiveCallback(CATCPPacketReceivedCallback callback)
155 OIC_LOG(DEBUG, TAG, "IN");
157 g_packetReceivedCallback = callback;
159 OIC_LOG(DEBUG, TAG, "OUT");
162 void CATCPSetConnectionChangedCallback(CATCPConnectionHandleCallback connHandler)
167 void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback)
172 void CATCPReadDataInternal()
174 OIC_LOG(DEBUG, TAG, "CATCPReadDataInternal IN");
175 if (false == caglobals.tcp.started)
177 OIC_LOG(ERROR, TAG, "Server is not running");
181 EthernetClient client = server.available();
183 if (client && client.connected())
185 client.getTCPClientIP(tcpClientIP);
186 client.getTCPClientPort(&tcpClientPort);
187 OIC_LOG_V(DEBUG, TAG, "Client ip is %d.%d.%d.%d , Port is : %d", tcpClientIP[0],
188 tcpClientIP[1], tcpClientIP[2], tcpClientIP[3], tcpClientPort);
190 OIC_LOG(DEBUG, TAG, "DATA Available");
191 unsigned char *recvBuffer = NULL;
192 size_t bufSize = TCP_MAX_HEADER_LEN;
194 recvBuffer = (unsigned char *) OICCalloc(1, bufSize);
197 OIC_LOG(ERROR, TAG, "out of memory");
200 bool isHeaderChecked = false;
202 size_t totalReceivedLen = 0;
206 size_t bufferLen = 0;
207 if (client.available())
209 bufferLen = client.read(recvBuffer, bufSize);
210 totalReceivedLen += bufferLen;
213 if (!isHeaderChecked && totalReceivedLen)
215 coap_transport_t transport;
217 CAGetTCPHeaderDetails(recvBuffer, &transport, &headerLen);
218 if (totalReceivedLen >= headerLen)
220 // get actual data length from coap over tcp header
221 totalLen = CAGetTotalLengthFromPacketHeader((const unsigned char *) recvBuffer,
224 unsigned char *newBuf = (unsigned char *) OICRealloc(recvBuffer, bufSize);
227 OIC_LOG(ERROR, TAG, "out of memory");
233 isHeaderChecked = true;
237 if (totalLen == totalReceivedLen)
239 CASecureEndpoint_t ep =
240 {.endpoint = {.adapter = CA_ADAPTER_TCP,
241 .flags = CA_DEFAULT_FLAGS,
242 .port = tcpClientPort}};
244 IPAddress clientIP = tcpClientIP;
245 int ret = snprintf(ep.endpoint.addr, sizeof(ep.endpoint.addr), "%d.%d.%d.%d",
246 clientIP[0], clientIP[1], clientIP[2], clientIP[3]);
249 OIC_LOG(ERROR, TAG, "Error parsing client IP");
254 OIC_LOG_V(DEBUG, TAG, "Client ip is %d.%d.%d.%d", clientIP[0],
255 clientIP[1], clientIP[2], clientIP[3]);
256 if (g_packetReceivedCallback)
258 g_packetReceivedCallback(&ep, recvBuffer, totalLen);
261 OIC_LOG_V(DEBUG, TAG, "received data len:%d", totalLen);
264 } while (!totalLen || totalLen > totalReceivedLen);
268 OIC_LOG(DEBUG, TAG, "OUT");
272 OIC_LOG(DEBUG, TAG, "NoData");
277 CAResult_t CAGetTCPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
279 OIC_LOG(DEBUG, TAG, "IN");
281 VERIFY_NON_NULL(info, TAG, "info is NULL");
282 VERIFY_NON_NULL(size, TAG, "size is NULL");
284 return CA_NOT_SUPPORTED;
287 static ssize_t sendData(const CAEndpoint_t *endpoint,
288 const void *data, size_t dlen)
290 uint16_t port = endpoint->port;
291 uint8_t ipAddr[4] = { 0 };
292 uint16_t parsedPort = 0;
293 if (CAParseIPv4AddressInternal(endpoint->addr, ipAddr, sizeof(ipAddr),
294 &parsedPort) != CA_STATUS_OK)
296 OIC_LOG(ERROR, TAG, "parse fail");
300 if (dlen > 65535) // Max value for uint16_t
302 // This will never happen as max buffer size we are dealing with is COAP_MAX_PDU_SIZE
303 OIC_LOG(ERROR, TAG, "Size exceeded");
307 uint32_t ret = send(g_unicastSocket, (const uint8_t *)data, (uint16_t)dlen);
310 OIC_LOG_V(ERROR, TAG, "SendData failed: %d", ret);
313 OIC_LOG(DEBUG, TAG, "OUT");
317 ssize_t CATCPSendData(CAEndpoint_t *endpoint, const void *data, size_t datalen)
319 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
320 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
322 if (caglobals.tcp.ipv4tcpenabled && (endpoint->adapter & CA_ADAPTER_TCP))
324 return sendData(endpoint, data, datalen);