replace : iotivity -> iotivity-sec
[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 "iotivity_config.h"
22 #include "caadapterutils.h"
23
24 #include <string.h>
25 #include <ctype.h>
26 #include "oic_string.h"
27 #include "oic_malloc.h"
28 #include <errno.h>
29
30 #ifdef HAVE_WS2TCPIP_H
31 #include <ws2tcpip.h>
32 #endif
33 #ifdef HAVE_SYS_SOCKET_H
34 #include <sys/socket.h>
35 #endif
36 #ifdef HAVE_NETINET_IN_H
37 #include <netinet/in.h>
38 #endif
39 #if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
40 #include <winsock2.h>
41 #include <ws2tcpip.h>
42 #endif
43 #ifdef HAVE_NETDB_H
44 #include <netdb.h>
45 #endif
46
47 #ifdef __ANDROID__
48 #include <jni.h>
49 #endif
50
51 #define CA_ADAPTER_UTILS_TAG "OIC_CA_ADAP_UTILS"
52
53 #ifdef __ANDROID__
54 /**
55  * @var g_jvm
56  * @brief pointer to store JavaVM
57  */
58 static JavaVM *g_jvm = NULL;
59
60 /**
61  * @var gContext
62  * @brief pointer to store context for android callback interface
63  */
64 static jobject g_Context = NULL;
65 static jobject g_Activity = NULL;
66 #endif
67
68 #ifdef WITH_ARDUINO
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 #else // not with_arduino
134 /*
135  * These two conversion functions return void because errors can't happen
136  * (because of NI_NUMERIC), and there's nothing to do if they do happen.
137  */
138 void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
139                          char *host, uint16_t *port)
140 {
141     VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
142     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
143     VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
144
145     int r = getnameinfo((struct sockaddr *)sockAddr,
146                         sockAddrLen,
147                         host, MAX_ADDR_STR_SIZE_CA,
148                         NULL, 0,
149                         NI_NUMERICHOST|NI_NUMERICSERV);
150     if (r)
151     {
152 #if defined(EAI_SYSTEM)
153         if (EAI_SYSTEM == r)
154         {
155             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
156                             "getnameinfo failed: errno %s", strerror(errno));
157         }
158         else
159         {
160             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
161                             "getnameinfo failed: %s", gai_strerror(r));
162         }
163 #elif defined(_WIN32)
164         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
165                             "getnameinfo failed: errno %i", WSAGetLastError());
166 #else
167         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
168                             "getnameinfo failed: %s", gai_strerror(r));
169 #endif
170         return;
171     }
172     *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
173 }
174
175 void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
176 {
177     VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
178     VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
179
180     struct addrinfo *addrs = NULL;
181     struct addrinfo hints = { .ai_family = AF_UNSPEC,
182                               .ai_socktype = SOCK_DGRAM,
183                               .ai_flags = AI_NUMERICHOST };
184
185     int r = getaddrinfo(host, NULL, &hints, &addrs);
186     if (r)
187     {
188         if (NULL != addrs)
189         {
190             freeaddrinfo(addrs);
191         }
192 #if defined(EAI_SYSTEM)
193         if (EAI_SYSTEM == r)
194         {
195             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
196                             "getaddrinfo failed: errno %s", strerror(errno));
197         }
198         else
199         {
200             OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
201                             "getaddrinfo failed: %s", gai_strerror(r));
202         }
203 #elif defined(_WIN32)
204         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
205                             "getaddrinfo failed: errno %i", WSAGetLastError());
206 #else
207         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
208                             "getaddrinfo failed: %s", gai_strerror(r));
209 #endif
210         return;
211     }
212     // assumption: in this case, getaddrinfo will only return one addrinfo
213     // or first is the one we want.
214     if (addrs[0].ai_family == AF_INET6)
215     {
216         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
217         ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
218     }
219     else
220     {
221         memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
222         ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
223     }
224     freeaddrinfo(addrs);
225 }
226 #endif // WITH_ARDUINO
227
228 #ifdef __ANDROID__
229 void CANativeJNISetContext(JNIEnv *env, jobject context)
230 {
231     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
232
233     if (!context)
234     {
235         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "context is null");
236         return;
237     }
238
239     if (!g_Context)
240     {
241         g_Context = (*env)->NewGlobalRef(env, context);
242     }
243     else
244     {
245         OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "context is already set");
246     }
247 }
248
249 void CANativeJNISetJavaVM(JavaVM *jvm)
250 {
251     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
252     g_jvm = jvm;
253 }
254
255 jobject CANativeJNIGetContext()
256 {
257     return g_Context;
258 }
259
260 JavaVM *CANativeJNIGetJavaVM()
261 {
262     return g_jvm;
263 }
264
265 void CANativeSetActivity(JNIEnv *env, jobject activity)
266 {
267     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeSetActivity");
268
269     if (!activity)
270     {
271         OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "activity is null");
272         return;
273     }
274
275     if (!g_Activity)
276     {
277         g_Activity = (*env)->NewGlobalRef(env, activity);
278     }
279     else
280     {
281         OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "activity is already set");
282     }
283 }
284
285 jobject *CANativeGetActivity()
286 {
287     return g_Activity;
288 }
289
290 jmethodID CAGetJNIMethodID(JNIEnv *env, const char* className,
291                            const char* methodName,
292                            const char* methodFormat)
293 {
294     VERIFY_NON_NULL_RET(env, CA_ADAPTER_UTILS_TAG, "env", NULL);
295     VERIFY_NON_NULL_RET(className, CA_ADAPTER_UTILS_TAG, "className", NULL);
296     VERIFY_NON_NULL_RET(methodName, CA_ADAPTER_UTILS_TAG, "methodName", NULL);
297     VERIFY_NON_NULL_RET(methodFormat, CA_ADAPTER_UTILS_TAG, "methodFormat", NULL);
298
299     jclass jni_cid = (*env)->FindClass(env, className);
300     if (!jni_cid)
301     {
302         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_cid [%s] is null", className);
303         CACheckJNIException(env);
304         return NULL;
305     }
306
307     jmethodID jni_midID = (*env)->GetMethodID(env, jni_cid, methodName, methodFormat);
308     if (!jni_midID)
309     {
310         OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_midID [%s] is null", methodName);
311         CACheckJNIException(env);
312         (*env)->DeleteLocalRef(env, jni_cid);
313         return NULL;
314     }
315
316     (*env)->DeleteLocalRef(env, jni_cid);
317     return jni_midID;
318 }
319
320 bool CACheckJNIException(JNIEnv *env)
321 {
322     if ((*env)->ExceptionCheck(env))
323     {
324         (*env)->ExceptionDescribe(env);
325         (*env)->ExceptionClear(env);
326         return true;
327     }
328     return false;
329 }
330
331 void CADeleteGlobalReferences(JNIEnv *env)
332 {
333     if (g_Context)
334     {
335         (*env)->DeleteGlobalRef(env, g_Context);
336         g_Context = NULL;
337     }
338
339     if (g_Activity)
340     {
341         (*env)->DeleteGlobalRef(env, g_Activity);
342         g_Activity = NULL;
343     }
344 }
345 #endif
346
347 #ifndef WITH_ARDUINO
348 void CALogAdapterStateInfo(CATransportAdapter_t adapter, CANetworkStatus_t state)
349 {
350     OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogAdapterStateInfo");
351     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
352     CALogAdapterTypeInfo(adapter);
353     if (CA_INTERFACE_UP == state)
354     {
355         OIC_LOG(INFO, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_UP");
356     }
357     else
358     {
359         OIC_LOG(INFO, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_DOWN");
360     }
361     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
362 }
363
364 void CALogSendStateInfo(CATransportAdapter_t adapter,
365                         const char *addr, uint16_t port, ssize_t sentLen,
366                         bool isSuccess, const char* message)
367 {
368     OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogSendStateInfo");
369     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
370
371     if (true == isSuccess)
372     {
373         OIC_LOG_V(INFO, ANALYZER_TAG, "Send Success, sent length = [%d]", sentLen);
374     }
375     else
376     {
377         OIC_LOG_V(INFO, ANALYZER_TAG, "Send Failure, error message  = [%s]",
378                   message != NULL ? message : "no message");
379     }
380
381     CALogAdapterTypeInfo(adapter);
382     OIC_LOG_V(INFO, ANALYZER_TAG, "Address = [%s]:[%d]", addr, port);
383     OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
384
385     // samsung log
386     if (true == isSuccess)
387     {
388         OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "| Analyzer(Retail) | %02x", 1);
389     }
390     else
391     {
392         OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "| Analyzer(Retail) | %02x", 0);
393     }
394 }
395
396 void CALogAdapterTypeInfo(CATransportAdapter_t adapter)
397 {
398     switch(adapter)
399     {
400         case CA_ADAPTER_IP:
401             OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_IP]");
402             break;
403         case CA_ADAPTER_TCP:
404             OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_TCP]");
405             break;
406         case CA_ADAPTER_GATT_BTLE:
407             OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_GATT_BTLE]");
408             break;
409         case CA_ADAPTER_RFCOMM_BTEDR:
410             OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_RFCOMM_BTEDR]");
411             break;
412         default:
413             OIC_LOG_V(INFO, ANALYZER_TAG, "Transport Type = [%d]", adapter);
414             break;
415     }
416 }
417 #endif