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