replaced current TAG with 'OIC_xxx' commonly in CA
[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 #define __STDC_FORMAT_MACROS
27 #include <inttypes.h>
28
29 #include "catcpadapter.h"
30 #include "catcpinterface.h"
31 #include "caqueueingthread.h"
32 #include "caadapterutils.h"
33 #include "camutex.h"
34 #include "uarraylist.h"
35 #include "caremotehandler.h"
36 #include "logger.h"
37 #include "oic_malloc.h"
38 #include "oic_string.h"
39
40 /**
41  * Logging tag for module name.
42  */
43 #define TAG "OIC_CA_TCP_ADAP"
44
45 /**
46  * Holds internal thread TCP data information.
47  */
48 typedef struct
49 {
50     CAEndpoint_t *remoteEndpoint;
51     void *data;
52     size_t dataLen;
53     bool isMulticast;
54 } CATCPData;
55
56 #define CA_TCP_LISTEN_BACKLOG  3
57
58 #define CA_TCP_SELECT_TIMEOUT 10
59
60 /**
61  * Queue handle for Send Data.
62  */
63 static CAQueueingThread_t *g_sendQueueHandle = NULL;
64
65 /**
66  * Network Packet Received Callback to CA.
67  */
68 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
69
70 /**
71  * Network Changed Callback to CA.
72  */
73 static CANetworkChangeCallback g_networkChangeCallback = NULL;
74
75 /**
76  * error Callback to CA adapter.
77  */
78 static CAErrorHandleCallback g_errorCallback = NULL;
79
80 static void CATCPPacketReceivedCB(const CASecureEndpoint_t *sep,
81                                   const void *data, uint32_t dataLength);
82
83 static CAResult_t CATCPInitializeQueueHandles();
84
85 static void CATCPDeinitializeQueueHandles();
86
87 static void CATCPSendDataThread(void *threadData);
88
89 static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
90                                   const void *data, size_t dataLength,
91                                   bool isMulticast);
92 void CAFreeTCPData(CATCPData *ipData);
93
94 static void CADataDestroyer(void *data, uint32_t size);
95
96 CAResult_t CATCPInitializeQueueHandles()
97 {
98     // Check if the message queue is already initialized
99     if (g_sendQueueHandle)
100     {
101         OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
102         return CA_STATUS_OK;
103     }
104
105     // Create send message queue
106     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
107     if (!g_sendQueueHandle)
108     {
109         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
110         return CA_MEMORY_ALLOC_FAILED;
111     }
112
113     if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
114                                 (const ca_thread_pool_t)caglobals.tcp.threadpool,
115                                 CATCPSendDataThread, CADataDestroyer))
116     {
117         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
118         OICFree(g_sendQueueHandle);
119         g_sendQueueHandle = NULL;
120         return CA_STATUS_FAILED;
121     }
122
123     return CA_STATUS_OK;
124 }
125
126 void CATCPDeinitializeQueueHandles()
127 {
128     CAQueueingThreadDestroy(g_sendQueueHandle);
129     OICFree(g_sendQueueHandle);
130     g_sendQueueHandle = NULL;
131 }
132
133 void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
134 {
135     (void)ipAddress;
136     (void)status;
137 }
138
139 void CATCPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
140                            uint32_t dataLength)
141 {
142     VERIFY_NON_NULL_VOID(sep, TAG, "sep is NULL");
143     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
144
145     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
146
147     if (g_networkPacketCallback)
148     {
149         g_networkPacketCallback(sep, data, dataLength);
150     }
151 }
152
153 void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
154                        uint32_t dataLength, CAResult_t result)
155 {
156     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
157     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
158
159     if (g_errorCallback)
160     {
161         g_errorCallback(endpoint, data, dataLength, result);
162     }
163 }
164
165 static void CAInitializeTCPGlobals()
166 {
167     caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
168     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
169     caglobals.tcp.svrlist = NULL;
170
171     CATransportFlags_t flags = 0;
172     if (caglobals.client)
173     {
174         flags |= caglobals.clientFlags;
175     }
176     if (caglobals.server)
177     {
178         flags |= caglobals.serverFlags;
179     }
180
181     caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
182 }
183
184 CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
185                            CANetworkPacketReceivedCallback networkPacketCallback,
186                            CANetworkChangeCallback netCallback,
187                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
188 {
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");
194
195     g_networkChangeCallback = netCallback;
196     g_networkPacketCallback = networkPacketCallback;
197     g_errorCallback = errorCallback;
198
199     CAInitializeTCPGlobals();
200     caglobals.tcp.threadpool = handle;
201
202     CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
203     CATCPSetErrorHandler(CATCPErrorHandler);
204
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);
217
218     OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
219     return CA_STATUS_OK;
220 }
221
222 CAResult_t CAStartTCP()
223 {
224     if (CA_STATUS_OK != CATCPInitializeQueueHandles())
225     {
226         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
227         CATerminateTCP();
228         return CA_STATUS_FAILED;
229     }
230
231     // Start send queue thread
232     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
233     {
234         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
235         return CA_STATUS_FAILED;
236     }
237
238     CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
239     if (CA_STATUS_OK != ret)
240     {
241         OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
242         return ret;
243     }
244
245     return CA_STATUS_OK;
246 }
247
248 CAResult_t CAStartTCPListeningServer()
249 {
250     return CA_STATUS_OK;
251 }
252
253 CAResult_t CAStopTCPListeningServer()
254 {
255     return CA_STATUS_OK;
256 }
257
258 CAResult_t CAStartTCPDiscoveryServer()
259 {
260     return CA_STATUS_OK;
261 }
262
263 static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
264                              const void *data, size_t dataLength)
265 {
266     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", -1);
267     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
268
269     if (0 == dataLength)
270     {
271         OIC_LOG(ERROR, TAG, "Invalid Data Length");
272         return -1;
273     }
274
275     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
276
277     // Create TCPData to add to queue
278     CATCPData *tcpData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
279     if (!tcpData)
280     {
281         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
282         return -1;
283     }
284     // Add message to send queue
285     CAQueueingThreadAddData(g_sendQueueHandle, tcpData, sizeof(CATCPData));
286
287     return dataLength;
288 }
289
290 int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
291                              const void *data, uint32_t dataLength)
292 {
293     return CAQueueTCPData(false, endpoint, data, dataLength);
294 }
295
296 int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
297                                const void *data, uint32_t dataLength)
298 {
299     return CAQueueTCPData(true, endpoint, data, dataLength);
300 }
301
302 CAResult_t CAReadTCPData()
303 {
304     return CA_STATUS_OK;
305 }
306
307 CAResult_t CAStopTCP()
308 {
309     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
310     {
311         CAQueueingThreadStop(g_sendQueueHandle);
312     }
313
314     CATCPStopServer();
315
316     //Re-initializing the Globals to start them again
317     CAInitializeTCPGlobals();
318
319     return CA_STATUS_OK;
320 }
321
322 void CATerminateTCP()
323 {
324     CATCPSetPacketReceiveCallback(NULL);
325
326     CATCPDeinitializeQueueHandles();
327 }
328
329 void CATCPSendDataThread(void *threadData)
330 {
331     CATCPData *tcpData = (CATCPData *) threadData;
332     if (!tcpData)
333     {
334         OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
335         return;
336     }
337
338     if (tcpData->isMulticast)
339     {
340         //Processing for sending multicast
341         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
342         return;
343     }
344     else
345     {
346         //Processing for sending unicast
347         CATCPSendData(tcpData->remoteEndpoint, tcpData->data, tcpData->dataLen, false);
348     }
349 }
350
351 CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
352                            size_t dataLength, bool isMulticast)
353 {
354     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
355     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", NULL);
356
357     CATCPData *tcpData = (CATCPData *) OICCalloc(1, sizeof(*tcpData));
358     if (!tcpData)
359     {
360         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
361         return NULL;
362     }
363
364     tcpData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
365     tcpData->data = (void *) OICMalloc(dataLength);
366     if (!tcpData->data)
367     {
368         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
369         CAFreeTCPData(tcpData);
370         return NULL;
371     }
372
373     memcpy(tcpData->data, data, dataLength);
374     tcpData->dataLen = dataLength;
375
376     tcpData->isMulticast = isMulticast;
377
378     return tcpData;
379 }
380
381 void CAFreeTCPData(CATCPData *tcpData)
382 {
383     VERIFY_NON_NULL_VOID(tcpData, TAG, "tcpData is NULL");
384
385     CAFreeEndpoint(tcpData->remoteEndpoint);
386     OICFree(tcpData->data);
387     OICFree(tcpData);
388 }
389
390 void CADataDestroyer(void *data, uint32_t size)
391 {
392     if (size < sizeof(CATCPData))
393     {
394         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %" PRIu32, data, size);
395     }
396     CATCPData *TCPData = (CATCPData *) data;
397
398     CAFreeTCPData(TCPData);
399 }