IP address plumbing changes to support IPv6
[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     CAEndpoint_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_IPV4, address);
113     if (!localEndpoint)
114     {
115         OIC_LOG(ERROR, TAG, "Out of memory!");
116         return;
117     }
118     localEndpoint->port = port;
119
120     if (NULL != g_networkChangeCallback)
121     {
122         g_networkChangeCallback(localEndpoint, status);
123     }
124
125     CAAdapterFreeEndpoint(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     CAEndpoint_t *endPoint = CAAdapterCreateEndpoint(CA_DEFAULT_FLAGS, CA_IPV4, ipAddress, port);
213     if (NULL == endPoint)
214     {
215         OIC_LOG(ERROR, TAG, "Out of memory!");
216         return;
217     }
218
219     if (g_networkPacketCallback)
220     {
221         g_networkPacketCallback(endPoint, data, dataLength);
222     }
223     CAAdapterFreeEndpoint(endPoint);
224     OIC_LOG(DEBUG, TAG, "OUT");
225 }
226
227 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
228                                 CANetworkPacketReceivedCallback networkPacketCallback,
229                                 CANetworkChangeCallback netCallback)
230 {
231     OIC_LOG(DEBUG, TAG, "IN");
232     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
233     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
234     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
235
236     g_networkChangeCallback = netCallback;
237     g_networkPacketCallback = networkPacketCallback;
238
239     CAResult_t ret = CAIPInitializeNetworkMonitor();
240     if (CA_STATUS_OK != ret)
241     {
242         OIC_LOG_V(ERROR, TAG, "init n/w fail:%d", ret);
243         return ret;
244     }
245     CAIPSetConnectionStateChangeCallback(CAIPConnectionStateCB);
246
247     ret = CAIPInitializeServer();
248     if (CA_STATUS_OK != ret)
249     {
250         OIC_LOG_V(ERROR, TAG, "init fail:%d", ret);
251         CATerminateIP();
252         return ret;
253     }
254     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
255
256     CAConnectivityHandler_t IPHandler;
257     IPHandler.startAdapter = CAStartIP;
258     IPHandler.startListenServer = CAStartIPListeningServer;
259     IPHandler.startDiscoveryServer = CAStartIPDiscoveryServer;
260     IPHandler.sendData = CASendIPUnicastData;
261     IPHandler.sendDataToAll = CASendIPMulticastData;
262     IPHandler.GetnetInfo = CAGetIPInterfaceInformation;
263     IPHandler.readData = CAReadIPData;
264     IPHandler.stopAdapter = CAStopIP;
265     IPHandler.terminate = CATerminateIP;
266     registerCallback(IPHandler, CA_IPV4);
267
268     OIC_LOG(INFO, TAG, "success");
269     OIC_LOG(DEBUG, TAG, "OUT");
270     return CA_STATUS_OK;
271 }
272
273 CAResult_t CAStartIP()
274 {
275     OIC_LOG(DEBUG, TAG, "IN");
276
277     /* Start monitoring IP network */
278     CAResult_t ret = CAIPStartNetworkMonitor();
279     if (CA_STATUS_OK != ret)
280     {
281         OIC_LOG(ERROR, TAG, "strt n/w monitor fail");
282     }
283
284     g_startUnicastServerRequested = true;
285     bool retVal = CAIPIsConnected();
286     if (false == retVal)
287     {
288         OIC_LOG(ERROR, TAG, "not connected");
289         return ret;
290     }
291
292     uint16_t unicastPort = CA_PORT;
293     int32_t serverFd = 0;
294     // Address is hardcoded as we are using Single Interface
295     ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false, &serverFd);
296     if (CA_STATUS_OK == ret)
297     {
298         OIC_LOG_V(DEBUG, TAG, "unicast started:%d", unicastPort);
299         CAIPSetUnicastSocket(serverFd);
300         CAIPSetUnicastPort(unicastPort);
301         g_unicastServerport = unicastPort;
302     }
303
304     OIC_LOG(DEBUG, TAG, "OUT");
305     return ret;
306 }
307
308 CAResult_t CAStartIPListeningServer()
309 {
310     OIC_LOG(DEBUG, TAG, "IN");
311
312     CAResult_t ret = CA_STATUS_OK;
313     uint16_t multicastPort = CA_MCAST_PORT;
314     int32_t serverFD = 1;
315     if (g_isMulticastServerStarted == true)
316     {
317         OIC_LOG(ERROR, TAG, "Already Started!");
318         return CA_SERVER_STARTED_ALREADY;
319     }
320
321     g_startMulticastServerRequested = true;
322     bool retVal = CAIPIsConnected();
323     if (false == retVal)
324     {
325         OIC_LOG(ERROR, TAG,"Not connected");
326         return CA_ADAPTER_NOT_ENABLED;
327     }
328
329     ret = CAIPStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, multicastPort, &serverFD);
330     if (CA_STATUS_OK == ret)
331     {
332         OIC_LOG(INFO, TAG, "multicast success");
333         g_isMulticastServerStarted = true;
334     }
335
336     OIC_LOG(DEBUG, TAG, "OUT");
337     return ret;
338 }
339
340 CAResult_t CAStartIPDiscoveryServer()
341 {
342     OIC_LOG(DEBUG, TAG, "IN");
343     /* Both listening and discovery server are same */
344     OIC_LOG(DEBUG, TAG, "OUT");
345     return CAStartIPListeningServer();
346 }
347
348 int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
349 {
350     OIC_LOG(DEBUG, TAG, "IN");
351
352     VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
353     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
354     if (dataLength == 0)
355     {
356         OIC_LOG(ERROR, TAG, "Invalid length");
357         return -1;
358     }
359
360     CAIPSendData(endpoint->addr, endpoint->port, data, dataLength, false);
361     OIC_LOG(DEBUG, TAG, "OUT");
362     return dataLength;
363 }
364
365 int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
366 {
367     OIC_LOG(DEBUG, TAG, "IN");
368
369     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
370     if (dataLength == 0)
371     {
372         OIC_LOG(ERROR, TAG, "Invalid length");
373         return -1;
374     }
375
376     CAIPSendData(CA_MULTICAST_IP, CA_MCAST_PORT, data, dataLength, true);
377     OIC_LOG(DEBUG, TAG, "OUT");
378     return dataLength;
379 }
380
381 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
382 {
383     OIC_LOG(DEBUG, TAG, "IN");
384     VERIFY_NON_NULL(info, TAG, "info");
385     VERIFY_NON_NULL(size, TAG, "size");
386
387     bool retVal = CAIPIsConnected();
388     if (false == retVal)
389     {
390         OIC_LOG(ERROR, TAG, "Not connected");
391         return CA_ADAPTER_NOT_ENABLED;
392     }
393
394     char *ipAddress = NULL;
395     char *ifcName = NULL;
396     CAResult_t ret = CAIPGetInterfaceInfo(&ipAddress, &ifcName);
397     if (CA_STATUS_OK != ret)
398     {
399         OIC_LOG_V(ERROR, TAG, "get interface info fail:%d", ret);
400         OICFree(ipAddress);
401         OICFree(ifcName);
402         return ret;
403     }
404
405     // Create local endpoint using util function
406     (*info) = CAAdapterCreateLocalEndpoint(CA_IPV4, ipAddress);
407     if (NULL == (*info))
408     {
409         OIC_LOG(ERROR, TAG, "malloc fail");
410         OICFree(ipAddress);
411         OICFree(ifcName);
412         return CA_MEMORY_ALLOC_FAILED;
413     }
414
415     (*info)->port = g_unicastServerport;
416     (*size) = 1;
417
418     OICFree(ipAddress);
419     OICFree(ifcName);
420
421     OIC_LOG(INFO, TAG, "success");
422     OIC_LOG(DEBUG, TAG, "OUT");
423     return CA_STATUS_OK;
424 }
425
426 CAResult_t CAReadIPData()
427 {
428     CAIPPullData();
429     return CA_STATUS_OK;
430 }
431
432 CAResult_t CAIPStopServers()
433 {
434     CAResult_t result = CAIPStopUnicastServer();
435     if (CA_STATUS_OK != result)
436     {
437         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
438         return result;
439     }
440     CAIPSetUnicastSocket(-1);
441     CAIPSetUnicastPort(0);
442     g_unicastServerport = 0;
443
444     result = CAIPStopMulticastServer();
445     if (CA_STATUS_OK != result)
446     {
447         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
448         return result;
449     }
450     g_isMulticastServerStarted = false;
451
452     return result;
453 }
454
455 CAResult_t CAStopIP()
456 {
457     OIC_LOG(DEBUG, TAG, "IN");
458
459     g_startUnicastServerRequested = false;
460     g_startMulticastServerRequested = false;
461     CAIPStopNetworkMonitor();
462     CAResult_t result = CAIPStopServers();
463     if (CA_STATUS_OK != result)
464     {
465         OIC_LOG_V(ERROR, TAG, "stop srv fail:%d", result);
466     }
467
468     OIC_LOG(DEBUG, TAG, "OUT");
469     return result;
470 }
471
472 void CATerminateIP()
473 {
474     OIC_LOG(DEBUG, TAG, "IN");
475
476     CAIPSetConnectionStateChangeCallback(NULL);
477     CAIPTerminateNetworkMonitor();
478     CAIPSetPacketReceiveCallback(NULL);
479     OIC_LOG(INFO, TAG, "Terminated Ethernet");
480     OIC_LOG(DEBUG, TAG, "OUT");
481     return;
482 }
483
484