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