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_LISTEN_BACKLOG 3
58 #define CA_TCP_SELECT_TIMEOUT 10
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 // Check if the message queue is already initialized
99 if (g_sendQueueHandle)
101 OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
105 // Create send message queue
106 g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
107 if (!g_sendQueueHandle)
109 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
110 return CA_MEMORY_ALLOC_FAILED;
113 if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
114 (const ca_thread_pool_t)caglobals.tcp.threadpool,
115 CATCPSendDataThread, CADataDestroyer))
117 OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
118 OICFree(g_sendQueueHandle);
119 g_sendQueueHandle = NULL;
120 return CA_STATUS_FAILED;
126 void CATCPDeinitializeQueueHandles()
128 CAQueueingThreadDestroy(g_sendQueueHandle);
129 OICFree(g_sendQueueHandle);
130 g_sendQueueHandle = NULL;
133 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
139 void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
142 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
143 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
145 OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
147 if (g_networkPacketCallback)
149 g_networkPacketCallback(endpoint, data, dataLength);
153 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
154 uint32_t dataLength, CAResult_t result)
156 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
157 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
161 g_errorCallback(endpoint, data, dataLength, result);
165 static void CAInitializeTCPGlobals()
167 caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
168 caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
169 caglobals.tcp.svrlist = NULL;
171 CATransportFlags_t flags = 0;
172 if (caglobals.client)
174 flags |= caglobals.clientFlags;
176 if (caglobals.server)
178 flags |= caglobals.serverFlags;
181 caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
184 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
185 CANetworkPacketReceivedCallback networkPacketCallback,
186 CANetworkChangeCallback netCallback,
187 CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
189 OIC_LOG(DEBUG, TAG, "IN");
190 VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
191 VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
192 VERIFY_NON_NULL(netCallback, TAG, "netCallback");
193 VERIFY_NON_NULL(handle, TAG, "thread pool handle");
195 g_networkChangeCallback = netCallback;
196 g_networkPacketCallback = networkPacketCallback;
197 g_errorCallback = errorCallback;
199 CAInitializeTCPGlobals();
200 caglobals.tcp.threadpool = handle;
202 CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
203 CATCPSetErrorHandler(CATCPErrorHandler);
205 CAConnectivityHandler_t TCPHandler = {
206 .startAdapter = CAStartTCP,
207 .startListenServer = CAStartTCPListeningServer,
208 .stopListenServer = CAStopTCPListeningServer,
209 .startDiscoveryServer = CAStartTCPDiscoveryServer,
210 .sendData = CASendTCPUnicastData,
211 .sendDataToAll = CASendTCPMulticastData,
212 .GetnetInfo = CAGetTCPInterfaceInformation,
213 .readData = CAReadTCPData,
214 .stopAdapter = CAStopTCP,
215 .terminate = CATerminateTCP };
216 registerCallback(TCPHandler, CA_ADAPTER_TCP);
218 OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
222 CAResult_t CAStartTCP()
224 if (CA_STATUS_OK != CATCPInitializeQueueHandles())
226 OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
228 return CA_STATUS_FAILED;
231 // Start send queue thread
232 if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
234 OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
235 return CA_STATUS_FAILED;
238 CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
239 if (CA_STATUS_OK != ret)
241 OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
248 CAResult_t CAStartTCPListeningServer()
253 CAResult_t CAStopTCPListeningServer()
258 CAResult_t CAStartTCPDiscoveryServer()
263 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
264 const void *data, size_t dataLength)
266 VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", -1);
267 VERIFY_NON_NULL_RET(data, TAG, "data", -1);
271 OIC_LOG(ERROR, TAG, "Invalid Data Length");
275 VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
277 // Create TCPData to add to queue
278 CATCPData *tcpData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
281 OIC_LOG(ERROR, TAG, "Failed to create ipData!");
284 // Add message to send queue
285 CAQueueingThreadAddData(g_sendQueueHandle, tcpData, sizeof(CATCPData));
290 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
291 const void *data, uint32_t dataLength)
293 return CAQueueTCPData(false, endpoint, data, dataLength);
296 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
297 const void *data, uint32_t dataLength)
299 return CAQueueTCPData(true, endpoint, data, dataLength);
302 CAResult_t CAReadTCPData()
307 CAResult_t CAStopTCP()
309 if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
311 CAQueueingThreadStop(g_sendQueueHandle);
314 CATCPDeinitializeQueueHandles();
316 //Re-initializing the Globals to start them again
317 CAInitializeTCPGlobals();
322 void CATerminateTCP()
324 CATCPSetPacketReceiveCallback(NULL);
326 CATCPDeinitializeQueueHandles();
329 void CATCPSendDataThread(void *threadData)
331 CATCPData *tcpData = (CATCPData *) threadData;
334 OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
338 if (tcpData->isMulticast)
340 //Processing for sending multicast
341 OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
346 //Processing for sending unicast
347 CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen, false);
351 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
352 size_t dataLength, bool isMulticast)
354 VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
355 VERIFY_NON_NULL_RET(data, TAG, "data is NULL", NULL);
357 CATCPData *tcpData = (CATCPData *) OICCalloc(1, sizeof(*tcpData));
360 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
364 tcpData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
365 tcpData->data = (void *) OICMalloc(dataLength);
368 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
369 CAFreeTCPData(tcpData);
373 memcpy(tcpData->data, data, dataLength);
374 tcpData->dataLen = dataLength;
376 tcpData->isMulticast = isMulticast;
381 void CAFreeTCPData(CATCPData *tcpData)
383 VERIFY_NON_NULL_VOID(tcpData, TAG, "tcpData is NULL");
385 CAFreeEndpoint(tcpData->remoteEndpoint);
386 OICFree(tcpData->data);
390 void CADataDestroyer(void *data, uint32_t size)
392 if (size < sizeof(CATCPData))
394 OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
396 CATCPData *TCPData = (CATCPData *) data;
398 CAFreeTCPData(TCPData);