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