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