X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_edr_adapter%2Fandroid%2Fcaedrserver.c;h=3d4dcb659eb58d5064251ac31e90d8c90f469e2d;hb=e502658ef0da9a5d4a4cd7465be9ebb3f7e11348;hp=645a2f264098b7c9ef3e1cc343770a16cc56b270;hpb=ec501972e17105287c868a34f452841f2ad1bb2a;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c index 645a2f2..3d4dcb6 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c +++ b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c @@ -1,22 +1,22 @@ -/****************************************************************** -* -* Copyright 2014 Samsung Electronics All Rights Reserved. -* -* -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -******************************************************************/ +/* **************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ #include #include @@ -27,77 +27,72 @@ #include "caedrserver.h" #include "logger.h" #include "oic_malloc.h" -#include "uthreadpool.h" /* for thread pool */ -#include "umutex.h" +#include "cathreadpool.h" /* for thread pool */ +#include "camutex.h" #include "uarraylist.h" #include "caadapterutils.h" +#include "org_iotivity_ca_CaEdrInterface.h" +#include "oic_string.h" -//#define DEBUG_MODE -#define TAG PCF("CA_EDR_SERVER") +#define TAG PCF("OIC_CA_EDR_SERVER") static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;"; -static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;"; static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter"; static const char CLASSPATH_BT_UUID[] = "java/util/UUID"; +static const char CLASSPATH_BT_SERVER_SOCKET[] = "android/bluetooth/BluetoothServerSocket"; -static const uint32_t MAX_PDU_BUFFER = 1024; - -static u_arraylist_t *g_deviceStateList = NULL; -static u_arraylist_t *g_deviceObjectList = NULL; - -static u_thread_pool_t g_threadPoolHandle = NULL; +static ca_thread_pool_t g_threadPoolHandle = NULL; static JavaVM *g_jvm; -static jbyteArray g_sendBuffer; +/** + * Maximum CoAP over TCP header length + * to know the total data length. + */ +#define EDR_MAX_HEADER_LEN 6 /** - * @var g_mMutexSocketListManager - * @brief Mutex to synchronize socket list update + * Mutex to synchronize receive server. */ -static u_mutex g_mutexSocketListManager; +static ca_mutex g_mutexReceiveServer = NULL; -// server socket instance -static jobject g_serverSocketObject = NULL; +/** + * Flag to control the Receive Unicast Data Thread. + */ +static bool g_stopUnicast = false; /** - * @var g_mutexUnicastServer - * @brief Mutex to synchronize unicast server + * Mutex to synchronize accept server. */ -static u_mutex g_mutexUnicastServer = NULL; +static ca_mutex g_mutexAcceptServer = NULL; /** - * @var g_stopUnicast - * @brief Flag to control the Receive Unicast Data Thread + * Flag to control the Accept Thread. */ -static bool g_stopUnicast = false; +static bool g_stopAccept = false; /** - * @var g_mutexMulticastServer - * @brief Mutex to synchronize secure multicast server + * Mutex to synchronize server socket. */ -static u_mutex g_mutexMulticastServer = NULL; +static ca_mutex g_mutexServerSocket = NULL; /** - * @var g_stopMulticast - * @brief Flag to control the Receive Multicast Data Thread + * Flag to control the server socket. */ -static bool g_stopMulticast = false; +static jobject g_serverSocket = NULL; /** - * @var g_stopAccept - * @brief Flag to control the Accept Thread + * Mutex to synchronize device state list. */ -static bool g_stopAccept = false; +static ca_mutex g_mutexStateList = NULL; -typedef struct send_data { - char* address; - char* data; - uint32_t id; -} data_t; +/** + * Mutex to synchronize device object list. + */ +static ca_mutex g_mutexObjectList = NULL; /** - @brief Thread context information for unicast, multicast and secured unicast server + * Thread context information for unicast, multicast and secured unicast server. */ typedef struct { @@ -110,200 +105,266 @@ typedef struct bool *stopFlag; } CAAdapterAcceptThreadContext_t; -// callback instance - /** - * @var g_EDRPacketReceivedCallback - * @brief Maintains the callback to be notified when data received from remote Bluetooth device + * Maintains the callback to be notified when data received from remote + * Bluetooth device. */ -static CAEDRDataReceivedCallback g_EDRPacketReceivedCallback = NULL; +static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL; static void CAReceiveHandler(void *data) { - OIC_LOG_V(DEBUG, TAG, "start CAReceiveHandler.."); - OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler.."); // Input validation VERIFY_NON_NULL_VOID(data, TAG, "Invalid thread context"); - jboolean isAttached = JNI_FALSE; + bool isAttached = false; JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); return; } - isAttached = JNI_TRUE; + isAttached = true; } - CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data; + CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) data; while (true != *(ctx->stopFlag)) { - uint32_t idx; - - // if new socket object is added in socket list after below logic is ran. - // new socket will be started to read after next while loop - uint32_t length = CAEDRServerGetSocketListLength(); - if (0 == length) + if (!CAEDRNativeIsEnableBTAdapter(env)) { - OIC_LOG_V(DEBUG, TAG, "socket list is empty"); + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + break; } - for (idx = 0; idx < length; idx++) + // if new socket object is added in socket list after below logic is ran. + // new socket will be started to read after next while loop + uint32_t length = CAEDRGetSocketListLength(); + if (0 != length) { - OIC_LOG_V(DEBUG, TAG, "start CAEDRNativeReadData"); - CAEDRNativeReadData(env, idx, ctx->type); + for (uint32_t idx = 0; idx < length; idx++) + { + CAEDRNativeReadData(env, idx); + } } - } - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - if(ctx) - OICFree(ctx); + OICFree(ctx); - OIC_LOG(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler"); } static void CAAcceptHandler(void *data) { - if (!data) - { - OIC_LOG(ERROR, TAG, "[EDR] CAAcceptHandler: data is null"); - return; - } - OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread start"); + OIC_LOG(DEBUG, TAG, "AcceptThread start"); + + VERIFY_NON_NULL_VOID(data, TAG, "data is null"); - jboolean isAttached = JNI_FALSE; + bool isAttached = false; JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "CAAcceptHandler - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); return; } - isAttached = JNI_TRUE; + isAttached = true; } - jobject jni_obj_BTSeverSocket = CAEDRNativeListen(env); - if (!jni_obj_BTSeverSocket) + jobject jni_obj_BTServerSocket = CAEDRNativeListen(env); + if (!jni_obj_BTServerSocket) { - OIC_LOG(ERROR, TAG, "[EDR] AcceptThread: jni_obj_BTSeverSocket is null"); + OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null"); - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } return; } - CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *)data; + ca_mutex_lock(g_mutexServerSocket); + g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket); + ca_mutex_unlock(g_mutexServerSocket); + + CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *) data; + + // it should be initialized for restart accept thread + ca_mutex_lock(g_mutexAcceptServer); + g_stopAccept = false; + ca_mutex_unlock(g_mutexAcceptServer); while (true != *(ctx->stopFlag)) { - OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread running"); - CAEDRNativeAccept(env, jni_obj_BTSeverSocket); + // when BT state is changed with Off. its thread will be stopped + if (!CAEDRNativeIsEnableBTAdapter(env)) + { + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + ca_mutex_lock(g_mutexAcceptServer); + g_stopAccept = true; + ca_mutex_unlock(g_mutexAcceptServer); + ca_mutex_lock(g_mutexServerSocket); + g_serverSocket = NULL; + ca_mutex_unlock(g_mutexServerSocket); + } + else + { + CAEDRNativeAccept(env, g_serverSocket); + } } - if(isAttached) + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - if(ctx) - OICFree(ctx); + OICFree(ctx); - OIC_LOG(DEBUG, TAG, "[EDR] AcceptThread finish"); + OIC_LOG(DEBUG, TAG, "AcceptThread finish"); return; } +/** + * implement for adapter common method. + */ +CAResult_t CAEDRServerStart() +{ + if (!g_threadPoolHandle) + { + return CA_STATUS_NOT_INITIALIZED; + } -// adapter common method + CAResult_t res = CAEDRServerStartAcceptThread(); + if (CA_STATUS_OK == res) + { + res = CAEDRStartReceiveThread(false); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "failed to start receive thread"); + CAEDRServerStop(); + return CA_STATUS_FAILED; + } + } -CAResult_t CAEDRServerStart(const char *serviceUUID, int32_t *serverFD, u_thread_pool_t handle) -{ - OIC_LOG_V(DEBUG, TAG, "IN"); - CAEDRServerInitialize(handle); - // FIXME - CAEDRStartUnicastServer(NULL, false); - OIC_LOG_V(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; + return res; } -CAResult_t CAEDRServerStop(int serverFD) +CAResult_t CAEDRServerStop() { - OIC_LOG_V(DEBUG, TAG, "IN"); - CAEDRStopUnicastServer(-1); - CAEDRStopMulticastServer(-1); + CAEDRStopReceiveThread(); + + ca_mutex_lock(g_mutexAcceptServer); + g_stopAccept = true; + ca_mutex_unlock(g_mutexAcceptServer); + + if (!g_jvm) + { + OIC_LOG(DEBUG, TAG, "g_jvm is null"); + return CA_STATUS_FAILED; + } + + bool isAttached = false; + JNIEnv* env; + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) + { + OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer"); + res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - g_stopAccept = TRUE; - g_stopMulticast = TRUE; - g_stopUnicast = TRUE; + if (JNI_OK != res) + { + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_FAILED; + } + isAttached = true; + } + + CAEDRNatvieCloseServerTask(env); + + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } - OIC_LOG_V(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } void CAEDRSetPacketReceivedCallback(CAEDRDataReceivedCallback packetReceivedCallback) { - g_EDRPacketReceivedCallback = packetReceivedCallback; + g_edrPacketReceivedCallback = packetReceivedCallback; } -/** - * Destroy Mutex - */ static void CAEDRServerDestroyMutex() { - OIC_LOG(DEBUG, TAG, "IN"); + if (g_mutexReceiveServer) + { + ca_mutex_free(g_mutexReceiveServer); + g_mutexReceiveServer = NULL; + } - if (g_mutexUnicastServer) + if (g_mutexAcceptServer) { - u_mutex_free(g_mutexUnicastServer); - g_mutexUnicastServer = NULL; + ca_mutex_free(g_mutexAcceptServer); + g_mutexAcceptServer = NULL; } - if (g_mutexMulticastServer) + if (g_mutexServerSocket) { - u_mutex_free(g_mutexMulticastServer); - g_mutexMulticastServer = NULL; + ca_mutex_free(g_mutexServerSocket); + g_mutexServerSocket = NULL; } - if(g_mutexSocketListManager) + if (g_mutexStateList) { - u_mutex_free(g_mutexSocketListManager); - g_mutexSocketListManager = NULL; + ca_mutex_free(g_mutexStateList); + g_mutexStateList = NULL; } - OIC_LOG(DEBUG, TAG, "OUT"); + if (g_mutexObjectList) + { + ca_mutex_free(g_mutexObjectList); + g_mutexObjectList = NULL; + } } - -/* - * Create Mutex - */ static CAResult_t CAEDRServerCreateMutex() { - OIC_LOG(DEBUG, TAG, "IN"); + g_mutexReceiveServer = ca_mutex_new(); + if (!g_mutexReceiveServer) + { + OIC_LOG(ERROR, TAG, "Failed to created mutex!"); + return CA_STATUS_FAILED; + } - g_mutexUnicastServer = u_mutex_new(); - if (!g_mutexUnicastServer) + g_mutexAcceptServer = ca_mutex_new(); + if (!g_mutexAcceptServer) { OIC_LOG(ERROR, TAG, "Failed to created mutex!"); + + CAEDRServerDestroyMutex(); return CA_STATUS_FAILED; } - g_mutexMulticastServer = u_mutex_new(); - if (!g_mutexMulticastServer) + g_mutexServerSocket = ca_mutex_new(); + if (!g_mutexServerSocket) { OIC_LOG(ERROR, TAG, "Failed to created mutex!"); @@ -311,8 +372,17 @@ static CAResult_t CAEDRServerCreateMutex() return CA_STATUS_FAILED; } - g_mutexSocketListManager = u_mutex_new(); - if (!g_mutexSocketListManager) + g_mutexStateList = ca_mutex_new(); + if (!g_mutexStateList) + { + OIC_LOG(ERROR, TAG, "Failed to created mutex!"); + + CAEDRServerDestroyMutex(); + return CA_STATUS_FAILED; + } + + g_mutexObjectList = ca_mutex_new(); + if (!g_mutexObjectList) { OIC_LOG(ERROR, TAG, "Failed to created mutex!"); @@ -320,39 +390,42 @@ static CAResult_t CAEDRServerCreateMutex() return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -void CAEDRServerJniInit(JNIEnv *env, JavaVM* jvm) +void CAEDRServerJniInit() { - OIC_LOG_V(DEBUG, TAG, "CAEDRServerJniInit"); - g_jvm = jvm; + OIC_LOG(DEBUG, TAG, "CAEDRServerJniInit"); + g_jvm = CANativeJNIGetJavaVM(); } -void CAEDRServerInitialize(u_thread_pool_t handle) +CAResult_t CAEDRServerInitialize(ca_thread_pool_t handle) { OIC_LOG(DEBUG, TAG, "CAEDRServerInitialize"); + VERIFY_NON_NULL(handle, TAG, "handle is NULL"); g_threadPoolHandle = handle; + CAEDRServerJniInit(); - // init mutex - CAEDRServerCreateMutex(); + return CAEDRServerCreateMutex(); +} - jboolean isAttached = JNI_FALSE; +CAResult_t CAEDRServerStartAcceptThread() +{ + bool isAttached = false; JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "CAEDRServerInitialize - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); - return; + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); + return CA_STATUS_FAILED; } - isAttached = JNI_TRUE; + isAttached = true; } jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env); @@ -363,29 +436,36 @@ void CAEDRServerInitialize(u_thread_pool_t handle) (*env)->ReleaseStringUTFChars(env, jni_address, localAddress); } - CAEDRServerNativeCreateDeviceStateList(); - CAEDRServerNativeCreateDeviceSocketList(); + ca_mutex_lock(g_mutexStateList); + CAEDRNativeCreateDeviceStateList(); + ca_mutex_unlock(g_mutexStateList); - if(isAttached) + ca_mutex_lock(g_mutexObjectList); + CAEDRNativeCreateDeviceSocketList(); + ca_mutex_unlock(g_mutexObjectList); + + if (isAttached) + { (*g_jvm)->DetachCurrentThread(g_jvm); + } - CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) - OICMalloc(sizeof(CAAdapterReceiveThreadContext_t)); + CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc( + sizeof(CAAdapterReceiveThreadContext_t)); if (!ctx) { OIC_LOG(ERROR, TAG, "Out of memory!"); - return; + return CA_MEMORY_ALLOC_FAILED; } ctx->stopFlag = &g_stopAccept; - if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *)ctx)) + if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *) ctx)) { OIC_LOG(ERROR, TAG, "Failed to create read thread!"); - OICFree((void *)ctx); - return; + OICFree((void *) ctx); + return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } void CAEDRServerTerminate() @@ -396,300 +476,366 @@ void CAEDRServerTerminate() { return; } - jboolean isAttached = JNI_FALSE; + bool isAttached = false; JNIEnv* env; - jint res = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - if(res != JNI_OK) + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "CAEDRServerTerminate - Could not get JNIEnv pointer"); + OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); - if(res != JNI_OK) + if (JNI_OK != res) { - OIC_LOG_V(DEBUG, TAG, "AttachCurrentThread failed"); + OIC_LOG(ERROR, TAG, "AttachCurrentThread failed"); return; } - isAttached = JNI_TRUE; + isAttached = true; } + CAEDRNativeSocketCloseToAll(env); + if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); } - CAEDRServerNativeRemoveAllDeviceState(); - CAEDRServerNativeRemoveAllDeviceSocket(env); + CAEDRNativeRemoveAllDeviceState(); + CAEDRNativeRemoveAllDeviceSocket(env); // delete mutex CAEDRServerDestroyMutex(); } -int32_t CAEDRStartUnicastServer(const char* address, bool isSecured) +CAResult_t CAEDRStartReceiveThread(bool isSecured) { - OIC_LOG_V(DEBUG, TAG, "CAEDRStartUnicastServer(%s)", address); + OIC_LOG(DEBUG, TAG, "CAEDRStartReceiveThread"); - u_mutex_lock(g_mutexUnicastServer); + ca_mutex_lock(g_mutexReceiveServer); /** - * The task to listen for data from unicast is added to the thread pool. - * This is a blocking call is made where we try to receive some data.. - * We will keep waiting until some data is received. - * This task will be terminated when thread pool is freed on stopping the adapters. - * Thread context will be freed by thread on exit. - */ - CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) - OICMalloc(sizeof(CAAdapterReceiveThreadContext_t)); + * The task to listen for data from unicast is added to the thread pool. + * This is a blocking call is made where we try to receive some data.. + * We will keep waiting until some data is received. + * This task will be terminated when thread pool is freed on stopping the adapters. + * Thread context will be freed by thread on exit. + */ + CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc( + sizeof(CAAdapterReceiveThreadContext_t)); if (!ctx) { OIC_LOG(ERROR, TAG, "Out of memory!"); - u_mutex_unlock(g_mutexUnicastServer); + ca_mutex_unlock(g_mutexReceiveServer); return CA_MEMORY_ALLOC_FAILED; } + g_stopUnicast = false; ctx->stopFlag = &g_stopUnicast; ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER; - if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *)ctx)) + if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *) ctx)) { OIC_LOG(ERROR, TAG, "Failed to create read thread!"); - u_mutex_unlock(g_mutexUnicastServer); - OICFree((void *)ctx); + ca_mutex_unlock(g_mutexReceiveServer); + OICFree((void *) ctx); return CA_STATUS_FAILED; } - u_mutex_unlock(g_mutexUnicastServer); + ca_mutex_unlock(g_mutexReceiveServer); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -int32_t CAEDRStartMulticastServer(bool isSecured) +CAResult_t CAEDRStopReceiveThread() { - OIC_LOG_V(DEBUG, TAG, "CAEDRStartMulticastServer"); + OIC_LOG(DEBUG, TAG, "CAEDRStopReceiveThread"); - u_mutex_lock(g_mutexMulticastServer); + ca_mutex_lock(g_mutexReceiveServer); + g_stopUnicast = true; + ca_mutex_unlock(g_mutexReceiveServer); - /** - * The task to listen to data from multicast socket is added to the thread pool. - * This is a blocking call is made where we try to receive some data. - * We will keep waiting until some data is received. - * This task will be terminated when thread pool is freed on stopping the adapters. - * Thread context will be freed by thread on exit. - */ - CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) - OICMalloc(sizeof(CAAdapterReceiveThreadContext_t)); - if (!ctx) - { - OIC_LOG(ERROR, TAG, "Out of memory!"); - u_mutex_unlock(g_mutexMulticastServer); + return CA_STATUS_OK; +} - return CA_MEMORY_ALLOC_FAILED; +CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t idx) +{ + if ((*env)->ExceptionCheck(env)) + { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + OIC_LOG(ERROR, TAG, "env error!!"); + return CA_STATUS_FAILED; } - ctx->stopFlag = &g_stopMulticast; - ctx->type = CA_MULTICAST_SERVER; - - g_stopMulticast = false; - if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *)ctx)) + jobject jni_obj_inputStream = CAEDRNativeGetInputStream(idx); + if (!jni_obj_inputStream) { - OIC_LOG(ERROR, TAG, "thread_pool_add_task failed!"); - - g_stopMulticast = true; - u_mutex_unlock(g_mutexMulticastServer); - OICFree((void *)ctx); - + OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null"); return CA_STATUS_FAILED; } - u_mutex_unlock(g_mutexMulticastServer); - - OIC_LOG(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; -} - -int32_t CAEDRStopUnicastServer(int32_t serverID) -{ - OIC_LOG(DEBUG, TAG, "CAEDRStopUnicastServer"); - - u_mutex_lock(g_mutexUnicastServer); - g_stopUnicast = true; - u_mutex_unlock(g_mutexUnicastServer); - - return 0; -} - -int32_t CAEDRStopMulticastServer(int32_t serverID) -{ - OIC_LOG(DEBUG, TAG, "CAEDRStopMulticastServer"); - - u_mutex_lock(g_mutexMulticastServer); - g_stopMulticast = true; - u_mutex_unlock(g_mutexMulticastServer); - OIC_LOG_V(INFO, TAG, "Multicast server stopped"); + jmethodID jni_mid_available = CAGetJNIMethodID(env, "java/io/InputStream", "available", "()I"); + if (!jni_mid_available) + { + OIC_LOG(ERROR, TAG, "jni_mid_available is null"); + return CA_STATUS_FAILED; + } - return 0; -} + jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available); -CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t type) -{ - if(!((*env)->ExceptionCheck(env))) + if (0 < available) { - // check whether this socket object is connected or not. - jobject jni_obj_socket = CAEDRServerNativeGetDeviceSocket(id); - if(!jni_obj_socket) + jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(idx); + if (!jni_obj_socket) { - return CA_STATUS_INVALID_PARAM; + OIC_LOG(ERROR, TAG, "jni_obj_socket is null"); + return CA_STATUS_FAILED; } jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket); + if (!jni_str_address) + { + OIC_LOG(ERROR, TAG, "jni_str_address is null"); + return CA_STATUS_FAILED; + } + const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL); - if(STATE_DISCONNECTED == CAEDRServerIsConnectedDevice(address)) + if (!address) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: it is not connected yet.."); + OIC_LOG(ERROR, TAG, "address is null"); + (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } - // start to read through InputStream - jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); - jmethodID jni_mid_getInputStream = (*env)->GetMethodID(env, - jni_cid_BTsocket, "getInputStream", "()Ljava/io/InputStream;"); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: get InputStream..%d, %s", id, address); + CAConnectedDeviceInfo_t *deviceInfo = + (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address); + if (!deviceInfo) + { + OIC_LOG(ERROR, TAG, "failed to get device info from list"); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } - if(!jni_obj_socket) + jint bufSize = (deviceInfo->totalDataLen == 0) ? EDR_MAX_HEADER_LEN + : deviceInfo->totalDataLen; + if (!deviceInfo->recvData) { - OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore.."); + deviceInfo->recvData = OICCalloc(1, bufSize); + if (!deviceInfo->recvData) + { + OIC_LOG(ERROR, TAG, "out of memory"); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } + } + + jint remainSize = (jint) bufSize - deviceInfo->recvDataLen; + if (0 >= remainSize) + { + OIC_LOG(ERROR, TAG, "remainSize value is invalid."); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } - jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, - jni_obj_socket, jni_mid_getInputStream); - OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: ready inputStream.."); + jbyteArray jbuf = (*env)->NewByteArray(env, remainSize); + if (!jbuf) + { + OIC_LOG(ERROR, TAG, "jbuf is null"); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } - jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream"); - jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream, "read", "([BII)I"); + jmethodID jni_mid_read = CAGetJNIMethodID(env, "java/io/InputStream", "read", "([BII)I"); + if (!jni_mid_read) + { + OIC_LOG(ERROR, TAG, "jni_mid_read is null"); + (*env)->DeleteLocalRef(env, jbuf); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } - jbyteArray jbuf = (*env)->NewByteArray(env, MAX_PDU_BUFFER); - jlong nread; + OIC_LOG_V(DEBUG, TAG, "read InputStream (idx:%d, addr:%s)", idx, address); + jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read, + jbuf, (jint) 0, remainSize); + if (-1 == recvLen) + { + OIC_LOG(ERROR, TAG, "recvLen is -1"); + (*env)->DeleteLocalRef(env, jbuf); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } + OIC_LOG_V(DEBUG, TAG, "read success (length: %d bytes)", recvLen); - if(!jni_obj_socket) + jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL); + if (!buf) { - OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore..."); + OIC_LOG(ERROR, TAG, "buf is null"); + (*env)->DeleteLocalRef(env, jbuf); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } + memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen); + deviceInfo->recvDataLen += recvLen; + + (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0); + (*env)->DeleteLocalRef(env, jbuf); - while ((nread = (*env)->CallIntMethod(env, jni_obj_inputStream, - jni_mid_read, jbuf, (jint)0, MAX_PDU_BUFFER)) != -1) + if (!deviceInfo->totalDataLen) { - if((*env)->ExceptionCheck(env)) + coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( + ((unsigned char *) deviceInfo->recvData)[0] >> 4); + size_t headerLen = coap_get_tcp_header_length_for_transport(transport); + if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: read Error!!!"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - return CA_STATUS_FAILED; + deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData, + deviceInfo->recvDataLen); + OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen); + + uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen); + if (!newBuf) + { + OIC_LOG(ERROR, TAG, "out of memory"); + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); + return CA_STATUS_FAILED; + } + deviceInfo->recvData = newBuf; } - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: reading"); - jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL); - jint length = strlen((char*)buf); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: read %s", buf); - if (buf == NULL) + } + + if (deviceInfo->totalDataLen == deviceInfo->recvDataLen) + { + if ((*env)->ExceptionCheck(env)) { + OIC_LOG(ERROR, TAG, "read Error!!!"); + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + + // update state to disconnect + // the socket will be close next read thread routine + ca_mutex_lock(g_mutexStateList); + CAEDRUpdateDeviceState(STATE_DISCONNECTED, address); + ca_mutex_unlock(g_mutexStateList); + + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); return CA_STATUS_FAILED; } - switch (type) + if (g_edrPacketReceivedCallback) { - case CA_UNICAST_SERVER: - case CA_MULTICAST_SERVER: - // Notify data to upper layer - if (g_EDRPacketReceivedCallback) - { - uint32_t sentLength = 0; - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] data will be sent \ - to callback routine: %s, %d", buf, length); - g_EDRPacketReceivedCallback(address, (void*)buf, length, &sentLength); - } - break; - - default: - // Should never occur - OIC_LOG_V(DEBUG, TAG, "Invalid server type"); - return CA_STATUS_FAILED; - } - (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0); + OIC_LOG_V(DEBUG, TAG, "data will be sent to callback routine: %s, %d", + deviceInfo->recvData, deviceInfo->recvDataLen); - // close socket after data was sent - CAEDRNativeServerSocketClose(env, address, id); - break; + uint32_t sentLength = 0; + g_edrPacketReceivedCallback(address, (void*) deviceInfo->recvData, + deviceInfo->recvDataLen, &sentLength); + + OICFree(deviceInfo->recvData); + deviceInfo->recvData = NULL; + deviceInfo->recvDataLen = 0; + deviceInfo->totalDataLen = 0; + } } + + (*env)->ReleaseStringUTFChars(env, jni_str_address, address); + (*env)->DeleteLocalRef(env, jni_str_address); } - else + + return CA_STATUS_OK; +} + +void CANativeStartListenTask(JNIEnv *env) +{ + jobject jni_obj_BTServerSocket = CAEDRNativeListen(env); + if (!jni_obj_BTServerSocket) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: env error!!"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null"); + return; } - return CA_STATUS_OK; + ca_mutex_lock(g_mutexServerSocket); + g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket); + ca_mutex_unlock(g_mutexServerSocket); } jobject CAEDRNativeListen(JNIEnv *env) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btListen"); + OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - IN"); + + if (!CAEDRNativeIsEnableBTAdapter(env)) + { + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return NULL; + } - jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER); - if(!jni_cid_BTAdapter) + jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER); + if (!jni_cid_BTAdapter) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_cid_BTAdapter is null"); + OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null"); return NULL; } // get BTadpater - jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, - jni_cid_BTAdapter, "getDefaultAdapter", METHODID_OBJECTNONPARAM); - if(!jni_cid_BTAdapter) + jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, + "getDefaultAdapter", + METHODID_OBJECTNONPARAM); + if (!jni_mid_getDefaultAdapter) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_cid_BTAdapter is null"); + OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); return NULL; } - jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, - jni_cid_BTAdapter, jni_mid_getDefaultAdapter); - if(!jni_obj_BTAdapter) + jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, + jni_mid_getDefaultAdapter); + if (!jni_obj_BTAdapter) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_obj_BTAdapter is null"); + OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); return NULL; } // get listen method ID - jmethodID jni_mid_listen = (*env)->GetMethodID(env, jni_cid_BTAdapter, - "listenUsingInsecureRfcommWithServiceRecord", - "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;"); - if(!jni_mid_listen) + jmethodID jni_mid_listen = (*env)->GetMethodID( + env, jni_cid_BTAdapter, "listenUsingInsecureRfcommWithServiceRecord", + "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;"); + if (!jni_mid_listen) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_listen is null"); + OIC_LOG(ERROR, TAG, "jni_mid_listen is null"); return NULL; } // listenUsingInsecureRfcommWithServiceRecord / listenUsingRfcommWithServiceRecord // setting UUID jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID); - if(!jni_cid_uuid) + if (!jni_cid_uuid) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_listen is null"); + OIC_LOG(ERROR, TAG, "jni_mid_listen is null"); return NULL; } - jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, - "fromString", "(Ljava/lang/String;)Ljava/util/UUID;"); - if(!jni_mid_fromString) + jmethodID jni_mid_fromString = (*env)->GetStaticMethodID( + env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;"); + if (!jni_mid_fromString) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_fromString is null"); + OIC_LOG(ERROR, TAG, "jni_mid_fromString is null"); return NULL; } - jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, - jni_mid_fromString, OIC_EDR_SERVICE_ID); - if(!jni_obj_uuid) + jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID); + if (!jni_uuid) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_obj_uuid is null"); + OIC_LOG(ERROR, TAG, "jni_uuid is null"); + return NULL; + } + jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString, + jni_uuid); + if (!jni_obj_uuid) + { + OIC_LOG(ERROR, TAG, "jni_obj_uuid is null"); return NULL; } @@ -697,565 +843,119 @@ jobject CAEDRNativeListen(JNIEnv *env) jstring jni_name = (*env)->NewStringUTF(env, "BluetoothTestSecure"); if (!jni_name) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_name is null"); + OIC_LOG(ERROR, TAG, "jni_name is null"); return NULL; } - jobject jni_obj_BTSeverSocket = (*env)->CallObjectMethod(env, - jni_obj_BTAdapter, jni_mid_listen, jni_name, jni_obj_uuid); - if(!jni_obj_BTSeverSocket) + jobject jni_obj_BTServerSocket = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_listen, + jni_name, jni_obj_uuid); + if (!jni_obj_BTServerSocket) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_obj_BTSeverSocket is null"); + OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null"); return NULL; } - g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTSeverSocket); + OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT"); - return jni_obj_BTSeverSocket; + return jni_obj_BTServerSocket; } -void CAEDRNativeAccept(JNIEnv *env, jobject severSocketObject) +void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject) { - if(severSocketObject != NULL) - { - jclass jni_cid_BTServerSocket = (*env)->FindClass(env, - "android/bluetooth/BluetoothServerSocket"); - if(!jni_cid_BTServerSocket) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_cid_BTServerSocket is null"); - return; - } + OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - IN"); - jmethodID jni_mid_accept = (*env)->GetMethodID(env, - jni_cid_BTServerSocket, "accept", - "(I)Landroid/bluetooth/BluetoothSocket;"); - if(!jni_mid_accept) + if (NULL != serverSocketObject) + { + jmethodID jni_mid_accept = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET, + "accept", + "()Landroid/bluetooth/BluetoothSocket;"); + if (!jni_mid_accept) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_mid_accept is null"); + OIC_LOG(ERROR, TAG, "jni_mid_accept is null"); return; } - OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: initiating accept..."); + OIC_LOG(DEBUG, TAG, "waiting for the new connection request..."); - jobject jni_obj_BTSocket = NULL; - jni_obj_BTSocket = (*env)->CallObjectMethod(env, severSocketObject, jni_mid_accept, 1000); - if(!jni_obj_BTSocket) + jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, serverSocketObject, + jni_mid_accept); + if (!jni_obj_BTSocket) { - OIC_LOG(ERROR, TAG, "[EDR][Native] btAccept: jni_obj_BTSocket is null"); - return; + OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null"); + + if ((*env)->ExceptionCheck(env)) + { + OIC_LOG(ERROR, TAG, "socket might closed or timeout!!!"); + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + return; + } } // get remote address jstring j_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_BTSocket); - - const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL); - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btAccept: address is %s", address); - - // set socket to list - jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket); - CAEDRServerNativeAddDeviceSocketToList(env, jni_socket); - - OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: Accepted!!"); - - // update state - CAEDRServerUpdateDeviceState(STATE_CONNECTED, address); - (*env)->ReleaseStringUTFChars(env, j_str_address, address); - } - else - { - OIC_LOG(DEBUG, TAG, "[EDR][Native] btAccept: severSocket is close previously"); - } -} - -void CAEDRNativeServerSocketClose(JNIEnv *env, const char *address, uint32_t id) -{ - - jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket"); - if(!jni_cid_BTSocket) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_cid_BTSocket is null"); - return; - } - - jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V"); - if(!jni_mid_close) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_mid_close is null"); - return; - } - - jobject jni_obj_socket = CAEDRServerNativeGetDeviceSocket(id); - if(!jni_obj_socket) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_obj_socket is not available"); - return; - } - - (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close); - - if((*env)->ExceptionCheck(env)) - { - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: close is Failed!!!"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - return; - } - - // remove socket to list - CAEDRServerNativeRemoveDeviceSocket(env, jni_obj_socket); - - // update state - CAEDRServerUpdateDeviceState(STATE_DISCONNECTED, address); - - OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected"); -} - -/** - * BT State List - */ -void CAEDRServerNativeCreateDeviceStateList() -{ - OIC_LOG(DEBUG, TAG, "[EDR][Native] CAEDRNativeCreateDeviceStateList"); - - // create new object array - if (g_deviceStateList == NULL) - { - OIC_LOG_V(DEBUG, TAG, "Create device list"); - - g_deviceStateList = u_arraylist_create(); - if (g_deviceStateList == NULL) - { - OIC_LOG_V(DEBUG, TAG, "Create device list is null"); - } - } -} - -void CAEDRServerUpdateDeviceState(uint32_t state, const char *address) -{ - state_t *newstate = (state_t*) OICCalloc(1, sizeof(state_t)); - if (!newstate) { - OIC_LOG(ERROR, TAG, "[BLE][Native] newstate is null"); - return; - } - strcpy(newstate->address, address); - newstate->state = state; - - CAEDRServerNativeAddDeviceStateToList(newstate); -} - -void CAEDRServerNativeAddDeviceStateToList(state_t *state) -{ - if(!state) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] device is null"); - return; - } - - if(!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] gdevice_list is null"); - return; - } - - if(!CAEDRServerNativeIsDeviceInList(state->address)) { - CAEDRServerNativeRemoveDevice(state->address); // delete previous state for update new state - u_arraylist_add(g_deviceStateList, state); // update new state - OIC_LOG_V(DEBUG, TAG, "Set State to Connected State List"); - } -} - -jboolean CAEDRServerNativeIsDeviceInList(const char* remoteAddress){ - - if (!remoteAddress) { - OIC_LOG(ERROR, TAG, "[BLE][Native] remoteAddress is null"); - return JNI_TRUE; - } - jint index; - for (index = 0; index < u_arraylist_length(g_deviceStateList); index++) - { - state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); - if(!state) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] state_t object is null"); - return JNI_TRUE; - } - - if(!strcmp(remoteAddress, state->address)) - { - OIC_LOG_V(DEBUG, TAG, "the device is already set"); - return JNI_TRUE; - } - else + if (!j_str_address) { - continue; - } - } - - OIC_LOG_V(DEBUG, TAG, "there are no the device in list."); - return JNI_FALSE; -} - -void CAEDRServerNativeRemoveAllDeviceState() -{ - OIC_LOG_V(DEBUG, TAG, "CAEDRNativeRemoveAllDevices"); - - if(!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null"); - return; - } - - jint index; - for (index = 0; index < u_arraylist_length(g_deviceStateList); index++) - { - state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); - if(!state) - { - OIC_LOG(DEBUG, TAG, "[EDR][Native] jarrayObj is null"); - continue; - } - OICFree(state); - } - - OICFree(g_deviceStateList); - g_deviceStateList = NULL; - return; -} - -void CAEDRServerNativeRemoveDevice(const char *remoteAddress) -{ - OIC_LOG_V(DEBUG, TAG, "CAEDRNativeRemoveDevice"); - - if(!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null"); - return; - } - if (!remoteAddress) { - OIC_LOG(ERROR, TAG, "[BLE][Native] remoteAddress is null"); - return; - } - - jint index; - for (index = 0; index < u_arraylist_length(g_deviceStateList); index++) - { - state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); - if(!state) - { - OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null"); - continue; + OIC_LOG(ERROR, TAG, "j_str_address is null"); + return; } - if(!strcmp(state->address, remoteAddress)) - { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove object : %s", remoteAddress); - OICFree(state); + const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL); - CAEDRServerReorderingDeviceList(index); - break; - } - } - OIC_LOG(DEBUG, TAG, "[EDR][Native] there are no target object"); - return; -} + OIC_LOG_V(INFO, TAG, "accept a new connection from [%s]", address); -jboolean CAEDRServerIsConnectedDevice(const char *remoteAddress) -{ - OIC_LOG_V(DEBUG, TAG, "CAEDRServerIsConnectedDevice"); + // update state + ca_mutex_lock(g_mutexStateList); + CAEDRUpdateDeviceState(STATE_CONNECTED, address); + ca_mutex_unlock(g_mutexStateList); - if(!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null"); - return JNI_FALSE; - } - if (!remoteAddress) { - OIC_LOG(ERROR, TAG, "[BLE][Native] remoteAddress is null"); - return JNI_FALSE; - } + (*env)->ReleaseStringUTFChars(env, j_str_address, address); + (*env)->DeleteLocalRef(env, j_str_address); - jint index; - for (index = 0; index < u_arraylist_length(g_deviceStateList); index++) - { - state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); - if(!state) + // set socket to list + jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket); + if (!jni_socket) { - OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null"); - continue; + OIC_LOG(ERROR, TAG, "jni_socket is null"); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); + return; } - if(!strcmp(state->address, remoteAddress)) - { - OIC_LOG_V(DEBUG, TAG, "[EDR][Native] check whether it is connected or not"); - - return state->state; - } - } - OIC_LOG(DEBUG, TAG, "[EDR][Native] there are no target object"); - return JNI_FALSE; -} + ca_mutex_lock(g_mutexObjectList); + CAEDRNativeAddDeviceSocketToList(env, jni_socket); + ca_mutex_unlock(g_mutexObjectList); -void CAEDRServerReorderingDeviceList(uint32_t index) -{ - if (index >= g_deviceStateList->length) - { - return; + (*env)->DeleteGlobalRef(env, jni_socket); + (*env)->DeleteLocalRef(env, jni_obj_BTSocket); } - - if (index < g_deviceStateList->length - 1) + else { - memmove(&g_deviceStateList->data[index], &g_deviceStateList->data[index + 1], - (g_deviceStateList->length - index - 1) * sizeof(void *)); + OIC_LOG(DEBUG, TAG, "serverSocket is close previously"); } - g_deviceStateList->size--; - g_deviceStateList->length--; + OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - OUT"); } /** - * Device Socket Object List + * InputStream & BluetoothServerSocket will be close for Terminating. */ -void CAEDRServerNativeCreateDeviceSocketList() +void CAEDRNatvieCloseServerTask(JNIEnv* env) { - OIC_LOG(DEBUG, TAG, "[BLE][Native] CAEDRServerNativeCreateDeviceSocketList"); - - // create new object array - if (g_deviceObjectList == NULL) + if (g_serverSocket) { - OIC_LOG_V(DEBUG, TAG, "Create Device object list"); + OIC_LOG(DEBUG, TAG, "Accept Resource will be close"); - g_deviceObjectList = u_arraylist_create(); - if (g_deviceObjectList == NULL) + jmethodID jni_mid_close = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET, + "close", "()V"); + if (!jni_mid_close) { - OIC_LOG_V(DEBUG, TAG, "Create Device object list is null"); - } - } -} - -void CAEDRServerNativeAddDeviceSocketToList(JNIEnv *env, jobject deviceSocket) -{ - OIC_LOG(DEBUG, TAG, "[BLE][Native] CAEDRServerNativeAddDeviceSocketToList"); - - if(!deviceSocket) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] Device is null"); - return; - } - - if(!g_deviceObjectList) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null"); - return; - } - - jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket); - if(!jni_remoteAddress) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] jni_remoteAddress is null"); - return; - } - - u_mutex_lock(g_mutexSocketListManager); - - const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL); - - if(!CAEDRServerNativeIsDeviceSocketInList(env, remoteAddress)) - { - jobject gDeviceSocket = (*env)->NewGlobalRef(env, deviceSocket); - u_arraylist_add(g_deviceObjectList, gDeviceSocket); - OIC_LOG_V(DEBUG, TAG, "Set Object to Array as Element"); - } - - (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); - u_mutex_unlock(g_mutexSocketListManager); -} - -jboolean CAEDRServerNativeIsDeviceSocketInList(JNIEnv *env, const char* remoteAddress) -{ - OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeIsDeviceObjInList"); - - jint index; - for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++) - { - - jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index); - if(!jarrayObj) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null"); - return JNI_TRUE; - } - - jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj); - if(!jni_setAddress) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null"); - return JNI_TRUE; - } - - const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL); - if (!setAddress || !remoteAddress) { - OIC_LOG(ERROR, TAG, "[BLE][Native] setAddress or remoteAddress is null"); - return JNI_TRUE; - } - if(!strcmp(remoteAddress, setAddress)) - { - OIC_LOG_V(DEBUG, TAG, "the device is already set"); - return JNI_TRUE; - } - else - { - continue; - } - } - - OIC_LOG_V(DEBUG, TAG, "there are no the Device obejct in list. we can add"); - return JNI_FALSE; -} - -void CAEDRServerNativeRemoveAllDeviceSocket(JNIEnv *env) -{ - OIC_LOG_V(DEBUG, TAG, "CANativeRemoveAllDeviceObjsList"); - - if(!g_deviceObjectList) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null"); - return; - } - - jint index; - for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++) - { - jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index); - if(!jarrayObj) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null"); + OIC_LOG(ERROR, TAG, "jni_mid_close is null"); return; } - (*env)->DeleteGlobalRef(env, jarrayObj); - } - OICFree(g_deviceObjectList); - g_deviceObjectList = NULL; - return; -} + (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_close); + (*env)->DeleteGlobalRef(env, g_serverSocket); + g_serverSocket = NULL; -void CAEDRServerNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket) -{ - OIC_LOG_V(DEBUG, TAG, "CAEDRServerNativeRemoveDeviceSocket"); - - if(!g_deviceObjectList) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null"); - return; + OIC_LOG(DEBUG, TAG, "close accept obj"); } - - u_mutex_lock(g_mutexSocketListManager); - - jint index; - for (index = 0; index < u_arraylist_length(g_deviceObjectList); index++) - { - jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index); - if(!jarrayObj) - { - OIC_LOG(DEBUG, TAG, "[BLE][Native] jarrayObj is null"); - continue; - } - - jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj); - if(!jni_setAddress) - { - OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_setAddress is null"); - continue; - } - const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL); - (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - - jstring jni_remoteAddress = CAEDRNativeGetAddressFromDeviceSocket(env, deviceSocket); - if(!jni_remoteAddress) - { - OIC_LOG(DEBUG, TAG, "[BLE][Native] jni_remoteAddress is null"); - continue; - } - const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL); - (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); - - if (!setAddress || !remoteAddress) { - OIC_LOG(DEBUG, TAG, "[BLE][Native] setAddress or remoteAddress is null"); - continue; - } - if(!strcmp(setAddress, remoteAddress)) - { - OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress); - (*env)->DeleteGlobalRef(env, jarrayObj); - - CAEDRServerReorderingDeviceSocketList(index); - break; - } - } - u_mutex_unlock(g_mutexSocketListManager); - - OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object"); - return; -} - -jobject CAEDRServerNativeGetDeviceSocket(uint32_t idx) -{ - OIC_LOG_V(DEBUG, TAG, "CAEDRServerNativeGetDeviceSocket"); - - if(idx < 0) - { - OIC_LOG(DEBUG, TAG, "[BLE][Native] index is not available"); - return NULL; - } - - if(!g_deviceObjectList) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null"); - return NULL; - } - - jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, idx); - if(!jarrayObj) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is not available"); - return NULL; - } - return jarrayObj; } - -uint32_t CAEDRServerGetSocketListLength() -{ - if(!g_deviceObjectList) - { - OIC_LOG(ERROR, TAG, "[BLE][Native] gdeviceObjectList is null"); - return 0; - } - - uint32_t length = u_arraylist_length(g_deviceObjectList); - - return length; -} - -void CAEDRServerReorderingDeviceSocketList(uint32_t index) -{ - if (index >= g_deviceObjectList->length) - { - return; - } - - if (index < g_deviceObjectList->length - 1) - { - memmove(&g_deviceObjectList->data[index], &g_deviceObjectList->data[index + 1], - (g_deviceObjectList->length - index - 1) * sizeof(void *)); - } - - g_deviceObjectList->size--; - g_deviceObjectList->length--; -} - -void CAEDRServerSetPacketReceivedCallback - (CAEDRDataReceivedCallback packetReceivedCallback) -{ - g_EDRPacketReceivedCallback = packetReceivedCallback; -} - - -