Imported Upstream version 1.0.1
[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 #ifdef WITH_ARDUINO
56 CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
57                                    size_t ipAddrLen, uint16_t *port)
58 {
59     if (!ipAddr || !isdigit(ipAddrStr[0]) || !port)
60     {
61         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
62         return CA_STATUS_INVALID_PARAM;
63     }
64
65     size_t index = 0;
66     uint8_t dotCount = 0;
67
68     ipAddr[index] = 0;
69     *port = 0;
70     while (*ipAddrStr)
71     {
72         if (isdigit(*ipAddrStr))
73         {
74             if(index >= ipAddrLen)
75             {
76                 OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
77                 return CA_STATUS_INVALID_PARAM;
78             }
79             ipAddr[index] *= 10;
80             ipAddr[index] += *ipAddrStr - '0';
81         }
82         else if (*ipAddrStr == '.')
83         {
84             index++;
85             dotCount++;
86             ipAddr[index] = 0;
87         }
88         else
89         {
90             break;
91         }
92         ipAddrStr++;
93     }
94
95     if (*ipAddrStr == ':')
96     {
97         ipAddrStr++;
98         while (*ipAddrStr)
99         {
100             if (isdigit(*ipAddrStr))
101             {
102                 *port *= 10;
103                 *port += *ipAddrStr - '0';
104             }
105             else
106             {
107                 break;
108             }
109             ipAddrStr++;
110         }
111     }
112
113     if (dotCount == 3)
114     {
115         return CA_STATUS_OK;
116     }
117     return CA_STATUS_FAILED;
118 }
119
120 #else // not with_arduino
121 /*
122  * These two conversion functions return void because errors can't happen
123  * (because of NI_NUMERIC), and there's nothing to do if they do happen.
124  */
125 void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
126                          char *host, uint16_t *port)
127 {
128     VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
129     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
130     VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
131
132     int r = getnameinfo((struct sockaddr *)sockAddr,
133                         sockAddrLen,
134                         host, MAX_ADDR_STR_SIZE_CA,
135                         NULL, 0,
136                         NI_NUMERICHOST|NI_NUMERICSERV);
137     if (r)
138     {
139         if (EAI_SYSTEM == r)
140         {
141             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
142                             "getnameinfo failed: errno %s", strerror(errno));
143         }
144         else
145         {
146             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
147                             "getnameinfo failed: %s", gai_strerror(r));
148         }
149         return;
150     }
151     *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
152 }
153
154 void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
155 {
156     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
157     VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
158
159     struct addrinfo *addrs;
160     struct addrinfo hints = { .ai_family = AF_UNSPEC,
161                               .ai_socktype = SOCK_DGRAM,
162                               .ai_flags = AI_NUMERICHOST };
163
164     int r = getaddrinfo(host, NULL, &hints, &addrs);
165     if (r)
166     {
167         if (EAI_SYSTEM == r)
168         {
169             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
170                             "getaddrinfo failed: errno %s", strerror(errno));
171         }
172         else
173         {
174             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
175                             "getaddrinfo failed: %s", gai_strerror(r));
176         }
177         return;
178     }
179     // assumption: in this case, getaddrinfo will only return one addrinfo
180     // or first is the one we want.
181     if (addrs[0].ai_family == AF_INET6)
182     {
183         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
184         ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
185     }
186     else
187     {
188         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
189         ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
190     }
191     freeaddrinfo(addrs);
192 }
193 #endif // WITH_ARDUINO
194
195 #ifdef __ANDROID__
196 void CANativeJNISetContext(JNIEnv *env, jobject context)
197 {
198     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
199
200     if (!context)
201     {
202         OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "context is null");
203
204     }
205
206     g_Context = (*env)->NewGlobalRef(env, context);
207 }
208
209 void CANativeJNISetJavaVM(JavaVM *jvm)
210 {
211     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
212     g_jvm = jvm;
213 }
214
215 jobject CANativeJNIGetContext()
216 {
217     return g_Context;
218 }
219
220 JavaVM *CANativeJNIGetJavaVM()
221 {
222     return g_jvm;
223 }
224 #endif