*
******************************************************************/
+#include "iotivity_config.h"
#include "caadapterutils.h"
#include <string.h>
-#ifndef __ARDUINO__
+#include <ctype.h>
+#include "oic_string.h"
#include "oic_malloc.h"
-#endif //#ifndef __ARDUINO__
-#define CA_ADAPTER_UTILS_TAG "CA_ADAPTER_UTILS"
+#include <errno.h>
-CALocalConnectivity_t *CAAdapterCreateLocalEndpoint(CAConnectivityType_t type, const char *address,
- const char *interfaceName)
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef __ANDROID__
+#include <jni.h>
+#endif
+
+#define CA_ADAPTER_UTILS_TAG "OIC_CA_ADAP_UTILS"
+
+#ifdef __ANDROID__
+/**
+ * @var g_jvm
+ * @brief pointer to store JavaVM
+ */
+static JavaVM *g_jvm = NULL;
+
+/**
+ * @var gContext
+ * @brief pointer to store context for android callback interface
+ */
+static jobject g_Context = NULL;
+static jobject g_Activity = NULL;
+#endif
+
+#ifdef WITH_ARDUINO
+CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
+ size_t ipAddrLen, uint16_t *port)
{
- CALocalConnectivity_t *info = (CALocalConnectivity_t *) OICMalloc(
- sizeof(CALocalConnectivity_t));
- if (NULL == info)
+ if (!ipAddr || !isdigit(ipAddrStr[0]) || !port)
{
- OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
- return NULL;
+ OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
+ return CA_STATUS_INVALID_PARAM;
}
- memset(info, 0, sizeof(CALocalConnectivity_t));
- info->type = type;
- if (address && strlen(address))
+ size_t index = 0;
+ uint8_t dotCount = 0;
+
+ ipAddr[index] = 0;
+ *port = 0;
+ while (*ipAddrStr)
{
- if (CA_EDR == type)
+ if (isdigit(*ipAddrStr))
{
- strncpy(info->addressInfo.BT.btMacAddress, address, CA_MACADDR_SIZE - 1);
- info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ if(index >= ipAddrLen)
+ {
+ OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "invalid param");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ ipAddr[index] *= 10;
+ ipAddr[index] += *ipAddrStr - '0';
}
- else if (CA_LE == type)
+ else if (*ipAddrStr == '.')
{
- strncpy(info->addressInfo.LE.leMacAddress, address, CA_MACADDR_SIZE - 1);
- info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ index++;
+ dotCount++;
+ ipAddr[index] = 0;
}
- else if (CA_WIFI == type || CA_ETHERNET == type)
+ else
{
- strncpy(info->addressInfo.IP.ipAddress, address, CA_IPADDR_SIZE - 1);
- info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ break;
}
+ ipAddrStr++;
}
- return info;
+ if (*ipAddrStr == ':')
+ {
+ ipAddrStr++;
+ while (*ipAddrStr)
+ {
+ if (isdigit(*ipAddrStr))
+ {
+ *port *= 10;
+ *port += *ipAddrStr - '0';
+ }
+ else
+ {
+ break;
+ }
+ ipAddrStr++;
+ }
+ }
+
+ if (dotCount == 3)
+ {
+ return CA_STATUS_OK;
+ }
+ return CA_STATUS_FAILED;
}
-CALocalConnectivity_t *CAAdapterCopyLocalEndpoint(CALocalConnectivity_t *connectivity)
+#else // not with_arduino
+/*
+ * These two conversion functions return void because errors can't happen
+ * (because of NI_NUMERIC), and there's nothing to do if they do happen.
+ */
+void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
+ char *host, uint16_t *port)
{
- VERIFY_NON_NULL_RET(connectivity, CA_ADAPTER_UTILS_TAG, "connectivity is NULL", NULL);
+ VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
+ VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
+ VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
- CALocalConnectivity_t *info = (CALocalConnectivity_t *) OICMalloc(
- sizeof(CALocalConnectivity_t));
- if (NULL == info)
+ int r = getnameinfo((struct sockaddr *)sockAddr,
+ sockAddrLen,
+ host, MAX_ADDR_STR_SIZE_CA,
+ NULL, 0,
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if (r)
{
- OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
- return NULL;
+#if defined(EAI_SYSTEM)
+ if (EAI_SYSTEM == r)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getnameinfo failed: errno %s", strerror(errno));
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getnameinfo failed: %s", gai_strerror(r));
+ }
+#elif defined(_WIN32)
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getnameinfo failed: errno %i", WSAGetLastError());
+#else
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getnameinfo failed: %s", gai_strerror(r));
+#endif
+ return;
}
- memset(info, 0, sizeof(CALocalConnectivity_t));
+ *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
+}
+
+void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
+{
+ VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
+ VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
+
+ struct addrinfo *addrs = NULL;
+ struct addrinfo hints = { .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = AI_NUMERICHOST };
- info->type = connectivity->type;
- if (CA_EDR == info->type && strlen(connectivity->addressInfo.BT.btMacAddress))
+ int r = getaddrinfo(host, NULL, &hints, &addrs);
+ if (r)
{
- strncpy(info->addressInfo.BT.btMacAddress, connectivity->addressInfo.BT.btMacAddress,
- CA_MACADDR_SIZE - 1);
- info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ if (NULL != addrs)
+ {
+ freeaddrinfo(addrs);
+ }
+#if defined(EAI_SYSTEM)
+ if (EAI_SYSTEM == r)
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getaddrinfo failed: errno %s", strerror(errno));
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getaddrinfo failed: %s", gai_strerror(r));
+ }
+#elif defined(_WIN32)
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getaddrinfo failed: errno %i", WSAGetLastError());
+#else
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+ "getaddrinfo failed: %s", gai_strerror(r));
+#endif
+ return;
}
- else if (CA_LE == info->type && strlen(connectivity->addressInfo.LE.leMacAddress))
+ // assumption: in this case, getaddrinfo will only return one addrinfo
+ // or first is the one we want.
+ if (addrs[0].ai_family == AF_INET6)
{
- strncpy(info->addressInfo.LE.leMacAddress, connectivity->addressInfo.LE.leMacAddress,
- CA_MACADDR_SIZE - 1);
- info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
+ ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
}
- else if ((CA_WIFI == info->type || CA_ETHERNET == info->type)
- && strlen(connectivity->addressInfo.IP.ipAddress))
+ else
{
- strncpy(info->addressInfo.IP.ipAddress, connectivity->addressInfo.IP.ipAddress,
- CA_IPADDR_SIZE - 1);
- info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
+ memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
+ ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
}
-
- return info;
+ freeaddrinfo(addrs);
}
+#endif // WITH_ARDUINO
-void CAAdapterFreeLocalEndpoint(CALocalConnectivity_t *localEndpoint)
+#ifdef __ANDROID__
+void CANativeJNISetContext(JNIEnv *env, jobject context)
{
- if (localEndpoint)
+ OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
+
+ if (!context)
{
- OICFree(localEndpoint);
+ OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "context is null");
+ return;
}
+
+ if (!g_Context)
+ {
+ g_Context = (*env)->NewGlobalRef(env, context);
+ }
+ else
+ {
+ OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "context is already set");
+ }
+}
+
+void CANativeJNISetJavaVM(JavaVM *jvm)
+{
+ OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
+ g_jvm = jvm;
+}
+
+jobject CANativeJNIGetContext()
+{
+ return g_Context;
}
-CARemoteEndpoint_t *CAAdapterCreateRemoteEndpoint(CAConnectivityType_t type, const char *address,
- const char *resourceUri)
+JavaVM *CANativeJNIGetJavaVM()
{
- CARemoteEndpoint_t *info = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
- if (NULL == info)
+ return g_jvm;
+}
+
+void CANativeSetActivity(JNIEnv *env, jobject activity)
+{
+ OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeSetActivity");
+
+ if (!activity)
{
- OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
- return NULL;
+ OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "activity is null");
+ return;
}
- memset(info, 0, sizeof(CARemoteEndpoint_t));
- info->connectivityType = type;
- if (address && strlen(address))
+ if (!g_Activity)
{
- if (CA_EDR == type)
- {
- strncpy(info->addressInfo.BT.btMacAddress, address, CA_MACADDR_SIZE - 1);
- info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
- }
- else if (CA_LE == info->connectivityType)
- {
- strncpy(info->addressInfo.LE.leMacAddress, address, CA_MACADDR_SIZE - 1);
- info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
- }
- else if (CA_WIFI == type || CA_ETHERNET == type)
- {
- strncpy(info->addressInfo.IP.ipAddress, address, CA_IPADDR_SIZE - 1);
- info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
- }
+ g_Activity = (*env)->NewGlobalRef(env, activity);
}
-
- if (resourceUri && strlen(resourceUri))
+ else
{
- info->resourceUri = OICStrdup(resourceUri);
+ OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "activity is already set");
}
+}
- return info;
+jobject *CANativeGetActivity()
+{
+ return g_Activity;
}
-CARemoteEndpoint_t *CAAdapterCopyRemoteEndpoint(const CARemoteEndpoint_t *remoteEndpoint)
+jmethodID CAGetJNIMethodID(JNIEnv *env, const char* className,
+ const char* methodName,
+ const char* methodFormat)
{
- VERIFY_NON_NULL_RET(remoteEndpoint, CA_ADAPTER_UTILS_TAG, "Remote endpoint is NULL", NULL);
+ VERIFY_NON_NULL_RET(env, CA_ADAPTER_UTILS_TAG, "env", NULL);
+ VERIFY_NON_NULL_RET(className, CA_ADAPTER_UTILS_TAG, "className", NULL);
+ VERIFY_NON_NULL_RET(methodName, CA_ADAPTER_UTILS_TAG, "methodName", NULL);
+ VERIFY_NON_NULL_RET(methodFormat, CA_ADAPTER_UTILS_TAG, "methodFormat", NULL);
- CARemoteEndpoint_t *info = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
- if (NULL == info)
+ jclass jni_cid = (*env)->FindClass(env, className);
+ if (!jni_cid)
{
- OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Memory allocation failed !");
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_cid [%s] is null", className);
+ CACheckJNIException(env);
return NULL;
}
- memset(info, 0, sizeof(CARemoteEndpoint_t));
- info->connectivityType = remoteEndpoint->connectivityType;
- if (CA_EDR == info->connectivityType && strlen(remoteEndpoint->addressInfo.BT.btMacAddress))
+ jmethodID jni_midID = (*env)->GetMethodID(env, jni_cid, methodName, methodFormat);
+ if (!jni_midID)
{
- strncpy(info->addressInfo.BT.btMacAddress, remoteEndpoint->addressInfo.BT.btMacAddress,
- CA_MACADDR_SIZE - 1);
- info->addressInfo.BT.btMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_midID [%s] is null", methodName);
+ CACheckJNIException(env);
+ (*env)->DeleteLocalRef(env, jni_cid);
+ return NULL;
}
- else if (CA_LE == info->connectivityType && strlen(remoteEndpoint->addressInfo.LE.leMacAddress))
+
+ (*env)->DeleteLocalRef(env, jni_cid);
+ return jni_midID;
+}
+
+bool CACheckJNIException(JNIEnv *env)
+{
+ if ((*env)->ExceptionCheck(env))
{
- strncpy(info->addressInfo.LE.leMacAddress, remoteEndpoint->addressInfo.LE.leMacAddress,
- CA_MACADDR_SIZE - 1);
- info->addressInfo.LE.leMacAddress[CA_MACADDR_SIZE - 1] = '\0';
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ return true;
}
- else if ((CA_WIFI == info->connectivityType || CA_ETHERNET == info->connectivityType)
- && strlen(remoteEndpoint->addressInfo.IP.ipAddress))
+ return false;
+}
+
+void CADeleteGlobalReferences(JNIEnv *env)
+{
+ if (g_Context)
{
- strncpy(info->addressInfo.IP.ipAddress, remoteEndpoint->addressInfo.IP.ipAddress,
- CA_IPADDR_SIZE - 1);
- info->addressInfo.IP.ipAddress[CA_IPADDR_SIZE - 1] = '\0';
- info->addressInfo.IP.port = remoteEndpoint->addressInfo.IP.port;
+ (*env)->DeleteGlobalRef(env, g_Context);
+ g_Context = NULL;
}
- if (remoteEndpoint->resourceUri && strlen(remoteEndpoint->resourceUri))
+ if (g_Activity)
{
- info->resourceUri = OICStrdup(remoteEndpoint->resourceUri);
+ (*env)->DeleteGlobalRef(env, g_Activity);
+ g_Activity = NULL;
}
+}
+#endif
- return info;
+#ifndef WITH_ARDUINO
+void CALogAdapterStateInfo(CATransportAdapter_t adapter, CANetworkStatus_t state)
+{
+ OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogAdapterStateInfo");
+ OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+ CALogAdapterTypeInfo(adapter);
+ if (CA_INTERFACE_UP == state)
+ {
+ OIC_LOG(INFO, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_UP");
+ }
+ else
+ {
+ OIC_LOG(INFO, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_DOWN");
+ }
+ OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
}
-void CAAdapterFreeRemoteEndpoint(CARemoteEndpoint_t *remoteEndpoint)
+void CALogSendStateInfo(CATransportAdapter_t adapter,
+ const char *addr, uint16_t port, ssize_t sentLen,
+ bool isSuccess, const char* message)
{
- if (remoteEndpoint)
+ OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogSendStateInfo");
+ OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+
+ if (true == isSuccess)
{
- if (remoteEndpoint->resourceUri)
- {
- OICFree(remoteEndpoint->resourceUri);
- }
+ OIC_LOG_V(INFO, ANALYZER_TAG, "Send Success, sent length = [%d]", sentLen);
+ }
+ else
+ {
+ OIC_LOG_V(INFO, ANALYZER_TAG, "Send Failure, error message = [%s]",
+ message != NULL ? message : "no message");
+ }
+
+ CALogAdapterTypeInfo(adapter);
+ OIC_LOG_V(INFO, ANALYZER_TAG, "Address = [%s]:[%d]", addr, port);
+ OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
- OICFree(remoteEndpoint);
+ // samsung log
+ if (true == isSuccess)
+ {
+ OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "| Analyzer(Retail) | %02x", 1);
+ }
+ else
+ {
+ OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "| Analyzer(Retail) | %02x", 0);
}
}
+void CALogAdapterTypeInfo(CATransportAdapter_t adapter)
+{
+ switch(adapter)
+ {
+ case CA_ADAPTER_IP:
+ OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_IP]");
+ break;
+ case CA_ADAPTER_TCP:
+ OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_TCP]");
+ break;
+ case CA_ADAPTER_GATT_BTLE:
+ OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_GATT_BTLE]");
+ break;
+ case CA_ADAPTER_RFCOMM_BTEDR:
+ OIC_LOG(INFO, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_RFCOMM_BTEDR]");
+ break;
+ default:
+ OIC_LOG_V(INFO, ANALYZER_TAG, "Transport Type = [%d]", adapter);
+ break;
+ }
+}
+#endif