9ddc7e8aa0cd0d51904afea1200cf5df0e6becb1
[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 #ifdef HAVE_WS2TCPIP_H
30 #include <ws2tcpip.h>
31 #endif
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
37 #endif
38 #if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
39 #include <winsock2.h>
40 #include <ws2tcpip.h>
41 #endif
42 #ifdef HAVE_NETDB_H
43 #include <netdb.h>
44 #endif
45
46 #ifdef __ANDROID__
47 #include <jni.h>
48 #endif
49
50 #define CA_ADAPTER_UTILS_TAG "OIC_CA_ADAP_UTILS"
51
52 #ifdef __ANDROID__
53 /**
54  * @var g_jvm
55  * @brief pointer to store JavaVM
56  */
57 static JavaVM *g_jvm = NULL;
58
59 /**
60  * @var gContext
61  * @brief pointer to store context for android callback interface
62  */
63 static jobject g_Context = NULL;
64 static jobject g_Activity = NULL;
65 #endif
66
67 #ifdef WITH_ARDUINO
68 CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
69                                    size_t ipAddrLen, uint16_t *port)
70 {
71     if (!ipAddr || !isdigit(ipAddrStr[0]) || !port)
72     {
73         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
74         return CA_STATUS_INVALID_PARAM;
75     }
76
77     size_t index = 0;
78     uint8_t dotCount = 0;
79
80     ipAddr[index] = 0;
81     *port = 0;
82     while (*ipAddrStr)
83     {
84         if (isdigit(*ipAddrStr))
85         {
86             if(index >= ipAddrLen)
87             {
88                 OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
89                 return CA_STATUS_INVALID_PARAM;
90             }
91             ipAddr[index] *= 10;
92             ipAddr[index] += *ipAddrStr - '0';
93         }
94         else if (*ipAddrStr == '.')
95         {
96             index++;
97             dotCount++;
98             ipAddr[index] = 0;
99         }
100         else
101         {
102             break;
103         }
104         ipAddrStr++;
105     }
106
107     if (*ipAddrStr == ':')
108     {
109         ipAddrStr++;
110         while (*ipAddrStr)
111         {
112             if (isdigit(*ipAddrStr))
113             {
114                 *port *= 10;
115                 *port += *ipAddrStr - '0';
116             }
117             else
118             {
119                 break;
120             }
121             ipAddrStr++;
122         }
123     }
124
125     if (dotCount == 3)
126     {
127         return CA_STATUS_OK;
128     }
129     return CA_STATUS_FAILED;
130 }
131
132 #else // not with_arduino
133 /*
134  * These two conversion functions return void because errors can't happen
135  * (because of NI_NUMERIC), and there's nothing to do if they do happen.
136  */
137 void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
138                          char *host, uint16_t *port)
139 {
140     VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
141     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
142     VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
143
144     int r = getnameinfo((struct sockaddr *)sockAddr,
145                         sockAddrLen,
146                         host, MAX_ADDR_STR_SIZE_CA,
147                         NULL, 0,
148                         NI_NUMERICHOST|NI_NUMERICSERV);
149     if (r)
150     {
151 #if defined(EAI_SYSTEM)
152         if (EAI_SYSTEM == r)
153         {
154             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
155                             "getnameinfo failed: errno %s", strerror(errno));
156         }
157         else
158         {
159             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
160                             "getnameinfo failed: %s", gai_strerror(r));
161         }
162 #elif defined(_WIN32)
163         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
164                             "getnameinfo failed: errno %i", WSAGetLastError());
165 #else
166         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
167                             "getnameinfo failed: %s", gai_strerror(r));
168 #endif
169         return;
170     }
171     *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
172 }
173
174 void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
175 {
176     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
177     VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
178
179     struct addrinfo *addrs;
180     struct addrinfo hints = { .ai_family = AF_UNSPEC,
181                               .ai_socktype = SOCK_DGRAM,
182                               .ai_flags = AI_NUMERICHOST };
183
184     int r = getaddrinfo(host, NULL, &hints, &addrs);
185     if (r)
186     {
187 #if defined(EAI_SYSTEM)
188         if (EAI_SYSTEM == r)
189         {
190             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
191                             "getaddrinfo failed: errno %s", strerror(errno));
192         }
193         else
194         {
195             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
196                             "getaddrinfo failed: %s", gai_strerror(r));
197         }
198 #elif defined(_WIN32)
199         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
200                             "getaddrinfo failed: errno %i", WSAGetLastError());
201 #else
202         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
203                             "getaddrinfo failed: %s", gai_strerror(r));
204 #endif
205         return;
206     }
207     // assumption: in this case, getaddrinfo will only return one addrinfo
208     // or first is the one we want.
209     if (addrs[0].ai_family == AF_INET6)
210     {
211         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
212         ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
213     }
214     else
215     {
216         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
217         ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
218     }
219     freeaddrinfo(addrs);
220 }
221 #endif // WITH_ARDUINO
222
223 #ifdef __ANDROID__
224 void CANativeJNISetContext(JNIEnv *env, jobject context)
225 {
226     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
227
228     if (!context)
229     {
230         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "context is null");
231         return;
232     }
233
234     if (!g_Context)
235     {
236         g_Context = (*env)->NewGlobalRef(env, context);
237     }
238     else
239     {
240         OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "context is already set");
241     }
242 }
243
244 void CANativeJNISetJavaVM(JavaVM *jvm)
245 {
246     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
247     g_jvm = jvm;
248 }
249
250 jobject CANativeJNIGetContext()
251 {
252     return g_Context;
253 }
254
255 JavaVM *CANativeJNIGetJavaVM()
256 {
257     return g_jvm;
258 }
259
260 void CANativeSetActivity(JNIEnv *env, jobject activity)
261 {
262     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeSetActivity");
263
264     if (!activity)
265     {
266         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "activity is null");
267         return;
268     }
269
270     if (!g_Activity)
271     {
272         g_Activity = (*env)->NewGlobalRef(env, activity);
273     }
274     else
275     {
276         OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "activity is already set");
277     }
278 }
279
280 jobject *CANativeGetActivity()
281 {
282     return g_Activity;
283 }
284
285 jmethodID CAGetJNIMethodID(JNIEnv *env, const char* className,
286                            const char* methodName,
287                            const char* methodFormat)
288 {
289     VERIFY_NON_NULL_RET(env, CA_ADAPTER_UTILS_TAG, "env", NULL);
290     VERIFY_NON_NULL_RET(className, CA_ADAPTER_UTILS_TAG, "className", NULL);
291     VERIFY_NON_NULL_RET(methodName, CA_ADAPTER_UTILS_TAG, "methodName", NULL);
292     VERIFY_NON_NULL_RET(methodFormat, CA_ADAPTER_UTILS_TAG, "methodFormat", NULL);
293
294     jclass jni_cid = (*env)->FindClass(env, className);
295     if (!jni_cid)
296     {
297         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_cid [%s] is null", className);
298         return NULL;
299     }
300
301     jmethodID jni_midID = (*env)->GetMethodID(env, jni_cid, methodName, methodFormat);
302     if (!jni_midID)
303     {
304         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_midID [%s] is null", methodName);
305         (*env)->DeleteLocalRef(env, jni_cid);
306         return NULL;
307     }
308
309     (*env)->DeleteLocalRef(env, jni_cid);
310     return jni_midID;
311 }
312
313 void CADeleteGlobalReferences(JNIEnv *env)
314 {
315     if (g_Context)
316     {
317         (*env)->DeleteGlobalRef(env, g_Context);
318         g_Context = NULL;
319     }
320
321     if (g_Activity)
322     {
323         (*env)->DeleteGlobalRef(env, g_Activity);
324         g_Activity = NULL;
325     }
326 }
327 #endif