[IOT-570] fixed multicast issue
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / caadapterutils.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 "caadapterutils.h"
22
23 #include <string.h>
24 #include <ctype.h>
25 #include "oic_string.h"
26 #include "oic_malloc.h"
27 #include <errno.h>
28
29 #ifndef WITH_ARDUINO
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #endif
34
35 #ifdef __ANDROID__
36 #include <jni.h>
37 #endif
38
39 #define CA_ADAPTER_UTILS_TAG "CA_ADAPTER_UTILS"
40
41 #ifdef __ANDROID__
42 /**
43  * @var g_jvm
44  * @brief pointer to store JavaVM
45  */
46 static JavaVM *g_jvm = NULL;
47
48 /**
49  * @var gContext
50  * @brief pointer to store context for android callback interface
51  */
52 static jobject g_Context = NULL;
53 #endif
54
55 void CALogPDUData(coap_pdu_t *pdu)
56 {
57     VERIFY_NON_NULL_VOID(pdu, CA_ADAPTER_UTILS_TAG, "pdu");
58     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - payload : %s", pdu->data);
59
60     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - type : %d", pdu->hdr->type);
61
62     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - code : %d", pdu->hdr->code);
63
64     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - id : %d", pdu->hdr->id);
65
66     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - token : %s", pdu->hdr->token);
67 }
68 CAEndpoint_t *CAAdapterCreateEndpoint(CATransportFlags_t flags,
69                                       CATransportAdapter_t adapter,
70                                       const char *address,
71                                       uint16_t port)
72 {
73     CAEndpoint_t *info = (CAEndpoint_t *)OICCalloc(1, sizeof(CAEndpoint_t));
74     if (NULL == info)
75     {
76         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
77         return NULL;
78     }
79
80     if (address)
81     {
82         OICStrcpy(info->addr, sizeof(info->addr), address);
83         info->addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
84     }
85     info->flags = flags;
86     info->adapter = adapter;
87     info->port = port;
88
89     return info;
90 }
91
92 CAEndpoint_t *CAAdapterCreateLocalEndpoint(CATransportFlags_t flags,
93                         CATransportAdapter_t adapter, const char *address)
94 {
95     return CAAdapterCreateEndpoint(flags, adapter, address, 0);
96 }
97
98 CAResult_t CACreateEndpoint(CATransportFlags_t flags,
99                             CATransportAdapter_t adapter,
100                             const char *addr,
101                             uint16_t port,
102                             CAEndpoint_t **object)
103 {
104     VERIFY_NON_NULL_RET(object, CA_ADAPTER_UTILS_TAG, "Endpoint is NULL", CA_STATUS_INVALID_PARAM);
105     CAEndpoint_t *endpoint = CAAdapterCreateEndpoint(flags, adapter, addr, port);
106     if (!endpoint)
107     {
108         return CA_STATUS_FAILED;
109     }
110     *object = endpoint;
111     return CA_STATUS_OK;
112 }
113
114
115 CAEndpoint_t *CAAdapterCloneEndpoint(const CAEndpoint_t *endpoint)
116 {
117     VERIFY_NON_NULL_RET(endpoint, CA_ADAPTER_UTILS_TAG, "endpoint is NULL", NULL);
118
119     CAEndpoint_t *info = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
120     if (NULL == info)
121     {
122         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
123         return NULL;
124     }
125     *info = *endpoint;
126
127     return info;
128 }
129
130 void CAAdapterFreeEndpoint(CAEndpoint_t *remoteEndpoint)
131 {
132     OICFree(remoteEndpoint);
133 }
134
135 CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
136                                    size_t ipAddrLen, uint16_t *port)
137 {
138     if (!ipAddr || !isdigit(ipAddrStr[0]) || !port)
139     {
140         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
141         return CA_STATUS_INVALID_PARAM;
142     }
143
144     size_t index = 0;
145     uint8_t dotCount = 0;
146
147     ipAddr[index] = 0;
148     *port = 0;
149     while (*ipAddrStr)
150     {
151         if (isdigit(*ipAddrStr))
152         {
153             if(index >= ipAddrLen)
154             {
155                 OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
156                 return CA_STATUS_INVALID_PARAM;
157             }
158             ipAddr[index] *= 10;
159             ipAddr[index] += *ipAddrStr - '0';
160         }
161         else if (*ipAddrStr == '.')
162         {
163             index++;
164             dotCount++;
165             ipAddr[index] = 0;
166         }
167         else
168         {
169             break;
170         }
171         ipAddrStr++;
172     }
173
174     if (*ipAddrStr == ':')
175     {
176         ipAddrStr++;
177         while (*ipAddrStr)
178         {
179             if (isdigit(*ipAddrStr))
180             {
181                 *port *= 10;
182                 *port += *ipAddrStr - '0';
183             }
184             else
185             {
186                 break;
187             }
188             ipAddrStr++;
189         }
190     }
191
192     if (dotCount == 3)
193     {
194         return CA_STATUS_OK;
195     }
196     return CA_STATUS_FAILED;
197 }
198
199 bool CAAdapterIsSameSubnet(const char *ipAddress1, const char *ipAddress2, const char *netMask)
200 {
201     VERIFY_NON_NULL_RET(ipAddress1, CA_ADAPTER_UTILS_TAG, "First address", false);
202     VERIFY_NON_NULL_RET(ipAddress2, CA_ADAPTER_UTILS_TAG, "Second address", false);
203     VERIFY_NON_NULL_RET(netMask, CA_ADAPTER_UTILS_TAG, "netMask", false);
204
205     uint8_t ipList1[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
206     uint8_t ipList2[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
207     uint8_t maskList[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
208     CAResult_t ret = CA_STATUS_OK;
209
210     /* Local Loopback Address */
211     if (0 == strncmp(ipAddress1, "127.", 4) || 0 == strncmp(ipAddress2, "127.", 4))
212     {
213         return true;
214     }
215
216     uint16_t parsedPort = 0;
217     ret = CAParseIPv4AddressInternal(ipAddress1, ipList1, sizeof(ipList1), &parsedPort);
218     if (ret != CA_STATUS_OK)
219     {
220         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "First ip address parse fail %d", ret);
221         return false;
222     }
223
224     ret = CAParseIPv4AddressInternal(ipAddress2, ipList2, sizeof(ipList2), &parsedPort);
225     if (ret != CA_STATUS_OK)
226     {
227         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Second ip address parse fail %d", ret);
228         return false;
229     }
230
231     ret = CAParseIPv4AddressInternal(netMask, maskList, sizeof(maskList), &parsedPort);
232     if (ret != CA_STATUS_OK)
233     {
234         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Net mask parse fail %d", ret);
235         return false;
236     }
237
238     return ((ipList1[0] & maskList[0]) == (ipList2[0] & maskList[0])) && ((ipList1[1] & maskList[1])
239             == (ipList2[1] & maskList[1]))
240            && ((ipList1[2] & maskList[2]) == (ipList2[2] & maskList[2]))
241            && ((ipList1[3] & maskList[3]) == (ipList2[3] & maskList[3]));
242 }
243
244 bool CAIsMulticastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress,
245                                 const char *multicastAddress, uint16_t port)
246 {
247     VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false);
248     VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false);
249     VERIFY_NON_NULL_RET(multicastAddress, CA_ADAPTER_UTILS_TAG, "multicastAddress is null", false);
250
251     uint32_t listLength = u_arraylist_length(serverInfoList);
252     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
253     {
254         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
255         if (!info)
256         {
257             OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Info is NULL");
258             return false;
259         }
260
261         if (info->isMulticastServer && (strncmp(info->endpoint.addr, multicastAddress,
262                                                 strlen(multicastAddress)) == 0)
263             && (info->endpoint.port == port) && (strncmp(info->ifAddr, ipAddress, strlen(ipAddress)) == 0))
264         {
265             return info->isServerStarted;
266         }
267     }
268     return false;
269 }
270
271 bool CAIsUnicastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress,
272                               uint16_t port)
273 {
274     VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false);
275     VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false);
276
277     uint32_t listLength = u_arraylist_length(serverInfoList);
278     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
279     {
280         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
281         if (!info)
282         {
283             continue;
284         }
285
286         if (!info->isMulticastServer && (strncmp(info->endpoint.addr, ipAddress,
287                                                  strlen(ipAddress)) == 0)
288             && (info->endpoint.port == port))
289         {
290             return info->isServerStarted;
291         }
292     }
293     return false;
294 }
295
296 uint16_t CAGetServerPort(const u_arraylist_t *serverInfoList, const char *ipAddress, bool isSecured)
297 {
298     VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", 0);
299     VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", 0);
300
301     uint32_t listLength = u_arraylist_length(serverInfoList);
302     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
303     {
304         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
305         if (!info)
306         {
307             continue;
308         }
309         bool ifSecured = info->endpoint.flags & CA_SECURE;
310         if ((strncmp(info->endpoint.addr, ipAddress, strlen(ipAddress)) == 0) &&
311                     (ifSecured == isSecured))
312         {
313             return info->endpoint.port;
314         }
315     }
316
317     return 0;
318 }
319
320 int CAGetSocketFdForUnicastServer(const u_arraylist_t *serverInfoList,
321                                 bool isMulticast, const CAEndpoint_t *endpoint)
322 {
323     VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", -1);
324     VERIFY_NON_NULL_RET(endpoint, CA_ADAPTER_UTILS_TAG, "endpoint is null", -1);
325
326     bool isSecured = (endpoint->flags & CA_SECURE) != 0;
327
328     uint32_t listLength = u_arraylist_length(serverInfoList);
329
330     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
331     {
332         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
333         if (!info)
334         {
335             continue;
336         }
337
338         if (!CAAdapterIsSameSubnet(info->endpoint.addr, endpoint->addr, info->subNetMask))
339         {
340             continue;
341         }
342
343         bool ifSecured = info->endpoint.flags & CA_SECURE;
344         if (!info->isMulticastServer && (ifSecured == isSecured))
345         {
346             OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG,
347                       "CAGetSocketFdForServer found socket [%d]", info->socketFd);
348             return info->socketFd;
349         }
350
351     }
352
353     OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG,
354             "CAGetSocketFdForServer socket fd is not found");
355     return -1;
356 }
357
358 CAResult_t CAAddServerInfo(u_arraylist_t *serverInfoList, CAServerInfo_t *info)
359 {
360     VERIFY_NON_NULL(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null");
361     VERIFY_NON_NULL(info, CA_ADAPTER_UTILS_TAG, "info is null");
362
363     CAResult_t result = u_arraylist_add(serverInfoList, (void *) info);
364     if (CA_STATUS_OK != result)
365     {
366         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_add failed!");
367     }
368     return result;
369 }
370
371 void CARemoveServerInfo(u_arraylist_t *serverInfoList, int sockFd)
372 {
373     VERIFY_NON_NULL_VOID(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null");
374
375     uint32_t listLength = u_arraylist_length(serverInfoList);
376     for (uint32_t listIndex = 0; listIndex < listLength;)
377     {
378         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
379         if (!info)
380         {
381             listIndex++;
382             continue;
383         }
384
385         if (info->socketFd == sockFd)
386         {
387             if (u_arraylist_remove(serverInfoList, listIndex))
388             {
389                 OICFree(info);
390                 listLength--;
391             }
392             else
393             {
394                 OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_remove failed!");
395                 break;
396             }
397         }
398         else
399         {
400             listIndex++;
401         }
402     }
403 }
404
405 void CAClearNetInterfaceInfoList(u_arraylist_t *infoList)
406 {
407     uint32_t listLength = u_arraylist_length(infoList);
408     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
409     {
410         CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(infoList, listIndex);
411         if (!netInfo)
412         {
413             continue;
414         }
415         OICFree(netInfo);
416     }
417     u_arraylist_free(&infoList);
418 }
419
420 void CAClearServerInfoList(u_arraylist_t *serverInfoList)
421 {
422     uint32_t listLength = u_arraylist_length(serverInfoList);
423     for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
424     {
425         CAServerInfo_t *serverInfo = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
426         if (!serverInfo)
427         {
428             continue;
429         }
430         OICFree(serverInfo);
431     }
432     u_arraylist_free(&serverInfoList);
433 }
434
435 #ifndef WITH_ARDUINO
436 /*
437  * These two conversion functions return void because errors can't happen
438  * (because of NI_NUMERIC), and there's nothing to do if they do happen.
439  */
440 void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, char *host, uint16_t *port)
441 {
442     VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
443     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
444     VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
445
446     int r = getnameinfo((struct sockaddr *)sockAddr,
447                         sizeof (struct sockaddr_storage),
448                         host, CA_IPADDR_SIZE,
449                         NULL, 0,
450                         NI_NUMERICHOST|NI_NUMERICSERV);
451     if (r)
452     {
453         if (EAI_SYSTEM == r)
454         {
455             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
456                             "getaddrinfo failed: errno %s", strerror(errno));
457         }
458         else
459         {
460             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
461                             "getaddrinfo failed: %s", gai_strerror(r));
462         }
463         return;
464     }
465     *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
466 }
467
468 void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
469 {
470     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
471     VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
472
473     struct addrinfo *addrs;
474     struct addrinfo hints = { 0 };
475     hints.ai_family = AF_UNSPEC;
476     hints.ai_socktype = SOCK_DGRAM;
477     hints.ai_flags = AI_NUMERICHOST;
478
479     int r = getaddrinfo(host, NULL, &hints, &addrs);
480     if (r)
481     {
482         if (EAI_SYSTEM == r)
483         {
484             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
485                             "getaddrinfo failed: errno %s", strerror(errno));
486         }
487         else
488         {
489             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
490                             "getaddrinfo failed: %s", gai_strerror(r));
491         }
492         return;
493     }
494     // assumption: in this case, getaddrinfo will only return one addrinfo
495     // or first is the one we want.
496     if (addrs[0].ai_family == AF_INET6)
497     {
498         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
499         ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
500     }
501     else
502     {
503         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
504         ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
505     }
506     freeaddrinfo(addrs);
507 }
508 #endif // WITH_ARDUINO
509
510 #ifdef __ANDROID__
511 void CANativeJNISetContext(JNIEnv *env, jobject context)
512 {
513     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
514
515     if (!context)
516     {
517         OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "context is null");
518
519     }
520
521     g_Context = (*env)->NewGlobalRef(env, context);
522 }
523
524 void CANativeJNISetJavaVM(JavaVM *jvm)
525 {
526     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
527     g_jvm = jvm;
528 }
529
530 jobject CANativeJNIGetContext()
531 {
532     return g_Context;
533 }
534
535 JavaVM *CANativeJNIGetJavaVM()
536 {
537     return g_jvm;
538 }
539 #endif