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