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 .stopListenServer = CAStopTCPListeningServer,
222 .startDiscoveryServer = CAStartTCPDiscoveryServer,
223 .sendData = CASendTCPUnicastData,
224 .sendDataToAll = CASendTCPMulticastData,
225 .GetnetInfo = CAGetTCPInterfaceInformation,
226 .readData = CAReadTCPData,
227 .stopAdapter = CAStopTCP,
228 .terminate = CATerminateTCP };
229 registerCallback(TCPHandler, CA_ADAPTER_TCP);
231 OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
235 CAResult_t CAStartTCP()
237 OIC_LOG(DEBUG, TAG, "IN");
239 if (CA_STATUS_OK != CATCPInitializeQueueHandles())
241 OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
243 return CA_STATUS_FAILED;
246 // Start send queue thread
247 if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
249 OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
250 return CA_STATUS_FAILED;
253 CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
254 if (CA_STATUS_OK != ret)
256 OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
260 OIC_LOG(DEBUG, TAG, "OUT");
264 CAResult_t CAStartTCPListeningServer()
266 OIC_LOG(DEBUG, TAG, "IN");
268 OIC_LOG(DEBUG, TAG, "OUT");
272 CAResult_t CAStopTCPListeningServer()
274 OIC_LOG(DEBUG, TAG, "IN");
276 OIC_LOG(DEBUG, TAG, "OUT");
280 CAResult_t CAStartTCPDiscoveryServer()
282 OIC_LOG(DEBUG, TAG, "IN");
284 OIC_LOG(DEBUG, TAG, "OUT");
288 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
289 const void *data, size_t dataLength)
291 OIC_LOG(DEBUG, TAG, "IN");
293 VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
294 VERIFY_NON_NULL_RET(data, TAG, "data", -1);
298 OIC_LOG(ERROR, TAG, "Invalid Data Length");
302 VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
304 // Create TCPData to add to queue
305 CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
308 OIC_LOG(ERROR, TAG, "Failed to create ipData!");
311 // Add message to send queue
312 CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
314 OIC_LOG(DEBUG, TAG, "OUT");
318 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
319 const void *data, uint32_t dataLength)
321 OIC_LOG(DEBUG, TAG, "IN");
322 return CAQueueTCPData(false, endpoint, data, dataLength);
325 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
326 const void *data, uint32_t dataLength)
328 OIC_LOG(DEBUG, TAG, "IN");
329 return CAQueueTCPData(true, endpoint, data, dataLength);
332 CAResult_t CAReadTCPData()
334 OIC_LOG(DEBUG, TAG, "IN");
335 OIC_LOG(DEBUG, TAG, "OUT");
339 CAResult_t CAStopTCP()
341 OIC_LOG(DEBUG, TAG, "IN");
343 if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
345 CAQueueingThreadStop(g_sendQueueHandle);
348 CATCPDeinitializeQueueHandles();
352 OIC_LOG(DEBUG, TAG, "OUT");
356 void CATerminateTCP()
358 OIC_LOG(DEBUG, TAG, "IN");
360 CATCPSetPacketReceiveCallback(NULL);
362 CATCPDeinitializeQueueHandles();
364 OIC_LOG(DEBUG, TAG, "OUT");
367 void CATCPSendDataThread(void *threadData)
369 OIC_LOG(DEBUG, TAG, "IN");
371 CATCPData *TCPData = (CATCPData *) threadData;
374 OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
378 if (TCPData->isMulticast)
380 //Processing for sending multicast
381 OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
386 //Processing for sending unicast
387 CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
390 OIC_LOG(DEBUG, TAG, "OUT");
393 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
394 size_t dataLength, bool isMulticast)
396 VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
398 CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
401 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
405 TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
406 TCPData->data = (void *) OICMalloc(dataLength);
409 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
410 CAFreeTCPData(TCPData);
414 memcpy(TCPData->data, data, dataLength);
415 TCPData->dataLen = dataLength;
417 TCPData->isMulticast = isMulticast;
422 void CAFreeTCPData(CATCPData *TCPData)
424 VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
426 CAFreeEndpoint(TCPData->remoteEndpoint);
427 OICFree(TCPData->data);
431 void CADataDestroyer(void *data, size_t size)
433 if (size < sizeof(CATCPData))
435 OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
437 CATCPData *TCPData = (CATCPData *) data;
439 CAFreeTCPData(TCPData);