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