Merge branch 'security-CKM' into '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         .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);
229
230     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
231     return CA_STATUS_OK;
232 }
233
234 CAResult_t CAStartTCP()
235 {
236     OIC_LOG(DEBUG, TAG, "IN");
237
238     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
239     {
240         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
241         CATerminateTCP();
242         return CA_STATUS_FAILED;
243     }
244
245     // Start send queue thread
246     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
247     {
248         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
249         return CA_STATUS_FAILED;
250     }
251
252     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
253     if (CA_STATUS_OK != ret)
254     {
255         OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
256         return ret;
257     }
258
259     OIC_LOG(DEBUG, TAG, "OUT");
260     return CA_STATUS_OK;
261 }
262
263 CAResult_t CAStartTCPListeningServer()
264 {
265     OIC_LOG(DEBUG, TAG, "IN");
266
267     OIC_LOG(DEBUG, TAG, "OUT");
268     return CA_STATUS_OK;
269 }
270
271 CAResult_t CAStartTCPDiscoveryServer()
272 {
273     OIC_LOG(DEBUG, TAG, "IN");
274
275     OIC_LOG(DEBUG, TAG, "OUT");
276     return CA_STATUS_OK;
277 }
278
279 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
280                              const void *data, size_t dataLength)
281 {
282     OIC_LOG(DEBUG, TAG, "IN");
283
284     VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
285     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
286
287     if (0 == dataLength)
288     {
289         OIC_LOG(ERROR, TAG, "Invalid Data Length");
290         return -1;
291     }
292
293     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
294
295     // Create TCPData to add to queue
296     CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
297     if (!TCPData)
298     {
299         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
300         return -1;
301     }
302     // Add message to send queue
303     CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
304
305     OIC_LOG(DEBUG, TAG, "OUT");
306     return dataLength;
307 }
308
309 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
310                              const void *data, uint32_t dataLength)
311 {
312     OIC_LOG(DEBUG, TAG, "IN");
313     return CAQueueTCPData(false, endpoint, data, dataLength);
314 }
315
316 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
317                                const void *data, uint32_t dataLength)
318 {
319     OIC_LOG(DEBUG, TAG, "IN");
320     return CAQueueTCPData(true, endpoint, data, dataLength);
321 }
322
323 CAResult_t CAReadTCPData()
324 {
325     OIC_LOG(DEBUG, TAG, "IN");
326     OIC_LOG(DEBUG, TAG, "OUT");
327     return CA_STATUS_OK;
328 }
329
330 CAResult_t CAStopTCP()
331 {
332     OIC_LOG(DEBUG, TAG, "IN");
333
334     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
335     {
336         CAQueueingThreadStop(g_sendQueueHandle);
337     }
338
339     CATCPDeinitializeQueueHandles();
340
341     CATCPStopServer();
342
343     OIC_LOG(DEBUG, TAG, "OUT");
344     return CA_STATUS_OK;
345 }
346
347 void CATerminateTCP()
348 {
349     OIC_LOG(DEBUG, TAG, "IN");
350
351     CATCPSetPacketReceiveCallback(NULL);
352
353     CATCPDeinitializeQueueHandles();
354
355     OIC_LOG(DEBUG, TAG, "OUT");
356 }
357
358 void CATCPSendDataThread(void *threadData)
359 {
360     OIC_LOG(DEBUG, TAG, "IN");
361
362     CATCPData *TCPData = (CATCPData *) threadData;
363     if (!TCPData)
364     {
365         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
366         return;
367     }
368
369     if (TCPData->isMulticast)
370     {
371         //Processing for sending multicast
372         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
373         return;
374     }
375     else
376     {
377         //Processing for sending unicast
378         CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
379     }
380
381     OIC_LOG(DEBUG, TAG, "OUT");
382 }
383
384 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
385                            size_t dataLength, bool isMulticast)
386 {
387     VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
388
389     CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
390     if (!TCPData)
391     {
392         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
393         return NULL;
394     }
395
396     TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
397     TCPData->data = (void *) OICMalloc(dataLength);
398     if (!TCPData->data)
399     {
400         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
401         CAFreeTCPData(TCPData);
402         return NULL;
403     }
404
405     memcpy(TCPData->data, data, dataLength);
406     TCPData->dataLen = dataLength;
407
408     TCPData->isMulticast = isMulticast;
409
410     return TCPData;
411 }
412
413 void CAFreeTCPData(CATCPData *TCPData)
414 {
415     VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
416
417     CAFreeEndpoint(TCPData->remoteEndpoint);
418     OICFree(TCPData->data);
419     OICFree(TCPData);
420 }
421
422 void CADataDestroyer(void *data, size_t size)
423 {
424     if (size < sizeof(CATCPData))
425     {
426         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
427     }
428     CATCPData *TCPData = (CATCPData *) data;
429
430     CAFreeTCPData(TCPData);
431 }