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 #define __STDC_FORMAT_MACROS
29 #include "catcpadapter.h"
30 #include "catcpinterface.h"
31 #include "caqueueingthread.h"
32 #include "caadapterutils.h"
34 #include "uarraylist.h"
35 #include "caremotehandler.h"
37 #include "oic_malloc.h"
38 #include "oic_string.h"
41 * Logging tag for module name.
43 #define TAG "TCP_ADAP"
46 * Holds internal thread TCP data information.
50 CAEndpoint_t *remoteEndpoint;
56 #define CA_TCP_TIMEOUT 1000
58 #define CA_TCP_LISTEN_BACKLOG 3
61 * Queue handle for Send Data.
63 static CAQueueingThread_t *g_sendQueueHandle = NULL;
66 * Network Packet Received Callback to CA.
68 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
71 * Network Changed Callback to CA.
73 static CANetworkChangeCallback g_networkChangeCallback = NULL;
76 * error Callback to CA adapter.
78 static CAErrorHandleCallback g_errorCallback = NULL;
80 static void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint,
81 const void *data, uint32_t dataLength);
83 static CAResult_t CATCPInitializeQueueHandles();
85 static void CATCPDeinitializeQueueHandles();
87 static void CATCPSendDataThread(void *threadData);
89 static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
90 const void *data, size_t dataLength,
92 void CAFreeTCPData(CATCPData *ipData);
94 static void CADataDestroyer(void *data, uint32_t size);
96 CAResult_t CATCPInitializeQueueHandles()
98 OIC_LOG(DEBUG, TAG, "IN");
100 // Check if the message queue is already initialized
101 if (g_sendQueueHandle)
103 OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
107 // Create send message queue
108 g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
109 if (!g_sendQueueHandle)
111 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
112 return CA_MEMORY_ALLOC_FAILED;
115 if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
116 (const ca_thread_pool_t)caglobals.tcp.threadpool,
117 CATCPSendDataThread, CADataDestroyer))
119 OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
120 OICFree(g_sendQueueHandle);
121 g_sendQueueHandle = NULL;
122 return CA_STATUS_FAILED;
125 OIC_LOG(DEBUG, TAG, "OUT");
129 void CATCPDeinitializeQueueHandles()
131 OIC_LOG(DEBUG, TAG, "IN");
133 CAQueueingThreadDestroy(g_sendQueueHandle);
134 OICFree(g_sendQueueHandle);
135 g_sendQueueHandle = NULL;
137 OIC_LOG(DEBUG, TAG, "OUT");
140 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
144 OIC_LOG(DEBUG, TAG, "IN");
147 void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
150 OIC_LOG(DEBUG, TAG, "IN");
152 VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
153 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
155 OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
157 if (g_networkPacketCallback)
159 g_networkPacketCallback(endpoint, data, dataLength);
161 OIC_LOG(DEBUG, TAG, "OUT");
164 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
165 uint32_t dataLength, CAResult_t result)
167 OIC_LOG(DEBUG, TAG, "IN");
169 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
171 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
175 g_errorCallback(endpoint, data, dataLength, result);
178 OIC_LOG(DEBUG, TAG, "OUT");
181 static void CAInitializeTCPGlobals()
183 caglobals.tcp.selectTimeout = CA_TCP_TIMEOUT;
184 caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
185 caglobals.tcp.svrlist = NULL;
187 CATransportFlags_t flags = 0;
188 if (caglobals.client)
190 flags |= caglobals.clientFlags;
192 if (caglobals.server)
194 flags |= caglobals.serverFlags;
197 caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
200 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
201 CANetworkPacketReceivedCallback networkPacketCallback,
202 CANetworkChangeCallback netCallback,
203 CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
205 OIC_LOG(DEBUG, TAG, "IN");
206 VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
207 VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
208 VERIFY_NON_NULL(netCallback, TAG, "netCallback");
209 VERIFY_NON_NULL(handle, TAG, "thread pool handle");
211 g_networkChangeCallback = netCallback;
212 g_networkPacketCallback = networkPacketCallback;
213 g_errorCallback = errorCallback;
215 CAInitializeTCPGlobals();
216 caglobals.tcp.threadpool = handle;
218 CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
219 CATCPSetErrorHandler(CATCPErrorHandler);
221 CAConnectivityHandler_t TCPHandler = {
222 .startAdapter = CAStartTCP,
223 .startListenServer = CAStartTCPListeningServer,
224 .stopListenServer = CAStopTCPListeningServer,
225 .startDiscoveryServer = CAStartTCPDiscoveryServer,
226 .sendData = CASendTCPUnicastData,
227 .sendDataToAll = CASendTCPMulticastData,
228 .GetnetInfo = CAGetTCPInterfaceInformation,
229 .readData = CAReadTCPData,
230 .stopAdapter = CAStopTCP,
231 .terminate = CATerminateTCP };
232 registerCallback(TCPHandler, CA_ADAPTER_TCP);
234 OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
238 CAResult_t CAStartTCP()
240 OIC_LOG(DEBUG, TAG, "IN");
242 if (CA_STATUS_OK != CATCPInitializeQueueHandles())
244 OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
246 return CA_STATUS_FAILED;
249 // Start send queue thread
250 if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
252 OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
253 return CA_STATUS_FAILED;
256 CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
257 if (CA_STATUS_OK != ret)
259 OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
263 OIC_LOG(DEBUG, TAG, "OUT");
267 CAResult_t CAStartTCPListeningServer()
269 OIC_LOG(DEBUG, TAG, "IN");
271 OIC_LOG(DEBUG, TAG, "OUT");
275 CAResult_t CAStopTCPListeningServer()
277 OIC_LOG(DEBUG, TAG, "IN");
279 OIC_LOG(DEBUG, TAG, "OUT");
283 CAResult_t CAStartTCPDiscoveryServer()
285 OIC_LOG(DEBUG, TAG, "IN");
287 OIC_LOG(DEBUG, TAG, "OUT");
291 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
292 const void *data, size_t dataLength)
294 OIC_LOG(DEBUG, TAG, "IN");
296 VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
297 VERIFY_NON_NULL_RET(data, TAG, "data", -1);
301 OIC_LOG(ERROR, TAG, "Invalid Data Length");
305 VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
307 // Create TCPData to add to queue
308 CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
311 OIC_LOG(ERROR, TAG, "Failed to create ipData!");
314 // Add message to send queue
315 CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
317 OIC_LOG(DEBUG, TAG, "OUT");
321 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
322 const void *data, uint32_t dataLength)
324 OIC_LOG(DEBUG, TAG, "IN");
325 return CAQueueTCPData(false, endpoint, data, dataLength);
328 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
329 const void *data, uint32_t dataLength)
331 OIC_LOG(DEBUG, TAG, "IN");
332 return CAQueueTCPData(true, endpoint, data, dataLength);
335 CAResult_t CAReadTCPData()
337 OIC_LOG(DEBUG, TAG, "IN");
338 OIC_LOG(DEBUG, TAG, "OUT");
342 CAResult_t CAStopTCP()
344 OIC_LOG(DEBUG, TAG, "IN");
346 if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
348 CAQueueingThreadStop(g_sendQueueHandle);
351 CATCPDeinitializeQueueHandles();
355 OIC_LOG(DEBUG, TAG, "OUT");
359 void CATerminateTCP()
361 OIC_LOG(DEBUG, TAG, "IN");
363 CATCPSetPacketReceiveCallback(NULL);
365 CATCPDeinitializeQueueHandles();
367 OIC_LOG(DEBUG, TAG, "OUT");
370 void CATCPSendDataThread(void *threadData)
372 OIC_LOG(DEBUG, TAG, "IN");
374 CATCPData *TCPData = (CATCPData *) threadData;
377 OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
381 if (TCPData->isMulticast)
383 //Processing for sending multicast
384 OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
389 //Processing for sending unicast
390 CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
393 OIC_LOG(DEBUG, TAG, "OUT");
396 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
397 size_t dataLength, bool isMulticast)
399 VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
401 CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
404 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
408 TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
409 TCPData->data = (void *) OICMalloc(dataLength);
412 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
413 CAFreeTCPData(TCPData);
417 memcpy(TCPData->data, data, dataLength);
418 TCPData->dataLen = dataLength;
420 TCPData->isMulticast = isMulticast;
425 void CAFreeTCPData(CATCPData *TCPData)
427 VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
429 CAFreeEndpoint(TCPData->remoteEndpoint);
430 OICFree(TCPData->data);
434 void CADataDestroyer(void *data, uint32_t size)
436 if (size < sizeof(CATCPData))
438 OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
440 CATCPData *TCPData = (CATCPData *) data;
442 CAFreeTCPData(TCPData);