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 ******************************************************************/
26 #include "catcpadapter.h"
27 #include "catcpinterface.h"
28 #include "caqueueingthread.h"
29 #include "caadapterutils.h"
31 #include "uarraylist.h"
32 #include "caremotehandler.h"
34 #include "oic_malloc.h"
35 #include "oic_string.h"
38 * Logging tag for module name.
40 #define TAG "TCP_ADAP"
43 * Holds internal thread TCP data information.
47 CAEndpoint_t *remoteEndpoint;
53 #define CA_TCP_TIMEOUT 1000
55 #define CA_TCP_LISTEN_BACKLOG 3
58 * Queue handle for Send Data.
60 static CAQueueingThread_t *g_sendQueueHandle = NULL;
63 * Network Packet Received Callback to CA.
65 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
68 * Network Changed Callback to CA.
70 static CANetworkChangeCallback g_networkChangeCallback = NULL;
73 * error Callback to CA adapter.
75 static CAErrorHandleCallback g_errorCallback = NULL;
77 static void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint,
78 const void *data, size_t dataLength);
80 static CAResult_t CATCPInitializeQueueHandles();
82 static void CATCPDeinitializeQueueHandles();
84 static void CATCPSendDataThread(void *threadData);
86 static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
87 const void *data, size_t dataLength,
89 void CAFreeTCPData(CATCPData *ipData);
91 static void CADataDestroyer(void *data, size_t size);
93 CAResult_t CATCPInitializeQueueHandles()
95 OIC_LOG(DEBUG, TAG, "IN");
97 // Check if the message queue is already initialized
98 if (g_sendQueueHandle)
100 OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
104 // Create send message queue
105 g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
106 if (!g_sendQueueHandle)
108 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
109 return CA_MEMORY_ALLOC_FAILED;
112 if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
113 (const ca_thread_pool_t)caglobals.tcp.threadpool,
114 CATCPSendDataThread, CADataDestroyer))
116 OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
117 OICFree(g_sendQueueHandle);
118 g_sendQueueHandle = NULL;
119 return CA_STATUS_FAILED;
122 OIC_LOG(DEBUG, TAG, "OUT");
126 void CATCPDeinitializeQueueHandles()
128 OIC_LOG(DEBUG, TAG, "IN");
130 CAQueueingThreadDestroy(g_sendQueueHandle);
131 OICFree(g_sendQueueHandle);
132 g_sendQueueHandle = NULL;
134 OIC_LOG(DEBUG, TAG, "OUT");
137 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
141 OIC_LOG(DEBUG, TAG, "IN");
144 void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
147 OIC_LOG(DEBUG, TAG, "IN");
149 VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
150 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
152 OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
154 if (g_networkPacketCallback)
156 g_networkPacketCallback(endpoint, data, dataLength);
158 OIC_LOG(DEBUG, TAG, "OUT");
161 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
162 size_t dataLength, CAResult_t result)
164 OIC_LOG(DEBUG, TAG, "IN");
166 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
168 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
172 g_errorCallback(endpoint, data, dataLength, result);
175 OIC_LOG(DEBUG, TAG, "OUT");
178 static void CAInitializeTCPGlobals()
180 caglobals.tcp.selectTimeout = CA_TCP_TIMEOUT;
181 caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
182 caglobals.tcp.svrlist = NULL;
184 CATransportFlags_t flags = 0;
185 if (caglobals.client)
187 flags |= caglobals.clientFlags;
189 if (caglobals.server)
191 flags |= caglobals.serverFlags;
194 caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
197 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
198 CANetworkPacketReceivedCallback networkPacketCallback,
199 CANetworkChangeCallback netCallback,
200 CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
202 OIC_LOG(DEBUG, TAG, "IN");
203 VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
204 VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
205 VERIFY_NON_NULL(netCallback, TAG, "netCallback");
206 VERIFY_NON_NULL(handle, TAG, "thread pool handle");
208 g_networkChangeCallback = netCallback;
209 g_networkPacketCallback = networkPacketCallback;
210 g_errorCallback = errorCallback;
212 CAInitializeTCPGlobals();
213 caglobals.tcp.threadpool = handle;
215 CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
216 CATCPSetErrorHandler(CATCPErrorHandler);
218 CAConnectivityHandler_t TCPHandler = {
219 .startAdapter = CAStartTCP,
220 .startListenServer = CAStartTCPListeningServer,
221 .startDiscoveryServer = CAStartTCPDiscoveryServer,
222 .sendData = CASendTCPUnicastData,
223 .sendDataToAll = CASendTCPMulticastData,
224 .GetnetInfo = CAGetTCPInterfaceInformation,
225 .readData = CAReadTCPData,
226 .stopAdapter = CAStopTCP,
227 .terminate = CATerminateTCP };
228 registerCallback(TCPHandler, CA_ADAPTER_TCP);
230 OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
234 CAResult_t CAStartTCP()
236 OIC_LOG(DEBUG, TAG, "IN");
238 if (CA_STATUS_OK != CATCPInitializeQueueHandles())
240 OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
242 return CA_STATUS_FAILED;
245 // Start send queue thread
246 if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
248 OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
249 return CA_STATUS_FAILED;
252 CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
253 if (CA_STATUS_OK != ret)
255 OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
259 OIC_LOG(DEBUG, TAG, "OUT");
263 CAResult_t CAStartTCPListeningServer()
265 OIC_LOG(DEBUG, TAG, "IN");
267 OIC_LOG(DEBUG, TAG, "OUT");
271 CAResult_t CAStartTCPDiscoveryServer()
273 OIC_LOG(DEBUG, TAG, "IN");
275 OIC_LOG(DEBUG, TAG, "OUT");
279 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
280 const void *data, size_t dataLength)
282 OIC_LOG(DEBUG, TAG, "IN");
284 VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
285 VERIFY_NON_NULL_RET(data, TAG, "data", -1);
289 OIC_LOG(ERROR, TAG, "Invalid Data Length");
293 VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
295 // Create TCPData to add to queue
296 CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
299 OIC_LOG(ERROR, TAG, "Failed to create ipData!");
302 // Add message to send queue
303 CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
305 OIC_LOG(DEBUG, TAG, "OUT");
309 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
310 const void *data, uint32_t dataLength)
312 OIC_LOG(DEBUG, TAG, "IN");
313 return CAQueueTCPData(false, endpoint, data, dataLength);
316 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
317 const void *data, uint32_t dataLength)
319 OIC_LOG(DEBUG, TAG, "IN");
320 return CAQueueTCPData(true, endpoint, data, dataLength);
323 CAResult_t CAReadTCPData()
325 OIC_LOG(DEBUG, TAG, "IN");
326 OIC_LOG(DEBUG, TAG, "OUT");
330 CAResult_t CAStopTCP()
332 OIC_LOG(DEBUG, TAG, "IN");
334 if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
336 CAQueueingThreadStop(g_sendQueueHandle);
339 CATCPDeinitializeQueueHandles();
343 OIC_LOG(DEBUG, TAG, "OUT");
347 void CATerminateTCP()
349 OIC_LOG(DEBUG, TAG, "IN");
351 CATCPSetPacketReceiveCallback(NULL);
353 CATCPDeinitializeQueueHandles();
355 OIC_LOG(DEBUG, TAG, "OUT");
358 void CATCPSendDataThread(void *threadData)
360 OIC_LOG(DEBUG, TAG, "IN");
362 CATCPData *TCPData = (CATCPData *) threadData;
365 OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
369 if (TCPData->isMulticast)
371 //Processing for sending multicast
372 OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
377 //Processing for sending unicast
378 CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
381 OIC_LOG(DEBUG, TAG, "OUT");
384 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
385 size_t dataLength, bool isMulticast)
387 VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
389 CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
392 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
396 TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
397 TCPData->data = (void *) OICMalloc(dataLength);
400 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
401 CAFreeTCPData(TCPData);
405 memcpy(TCPData->data, data, dataLength);
406 TCPData->dataLen = dataLength;
408 TCPData->isMulticast = isMulticast;
413 void CAFreeTCPData(CATCPData *TCPData)
415 VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
417 CAFreeEndpoint(TCPData->remoteEndpoint);
418 OICFree(TCPData->data);
422 void CADataDestroyer(void *data, size_t size)
424 if (size < sizeof(CATCPData))
426 OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
428 CATCPData *TCPData = (CATCPData *) data;
430 CAFreeTCPData(TCPData);