Merge Resource Directory into the master
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / tcp_adapter / catcpadapter.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25
26 #include "catcpadapter.h"
27 #include "catcpinterface.h"
28 #include "caqueueingthread.h"
29 #include "caadapterutils.h"
30 #include "camutex.h"
31 #include "uarraylist.h"
32 #include "caremotehandler.h"
33 #include "logger.h"
34 #include "oic_malloc.h"
35 #include "oic_string.h"
36
37 /**
38  * Logging tag for module name.
39  */
40 #define TAG "TCP_ADAP"
41
42 /**
43  * Holds internal thread TCP data information.
44  */
45 typedef struct
46 {
47     CAEndpoint_t *remoteEndpoint;
48     void *data;
49     size_t dataLen;
50     bool isMulticast;
51 } CATCPData;
52
53 #define CA_TCP_TIMEOUT 1000
54
55 #define CA_TCP_LISTEN_BACKLOG  3
56
57 /**
58  * Queue handle for Send Data.
59  */
60 static CAQueueingThread_t *g_sendQueueHandle = NULL;
61
62 /**
63  * Network Packet Received Callback to CA.
64  */
65 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
66
67 /**
68  * Network Changed Callback to CA.
69  */
70 static CANetworkChangeCallback g_networkChangeCallback = NULL;
71
72 /**
73  * error Callback to CA adapter.
74  */
75 static CAErrorHandleCallback g_errorCallback = NULL;
76
77 static void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint,
78                                   const void *data, size_t dataLength);
79
80 static CAResult_t CATCPInitializeQueueHandles();
81
82 static void CATCPDeinitializeQueueHandles();
83
84 static void CATCPSendDataThread(void *threadData);
85
86 static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
87                                   const void *data, size_t dataLength,
88                                   bool isMulticast);
89 void CAFreeTCPData(CATCPData *ipData);
90
91 static void CADataDestroyer(void *data, size_t size);
92
93 CAResult_t CATCPInitializeQueueHandles()
94 {
95     OIC_LOG(DEBUG, TAG, "IN");
96
97     // Check if the message queue is already initialized
98     if (g_sendQueueHandle)
99     {
100         OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
101         return CA_STATUS_OK;
102     }
103
104     // Create send message queue
105     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
106     if (!g_sendQueueHandle)
107     {
108         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
109         return CA_MEMORY_ALLOC_FAILED;
110     }
111
112     if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
113                                 (const ca_thread_pool_t)caglobals.tcp.threadpool,
114                                 CATCPSendDataThread, CADataDestroyer))
115     {
116         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
117         OICFree(g_sendQueueHandle);
118         g_sendQueueHandle = NULL;
119         return CA_STATUS_FAILED;
120     }
121
122     OIC_LOG(DEBUG, TAG, "OUT");
123     return CA_STATUS_OK;
124 }
125
126 void CATCPDeinitializeQueueHandles()
127 {
128     OIC_LOG(DEBUG, TAG, "IN");
129
130     CAQueueingThreadDestroy(g_sendQueueHandle);
131     OICFree(g_sendQueueHandle);
132     g_sendQueueHandle = NULL;
133
134     OIC_LOG(DEBUG, TAG, "OUT");
135 }
136
137 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
138 {
139     (void)ipAddress;
140     (void)status;
141     OIC_LOG(DEBUG, TAG, "IN");
142 }
143
144 void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
145                            size_t dataLength)
146 {
147     OIC_LOG(DEBUG, TAG, "IN");
148
149     VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
150     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
151
152     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
153
154     if (g_networkPacketCallback)
155     {
156         g_networkPacketCallback(endpoint, data, dataLength);
157     }
158     OIC_LOG(DEBUG, TAG, "OUT");
159 }
160
161 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
162                        size_t dataLength, CAResult_t result)
163 {
164     OIC_LOG(DEBUG, TAG, "IN");
165
166     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
167
168     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
169
170     if (g_errorCallback)
171     {
172         g_errorCallback(endpoint, data, dataLength, result);
173     }
174
175     OIC_LOG(DEBUG, TAG, "OUT");
176 }
177
178 static void CAInitializeTCPGlobals()
179 {
180     caglobals.tcp.selectTimeout = CA_TCP_TIMEOUT;
181     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
182     caglobals.tcp.svrlist = NULL;
183
184     CATransportFlags_t flags = 0;
185     if (caglobals.client)
186     {
187         flags |= caglobals.clientFlags;
188     }
189     if (caglobals.server)
190     {
191         flags |= caglobals.serverFlags;
192     }
193
194     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
195 }
196
197 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
198                            CANetworkPacketReceivedCallback networkPacketCallback,
199                            CANetworkChangeCallback netCallback,
200                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
201 {
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");
207
208     g_networkChangeCallback = netCallback;
209     g_networkPacketCallback = networkPacketCallback;
210     g_errorCallback = errorCallback;
211
212     CAInitializeTCPGlobals();
213     caglobals.tcp.threadpool = handle;
214
215     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
216     CATCPSetErrorHandler(CATCPErrorHandler);
217
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);
230
231     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
232     return CA_STATUS_OK;
233 }
234
235 CAResult_t CAStartTCP()
236 {
237     OIC_LOG(DEBUG, TAG, "IN");
238
239     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
240     {
241         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
242         CATerminateTCP();
243         return CA_STATUS_FAILED;
244     }
245
246     // Start send queue thread
247     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
248     {
249         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
250         return CA_STATUS_FAILED;
251     }
252
253     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
254     if (CA_STATUS_OK != ret)
255     {
256         OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
257         return ret;
258     }
259
260     OIC_LOG(DEBUG, TAG, "OUT");
261     return CA_STATUS_OK;
262 }
263
264 CAResult_t CAStartTCPListeningServer()
265 {
266     OIC_LOG(DEBUG, TAG, "IN");
267
268     OIC_LOG(DEBUG, TAG, "OUT");
269     return CA_STATUS_OK;
270 }
271
272 CAResult_t CAStopTCPListeningServer()
273 {
274     OIC_LOG(DEBUG, TAG, "IN");
275
276     OIC_LOG(DEBUG, TAG, "OUT");
277     return CA_STATUS_OK;
278 }
279
280 CAResult_t CAStartTCPDiscoveryServer()
281 {
282     OIC_LOG(DEBUG, TAG, "IN");
283
284     OIC_LOG(DEBUG, TAG, "OUT");
285     return CA_STATUS_OK;
286 }
287
288 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
289                              const void *data, size_t dataLength)
290 {
291     OIC_LOG(DEBUG, TAG, "IN");
292
293     VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
294     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
295
296     if (0 == dataLength)
297     {
298         OIC_LOG(ERROR, TAG, "Invalid Data Length");
299         return -1;
300     }
301
302     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
303
304     // Create TCPData to add to queue
305     CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
306     if (!TCPData)
307     {
308         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
309         return -1;
310     }
311     // Add message to send queue
312     CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
313
314     OIC_LOG(DEBUG, TAG, "OUT");
315     return dataLength;
316 }
317
318 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
319                              const void *data, uint32_t dataLength)
320 {
321     OIC_LOG(DEBUG, TAG, "IN");
322     return CAQueueTCPData(false, endpoint, data, dataLength);
323 }
324
325 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
326                                const void *data, uint32_t dataLength)
327 {
328     OIC_LOG(DEBUG, TAG, "IN");
329     return CAQueueTCPData(true, endpoint, data, dataLength);
330 }
331
332 CAResult_t CAReadTCPData()
333 {
334     OIC_LOG(DEBUG, TAG, "IN");
335     OIC_LOG(DEBUG, TAG, "OUT");
336     return CA_STATUS_OK;
337 }
338
339 CAResult_t CAStopTCP()
340 {
341     OIC_LOG(DEBUG, TAG, "IN");
342
343     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
344     {
345         CAQueueingThreadStop(g_sendQueueHandle);
346     }
347
348     CATCPDeinitializeQueueHandles();
349
350     CATCPStopServer();
351
352     OIC_LOG(DEBUG, TAG, "OUT");
353     return CA_STATUS_OK;
354 }
355
356 void CATerminateTCP()
357 {
358     OIC_LOG(DEBUG, TAG, "IN");
359
360     CATCPSetPacketReceiveCallback(NULL);
361
362     CATCPDeinitializeQueueHandles();
363
364     OIC_LOG(DEBUG, TAG, "OUT");
365 }
366
367 void CATCPSendDataThread(void *threadData)
368 {
369     OIC_LOG(DEBUG, TAG, "IN");
370
371     CATCPData *TCPData = (CATCPData *) threadData;
372     if (!TCPData)
373     {
374         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
375         return;
376     }
377
378     if (TCPData->isMulticast)
379     {
380         //Processing for sending multicast
381         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
382         return;
383     }
384     else
385     {
386         //Processing for sending unicast
387         CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
388     }
389
390     OIC_LOG(DEBUG, TAG, "OUT");
391 }
392
393 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
394                            size_t dataLength, bool isMulticast)
395 {
396     VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
397
398     CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
399     if (!TCPData)
400     {
401         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
402         return NULL;
403     }
404
405     TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
406     TCPData->data = (void *) OICMalloc(dataLength);
407     if (!TCPData->data)
408     {
409         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
410         CAFreeTCPData(TCPData);
411         return NULL;
412     }
413
414     memcpy(TCPData->data, data, dataLength);
415     TCPData->dataLen = dataLength;
416
417     TCPData->isMulticast = isMulticast;
418
419     return TCPData;
420 }
421
422 void CAFreeTCPData(CATCPData *TCPData)
423 {
424     VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
425
426     CAFreeEndpoint(TCPData->remoteEndpoint);
427     OICFree(TCPData->data);
428     OICFree(TCPData);
429 }
430
431 void CADataDestroyer(void *data, size_t size)
432 {
433     if (size < sizeof(CATCPData))
434     {
435         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
436     }
437     CATCPData *TCPData = (CATCPData *) data;
438
439     CAFreeTCPData(TCPData);
440 }