Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipadapter_singlethread.c
1 /******************************************************************
2  *
3  * Copyright 2014 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 "caipadapter_singlethread.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include "caadapterutils.h"
28 #include "logger.h"
29 #include "oic_malloc.h"
30 #include "caipinterface_singlethread.h"
31
32 /**
33  * @def TAG
34  * @brief Logging tag for module name
35  */
36 #define TAG "IPAD"
37
38 /**
39  * @def CA_PORT
40  * @brief Unicast port number (to listen for incoming data on unicast server).
41  * Note :- Actual port number may differ based on result of bind() operation.
42  */
43 #define CA_PORT   6298
44
45 /**
46  * @def CA_SECURE_PORT
47  * @brief Secured (unicast) port number as defined in COAP Specification, RFC-7252.
48  */
49 #define CA_SECURE_PORT   5684
50
51 /**
52  * @def CA_MCAST_PORT
53  * @brief Multicast port number as defined in COAP Specification, RFC-7252.
54  */
55 #define CA_MCAST_PORT   5683
56
57 /**
58  * @def CA_MULTICAST_IP
59  * @brief Multicast IP Address
60  */
61 #define CA_MULTICAST_IP "224.0.1.187"
62
63 /* Skip Queue */
64 /**
65  * @var g_networkPacketCallback
66  * @brief Network Packet Received Callback to CA
67  */
68 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
69
70 /**
71  * @var g_networkChangeCallback
72  * @brief Network Changed Callback to CA
73  */
74
75 static CANetworkChangeCallback g_networkChangeCallback = NULL;
76
77 /**
78  * @var g_isMulticastServerStarted
79  * @brief Flag to check if multicast server is started
80  */
81 static bool g_isMulticastServerStarted = false;
82
83 /**
84  * @var g_startUnicastServerRequested
85  * @brief Flag to check if server start requested by CA.
86  */
87 static bool g_startUnicastServerRequested = false;
88
89 /**
90  * @var g_unicastServerport
91  * @brief port number on which unicast server is running.
92  */
93 static uint16_t g_unicastServerport = 0;
94
95 /**
96  * @var g_startMulticastServerRequested
97  * @brief Flag to check if server start requested by CA.
98  */
99 static bool g_startMulticastServerRequested = false;
100
101
102 static void CAIPNotifyNetworkChange(const char *address, uint16_t port,
103                                           CANetworkStatus_t status);
104 static void CAIPConnectionStateCB(const char *ipAddress,
105                                         CANetworkStatus_t status);
106 static void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port,
107                                        const void *data, uint32_t dataLength);
108 static CAResult_t CAIPStopServers();
109
110 void CAIPNotifyNetworkChange(const char *address, uint16_t port, CANetworkStatus_t status)
111 {
112     CALocalConnectivity_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_IPV4, address);
113     if (!localEndpoint)
114     {
115         OIC_LOG(ERROR, TAG, "Out of memory!");
116         return;
117     }
118     localEndpoint->addressInfo.IP.port = port;
119
120     if (NULL != g_networkChangeCallback)
121     {
122         g_networkChangeCallback(localEndpoint, status);
123     }
124
125     CAAdapterFreeLocalEndpoint(localEndpoint);
126 }
127
128 void CAIPConnectionStateCB(const char *ipAddr,
129                                  CANetworkStatus_t status)
130 {
131     OIC_LOG(DEBUG, TAG, "IN");
132
133     CAResult_t ret = CA_STATUS_FAILED;
134     /* If IP is connected, then get the latest IP from the IP Interface
135       * and start unicast and multicast servers if requested earlier */
136     if (CA_INTERFACE_UP == status)
137     {
138         uint16_t port = CA_PORT;
139         int32_t serverFd = -1;
140         /* Start Unicast server if requested earlier */
141         if (g_startUnicastServerRequested)
142         {
143             ret = CAIPStartUnicastServer("0.0.0.0", &port, false, &serverFd);
144             if (CA_STATUS_OK == ret)
145             {
146                 OIC_LOG_V(DEBUG, TAG, "unicast started:%d", port);
147                 CAIPSetUnicastSocket(serverFd);
148                 CAIPSetUnicastPort(port);
149                 g_unicastServerport = port;
150             }
151             else
152             {
153                 OIC_LOG_V(ERROR, TAG, "FAILED:%d", ret);
154             }
155         }
156
157         /* Start Multicast server if requested earlier */
158         if (g_startMulticastServerRequested)
159         {
160             uint16_t multicastPort = CA_MCAST_PORT;
161             ret = CAIPStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, multicastPort, &serverFd);
162             if (CA_STATUS_OK == ret)
163             {
164                 OIC_LOG_V(DEBUG, TAG, "multicast started:%d", multicastPort);
165                 g_isMulticastServerStarted = true;
166             }
167             else
168             {
169                 OIC_LOG_V(ERROR, TAG, "strt mcast srv fail:%d", ret);
170             }
171         }
172
173         char *ipAddress = NULL;
174         char *ifcName = NULL;
175         CAResult_t ret = CAIPGetInterfaceInfo(&ifcName, &ipAddress);
176         if (CA_STATUS_OK != ret)
177         {
178             OIC_LOG_V(ERROR, TAG, "get interface info fail:%d", ret);
179             OICFree(ipAddress);
180             OICFree(ifcName);
181             return;
182         }
183         /* Notify network change to CA */
184         CAIPNotifyNetworkChange(ipAddress, port, status);
185         OICFree(ipAddress);
186         OICFree(ifcName);
187     }
188     else
189     {
190         CAIPNotifyNetworkChange("", 0, status);
191         /* Stop both Unicast and Multicast servers */
192         ret = CAIPStopServers();
193         if (CA_STATUS_OK != ret)
194         {
195             OIC_LOG_V(ERROR, TAG, "stop srv fail:%d", ret);
196             return;
197         }
198     }
199
200     OIC_LOG(DEBUG, TAG, "OUT");
201 }
202
203 void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port,
204                                 const void *data, uint32_t dataLength)
205 {
206     OIC_LOG(DEBUG, TAG, "IN");
207     OIC_LOG_V(DEBUG, TAG, "sddress:%s", ipAddress);
208     OIC_LOG_V(DEBUG, TAG, "port:%d", port);
209     OIC_LOG_V(DEBUG, TAG, "data:%s", data);
210
211     /* CA is freeing this memory */
212     CARemoteEndpoint_t *endPoint = CAAdapterCreateRemoteEndpoint(CA_IPV4, ipAddress, NULL);
213     if (NULL == endPoint)
214     {
215         OIC_LOG(ERROR, TAG, "Out of memory!");
216         return;
217     }
218     endPoint->addressInfo.IP.port = port;
219
220     if (g_networkPacketCallback)
221     {
222         g_networkPacketCallback(endPoint, data, dataLength);
223     }
224     CAAdapterFreeRemoteEndpoint(endPoint);
225     OIC_LOG(DEBUG, TAG, "OUT");
226 }
227
228 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
229                                 CANetworkPacketReceivedCallback networkPacketCallback,
230                                 CANetworkChangeCallback netCallback)
231 {
232     OIC_LOG(DEBUG, TAG, "IN");
233     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
234     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
235     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
236
237     g_networkChangeCallback = netCallback;
238     g_networkPacketCallback = networkPacketCallback;
239
240     CAResult_t ret = CAIPInitializeNetworkMonitor();
241     if (CA_STATUS_OK != ret)
242     {
243         OIC_LOG_V(ERROR, TAG, "init n/w fail:%d", ret);
244         return ret;
245     }
246     CAIPSetConnectionStateChangeCallback(CAIPConnectionStateCB);
247
248     ret = CAIPInitializeServer();
249     if (CA_STATUS_OK != ret)
250     {
251         OIC_LOG_V(ERROR, TAG, "init fail:%d", ret);
252         CATerminateIP();
253         return ret;
254     }
255     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
256
257     CAConnectivityHandler_t IPHandler;
258     IPHandler.startAdapter = CAStartIP;
259     IPHandler.startListenServer = CAStartIPListeningServer;
260     IPHandler.startDiscoveryServer = CAStartIPDiscoveryServer;
261     IPHandler.sendData = CASendIPUnicastData;
262     IPHandler.sendDataToAll = CASendIPMulticastData;
263     IPHandler.GetnetInfo = CAGetIPInterfaceInformation;
264     IPHandler.readData = CAReadIPData;
265     IPHandler.stopAdapter = CAStopIP;
266     IPHandler.terminate = CATerminateIP;
267     registerCallback(IPHandler, CA_IPV4);
268
269     OIC_LOG(INFO, TAG, "success");
270     OIC_LOG(DEBUG, TAG, "OUT");
271     return CA_STATUS_OK;
272 }
273
274 CAResult_t CAStartIP()
275 {
276     OIC_LOG(DEBUG, TAG, "IN");
277
278     /* Start monitoring IP network */
279     CAResult_t ret = CAIPStartNetworkMonitor();
280     if (CA_STATUS_OK != ret)
281     {
282         OIC_LOG(ERROR, TAG, "strt n/w monitor fail");
283     }
284
285     g_startUnicastServerRequested = true;
286     bool retVal = CAIPIsConnected();
287     if (false == retVal)
288     {
289         OIC_LOG(ERROR, TAG, "not connected");
290         return ret;
291     }
292
293     uint16_t unicastPort = CA_PORT;
294     int32_t serverFd = 0;
295     // Address is hardcoded as we are using Single Interface
296     ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false, &serverFd);
297     if (CA_STATUS_OK == ret)
298     {
299         OIC_LOG_V(DEBUG, TAG, "unicast started:%d", unicastPort);
300         CAIPSetUnicastSocket(serverFd);
301         CAIPSetUnicastPort(unicastPort);
302         g_unicastServerport = unicastPort;
303     }
304
305     OIC_LOG(DEBUG, TAG, "OUT");
306     return ret;
307 }
308
309 CAResult_t CAStartIPListeningServer()
310 {
311     OIC_LOG(DEBUG, TAG, "IN");
312
313     CAResult_t ret = CA_STATUS_OK;
314     uint16_t multicastPort = CA_MCAST_PORT;
315     int32_t serverFD = 1;
316     if (g_isMulticastServerStarted == true)
317     {
318         OIC_LOG(ERROR, TAG, "Already Started!");
319         return CA_SERVER_STARTED_ALREADY;
320     }
321
322     g_startMulticastServerRequested = true;
323     bool retVal = CAIPIsConnected();
324     if (false == retVal)
325     {
326         OIC_LOG(ERROR, TAG,"Not connected");
327         return CA_ADAPTER_NOT_ENABLED;
328     }
329
330     ret = CAIPStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, multicastPort, &serverFD);
331     if (CA_STATUS_OK == ret)
332     {
333         OIC_LOG(INFO, TAG, "multicast success");
334         g_isMulticastServerStarted = true;
335     }
336
337     OIC_LOG(DEBUG, TAG, "OUT");
338     return ret;
339 }
340
341 CAResult_t CAStartIPDiscoveryServer()
342 {
343     OIC_LOG(DEBUG, TAG, "IN");
344     /* Both listening and discovery server are same */
345     OIC_LOG(DEBUG, TAG, "OUT");
346     return CAStartIPListeningServer();
347 }
348
349 int32_t CASendIPUnicastData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
350                                   uint32_t dataLength)
351 {
352     OIC_LOG(DEBUG, TAG, "IN");
353
354     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint", -1);
355     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
356     if (dataLength == 0)
357     {
358         OIC_LOG(ERROR, TAG, "Invalid length");
359         return -1;
360     }
361
362     CAIPSendData(remoteEndpoint->addressInfo.IP.ipAddress,
363                        remoteEndpoint->addressInfo.IP.port, data, dataLength, false);
364     OIC_LOG(DEBUG, TAG, "OUT");
365     return dataLength;
366 }
367
368 int32_t CASendIPMulticastData(const void *data, uint32_t dataLength)
369 {
370     OIC_LOG(DEBUG, TAG, "IN");
371
372     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
373     if (dataLength == 0)
374     {
375         OIC_LOG(ERROR, TAG, "Invalid length");
376         return -1;
377     }
378
379     CAIPSendData(CA_MULTICAST_IP, CA_MCAST_PORT, data, dataLength, true);
380     OIC_LOG(DEBUG, TAG, "OUT");
381     return dataLength;
382 }
383
384 CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
385 {
386     OIC_LOG(DEBUG, TAG, "IN");
387     VERIFY_NON_NULL(info, TAG, "info");
388     VERIFY_NON_NULL(size, TAG, "size");
389
390     bool retVal = CAIPIsConnected();
391     if (false == retVal)
392     {
393         OIC_LOG(ERROR, TAG, "Not connected");
394         return CA_ADAPTER_NOT_ENABLED;
395     }
396
397     char *ipAddress = NULL;
398     char *ifcName = NULL;
399     CAResult_t ret = CAIPGetInterfaceInfo(&ipAddress, &ifcName);
400     if (CA_STATUS_OK != ret)
401     {
402         OIC_LOG_V(ERROR, TAG, "get interface info fail:%d", ret);
403         OICFree(ipAddress);
404         OICFree(ifcName);
405         return ret;
406     }
407
408     // Create local endpoint using util function
409     (*info) = CAAdapterCreateLocalEndpoint(CA_IPV4, ipAddress);
410     if (NULL == (*info))
411     {
412         OIC_LOG(ERROR, TAG, "malloc fail");
413         OICFree(ipAddress);
414         OICFree(ifcName);
415         return CA_MEMORY_ALLOC_FAILED;
416     }
417
418     (*info)->addressInfo.IP.port = g_unicastServerport;
419     (*size) = 1;
420
421     OICFree(ipAddress);
422     OICFree(ifcName);
423
424     OIC_LOG(INFO, TAG, "success");
425     OIC_LOG(DEBUG, TAG, "OUT");
426     return CA_STATUS_OK;
427 }
428
429 CAResult_t CAReadIPData()
430 {
431     CAIPPullData();
432     return CA_STATUS_OK;
433 }
434
435 CAResult_t CAIPStopServers()
436 {
437     CAResult_t result = CAIPStopUnicastServer();
438     if (CA_STATUS_OK != result)
439     {
440         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
441         return result;
442     }
443     CAIPSetUnicastSocket(-1);
444     CAIPSetUnicastPort(0);
445     g_unicastServerport = 0;
446
447     result = CAIPStopMulticastServer();
448     if (CA_STATUS_OK != result)
449     {
450         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
451         return result;
452     }
453     g_isMulticastServerStarted = false;
454
455     return result;
456 }
457
458 CAResult_t CAStopIP()
459 {
460     OIC_LOG(DEBUG, TAG, "IN");
461
462     g_startUnicastServerRequested = false;
463     g_startMulticastServerRequested = false;
464     CAIPStopNetworkMonitor();
465     CAResult_t result = CAIPStopServers();
466     if (CA_STATUS_OK != result)
467     {
468         OIC_LOG_V(ERROR, TAG, "stop srv fail:%d", result);
469     }
470
471     OIC_LOG(DEBUG, TAG, "OUT");
472     return result;
473 }
474
475 void CATerminateIP()
476 {
477     OIC_LOG(DEBUG, TAG, "IN");
478
479     CAIPSetConnectionStateChangeCallback(NULL);
480     CAIPTerminateNetworkMonitor();
481     CAIPSetPacketReceiveCallback(NULL);
482     OIC_LOG(INFO, TAG, "Terminated Ethernet");
483     OIC_LOG(DEBUG, TAG, "OUT");
484     return;
485 }
486
487