Redefinition of Macro removed
[platform/upstream/iotivity.git] / resource / csdk / connectivity / samples / android / casample / sampleService / src / main / jni / ResourceModel.c
index 9f89c26..56f1ba6 100644 (file)
@@ -4,9 +4,12 @@
 #include <dlfcn.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "cainterface.h"
 #include "cacommon.h"
+#include "caadapterutils.h"
+#include "oic_string.h"
 
 #include "org_iotivity_ca_service_RMInterface.h"
 
 #define  LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
 #define  LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
 
-/**
- * @def RS_IDENTITY
- * @brief
- */
-#define IDENTITY     ("1111111111111111")
-/* @def RS_CLIENT_PSK
- * @brief
- */
-#define RS_CLIENT_PSK   ("AAAAAAAAAAAAAAAA")
+// Iotivity Device Identity.
+const unsigned char IDENTITY[] = ("1111111111111111");
+
+// PSK between this device and peer device.
+const unsigned char RS_CLIENT_PSK[] = ("AAAAAAAAAAAAAAAA");
 
 #define PORT_LENGTH 5
 #define SECURE_DEFAULT_PORT 5684
 #define RESOURCE_URI_LENGTH 14
 #define OPTION_INFO_LENGTH 1024
 #define NETWORK_INFO_LENGTH 1024
+#define BIG_PAYLOAD_LENGTH 1024
+#define RECEIVED_FILE_NAME_PREFIX_LENGTH 7
+#define RECEIVED_FILE_NAME_LENGTH 14
 
 typedef struct
 {
@@ -36,15 +38,20 @@ typedef struct
     uint16_t port;
 } addressSet_t;
 
-void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestInfo);
-void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo);
-void error_handler(const CAEndpoint_t *object, const CAErrorInfo_t* errorInfo);
-void get_resource_uri(const char *URI, char *resourceURI, uint32_t length);
-uint32_t get_secure_information(CAPayload_t payLoad);
-CAResult_t get_network_type(uint32_t selectedNetwork);
-void callback(char *subject, char *receivedData);
-CAResult_t get_remote_address(CATransportAdapter_t transportType, const char *address);
-void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t *flags);
+static void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestInfo);
+static void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo);
+static void error_handler(const CAEndpoint_t *object, const CAErrorInfo_t* errorInfo);
+static void get_resource_uri(const char *URI, char *resourceURI, int32_t length);
+static uint32_t get_secure_information(CAPayload_t payLoad);
+static CAResult_t get_network_type(uint32_t selectedNetwork, CATransportFlags_t *flags);
+static void callback(char *subject, char *receivedData);
+static CAResult_t get_remote_address(const char *address);
+static void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t *flags);
+static void delete_global_references(JNIEnv *env, jobject obj);
+static int get_address_set(const char *pAddress, addressSet_t* outAddress);
+bool read_file(const char* name, char** bytes, size_t* length);
+uint32_t gettodaydate();
+void saveFile(const char *payload, size_t payloadSize);
 
 uint16_t g_localSecurePort = SECURE_DEFAULT_PORT;
 CATransportAdapter_t g_selectedNwType = CA_ADAPTER_IP;
@@ -53,8 +60,13 @@ static uint8_t g_lastRequestTokenLength = 0;
 
 static const char COAP_PREFIX[] =  "coap://";
 static const char COAPS_PREFIX[] = "coaps://";
+static const char COAP_TCP_PREFIX[] =  "coap+tcp://";
+
 static const uint16_t COAP_PREFIX_LEN = sizeof(COAP_PREFIX) - 1;
 static const uint16_t COAPS_PREFIX_LEN = sizeof(COAPS_PREFIX) - 1;
+static const uint16_t COAP_TCP_PREFIX_LEN = sizeof(COAP_TCP_PREFIX) - 1;
+
+static const char RECEIVED_FILE_PATH[] = "/storage/emulated/0/Download/%d%s.txt";
 
 static const char SECURE_INFO_DATA[]
                                    = "{\"oc\":[{\"href\":\"%s\",\"prop\":{\"rt\":[\"core.led\"],"
@@ -81,89 +93,77 @@ Java_org_iotivity_ca_service_RMInterface_setNativeResponseListener(JNIEnv *env,
                                                                    jobject listener)
 {
     LOGI("setNativeResponseListener");
-    g_responseListenerObject = (*env)->NewGlobalRef(env, obj);
-}
-
-#ifdef __WITH_DTLS__
-static CADtlsPskCredsBlob_t *pskCredsBlob = NULL;
-
-void clearDtlsCredentialInfo()
-{
-    LOGI("clearDtlsCredentialInfo IN");
-    if (pskCredsBlob)
+    if (!env || !obj || !listener)
     {
-        // Initialize sensitive data to zeroes before freeing.
-        if (NULL != pskCredsBlob->creds)
-        {
-            memset(pskCredsBlob->creds, 0, sizeof(OCDtlsPskCreds)*(pskCredsBlob->num));
-            free(pskCredsBlob->creds);
-        }
-
-        memset(pskCredsBlob, 0, sizeof(CADtlsPskCredsBlob_t));
-        free(pskCredsBlob);
-        pskCredsBlob = NULL;
+        LOGI("Invalid input parameter");
+        return;
     }
-    LOGI("clearDtlsCredentialInfo OUT");
+
+    g_responseListenerObject = (*env)->NewGlobalRef(env, listener);
 }
 
+#ifdef __WITH_DTLS__
 // Internal API. Invoked by OC stack to retrieve credentials from this module
-void CAGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
+int32_t CAGetDtlsPskCredentials( CADtlsPskCredType_t type,
+              const unsigned char *desc, size_t desc_len,
+              unsigned char *result, size_t result_length)
 {
     LOGI("CAGetDtlsPskCredentials IN");
-    *credInfo = (CADtlsPskCredsBlob_t *) malloc(sizeof(CADtlsPskCredsBlob_t));
-    if (NULL == *credInfo)
+
+    int32_t ret = -1;
+
+    if (NULL == result)
     {
-        LOGE("Failed to allocate credential blob.");
-        return;
+        return ret;
     }
 
-    int16_t credLen = sizeof(OCDtlsPskCreds) * (pskCredsBlob->num);
-    (*credInfo)->creds = (OCDtlsPskCreds *) malloc(credLen);
-    if (NULL == (*credInfo)->creds)
+    switch (type)
     {
-        LOGE("Failed to allocate crentials.");
-        free(*credInfo);
-        *credInfo = NULL;
-        return;
-    }
+        case CA_DTLS_PSK_HINT:
+        case CA_DTLS_PSK_IDENTITY:
 
-    memcpy((*credInfo)->identity, pskCredsBlob->identity, DTLS_PSK_ID_LEN);
-    (*credInfo)->num = pskCredsBlob->num;
-    memcpy((*credInfo)->creds, pskCredsBlob->creds, credLen);
+            if (result_length < sizeof(IDENTITY))
+            {
+                LOGE("ERROR : Wrong value for result for storing IDENTITY");
+                return ret;
+            }
 
-    LOGI("CAGetDtlsPskCredentials OUT");
-}
+            memcpy(result, IDENTITY, sizeof(IDENTITY));
+            ret = sizeof(IDENTITY);
+            break;
 
-CAResult_t SetCredentials()
-{
-    LOGI("SetCredentials IN");
-    pskCredsBlob = (CADtlsPskCredsBlob_t *)malloc(sizeof(CADtlsPskCredsBlob_t));
-    if (NULL == pskCredsBlob)
-    {
-        LOGE("Memory allocation failed!");
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-    memcpy(pskCredsBlob->identity, IDENTITY, DTLS_PSK_ID_LEN);
+        case CA_DTLS_PSK_KEY:
 
-    pskCredsBlob->num = 1;
+            if ((desc_len == sizeof(IDENTITY)) &&
+                memcmp(desc, IDENTITY, sizeof(IDENTITY)) == 0)
+            {
+                if (result_length < sizeof(RS_CLIENT_PSK))
+                {
+                    LOGE("ERROR : Wrong value for result for storing RS_CLIENT_PSK");
+                    return ret;
+                }
 
-    pskCredsBlob->creds = (OCDtlsPskCreds *)malloc(sizeof(OCDtlsPskCreds) *(pskCredsBlob->num));
-    if (NULL == pskCredsBlob->creds)
-    {
-        LOGE("Memory allocation failed!");
-        return CA_MEMORY_ALLOC_FAILED;
+                memcpy(result, RS_CLIENT_PSK, sizeof(RS_CLIENT_PSK));
+                ret = sizeof(RS_CLIENT_PSK);
+            }
+            break;
+
+        default:
+
+            LOGE("Wrong value passed for PSK_CRED_TYPE.");
+            ret = -1;
     }
-    memcpy(pskCredsBlob->creds[0].id, IDENTITY, DTLS_PSK_ID_LEN);
-    memcpy(pskCredsBlob->creds[0].psk, RS_CLIENT_PSK, DTLS_PSK_PSK_LEN);
 
-    LOGI("SetCredentials OUT");
-    return CA_STATUS_OK;
+    LOGI("CAGetDtlsPskCredentials OUT\n");
+    return ret;
 }
+
 #endif
 
 JNIEXPORT jint JNI_OnLoad(JavaVM *jvm, void *reserved)
 {
     LOGI("JNI_OnLoad");
+    (void)reserved;
 
     JNIEnv* env;
     if (JNI_OK != (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6))
@@ -180,6 +180,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *jvm, void *reserved)
 void JNI_OnUnload(JavaVM *jvm, void *reserved)
 {
     LOGI("JNI_OnUnload");
+    (void)reserved;
 
     JNIEnv* env;
     if (JNI_OK != (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6))
@@ -191,12 +192,19 @@ void JNI_OnUnload(JavaVM *jvm, void *reserved)
 }
 
 JNIEXPORT void JNICALL
-Java_org_iotivity_ca_service_RMInterface_RMInitialize(JNIEnv *env, jobject obj, jobject context)
+Java_org_iotivity_ca_service_RMInterface_RMInitialize(JNIEnv *env, jobject obj, jobject context,
+                                                      jobject activity)
 {
     LOGI("RMInitialize");
+    if (!env || !obj || !context || !activity)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     //Currently set context for Android Platform
     CANativeJNISetContext(env, context);
+    CANativeSetActivity(env, activity);
 
     CAResult_t res = CAInitialize();
 
@@ -206,12 +214,6 @@ Java_org_iotivity_ca_service_RMInterface_RMInitialize(JNIEnv *env, jobject obj,
     }
 
 #ifdef __WITH_DTLS__
-    if (CA_STATUS_OK != SetCredentials())
-    {
-        LOGE("SetCredentials failed");
-        return;
-    }
-
     res = CARegisterDTLSCredentialsHandler(CAGetDtlsPskCredentials);
     if(CA_STATUS_OK != res)
     {
@@ -225,14 +227,26 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMTerminate(JNIEnv *env, jobject obj)
 {
     LOGI("RMTerminate");
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
+
     CADestroyToken(g_lastRequestToken);
     CATerminate();
+    delete_global_references(env, obj);
 }
 
 JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMStartListeningServer(JNIEnv *env, jobject obj)
 {
     LOGI("RMStartListeningServer");
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     if (CA_STATUS_OK != CAStartListeningServer())
     {
@@ -244,6 +258,11 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMStartDiscoveryServer(JNIEnv *env, jobject obj)
 {
     LOGI("RMStartDiscoveryServer");
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     if (CA_STATUS_OK != CAStartDiscoveryServer())
     {
@@ -255,6 +274,11 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMRegisterHandler(JNIEnv *env, jobject obj)
 {
     LOGI("RMRegisterHandler");
+    if(!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     CARegisterHandler(request_handler, response_handler, error_handler);
 }
@@ -262,10 +286,24 @@ Java_org_iotivity_ca_service_RMInterface_RMRegisterHandler(JNIEnv *env, jobject
 JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj, jstring uri,
                                                        jstring payload, jint selectedNetwork,
-                                                       jint isSecured, jint msgType)
+                                                       jint isSecured, jint msgType,
+                                                       jboolean isBigData)
 {
     LOGI("selectedNetwork - %d", selectedNetwork);
-    CAResult_t res = get_network_type(selectedNetwork);
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
+
+    if (!uri)
+    {
+        LOGE("Invalid input parameter : uri");
+        return;
+    }
+
+    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+    CAResult_t res = get_network_type(selectedNetwork, &flags);
     if (CA_STATUS_OK != res)
     {
         return;
@@ -274,13 +312,12 @@ Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj,
     const char* strUri = (*env)->GetStringUTFChars(env, uri, NULL);
     LOGI("RMSendRequest - %s", strUri);
 
-    CATransportFlags_t flags;
-    addressSet_t address = {};
+    addressSet_t address = {{0}, 0};
     parsing_coap_uri(strUri, &address, &flags);
 
     //create remote endpoint
     CAEndpoint_t* endpoint = NULL;
-    res = CACreateEndpoint(flags, g_selectedNwType, (const char*)address.ipAddress,
+    res = CACreateEndpoint(flags, g_selectedNwType, (const char*)(address.ipAddress),
                            address.port, &endpoint);
     if (CA_STATUS_OK != res)
     {
@@ -314,37 +351,77 @@ Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj,
     requestData.token = token;
     requestData.tokenLength = tokenLength;
 
-    if (1 == isSecured)
+    size_t payloadLength = 0;
+    if (isBigData)
     {
-        uint32_t length = sizeof(SECURE_INFO_DATA) + strlen(resourceURI);
-        requestData.payload = (CAPayload_t) malloc(length);
-        if (NULL == requestData.payload)
+        const char* path = NULL;
+        if (payload)
         {
-            LOGE("Memory allocation failed!");
-            // destroy token
-            CADestroyToken(token);
-            // destroy remote endpoint
-            CADestroyEndpoint(endpoint);
-            return;
+            path = (*env)->GetStringUTFChars(env, payload, NULL);
+            if(path)
+            {
+                char* bigData = NULL;
+                bool result = read_file(path, &bigData, &payloadLength);
+                if (!result)
+                {
+                    LOGE("read has failed");
+                    (*env)->ReleaseStringUTFChars(env, payload, path);
+                    CADestroyToken(token);
+                    CADestroyEndpoint(endpoint);
+                    return;
+                }
+                (*env)->ReleaseStringUTFChars(env, payload, path);
+
+                requestData.payload = (CAPayload_t) malloc(payloadLength);
+                if (NULL == requestData.payload)
+                {
+                    LOGE("Memory allocation failed!");
+                    // destroy token
+                    CADestroyToken(token);
+                    // destroy remote endpoint
+                    CADestroyEndpoint(endpoint);
+                    return;
+                }
+                memcpy(requestData.payload, bigData, payloadLength);
+                requestData.payloadSize = payloadLength;
+            }
         }
-        snprintf(requestData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
-        requestData.payloadSize = length;
     }
     else
     {
-        uint32_t length = sizeof(NORMAL_INFO_DATA) + strlen(resourceURI);
-        requestData.payload = (CAPayload_t) malloc(length);
-        if (NULL == requestData.payload)
+        if (isSecured)
         {
-            LOGE("Memory allocation failed!");
-            // destroy token
-            CADestroyToken(token);
-            // destroy remote endpoint
-            CADestroyEndpoint(endpoint);
-            return;
+            payloadLength = sizeof(SECURE_INFO_DATA) + strlen(resourceURI);
+            requestData.payload = (CAPayload_t) malloc(payloadLength);
+            if (NULL == requestData.payload)
+            {
+                LOGE("Memory allocation failed!");
+                // destroy token
+                CADestroyToken(token);
+                // destroy remote endpoint
+                CADestroyEndpoint(endpoint);
+                return;
+            }
+            snprintf((char *) requestData.payload, payloadLength, SECURE_INFO_DATA,
+                     resourceURI, g_localSecurePort);
+            requestData.payloadSize = payloadLength;
+        }
+        else
+        {
+            payloadLength = sizeof(NORMAL_INFO_DATA) + strlen(resourceURI);
+            requestData.payload = (CAPayload_t) malloc(payloadLength);
+            if (NULL == requestData.payload)
+            {
+                LOGE("Memory allocation failed!");
+                // destroy token
+                CADestroyToken(token);
+                // destroy remote endpoint
+                CADestroyEndpoint(endpoint);
+                return;
+            }
+            snprintf((char *) requestData.payload, payloadLength, NORMAL_INFO_DATA, resourceURI);
+            requestData.payloadSize = payloadLength;
         }
-        snprintf(requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
-        requestData.payloadSize = length;
     }
 
     requestData.type = messageType;
@@ -380,6 +457,7 @@ Java_org_iotivity_ca_service_RMInterface_RMSendRequest(JNIEnv *env, jobject obj,
 
     free(requestData.payload);
     free(requestData.resourceUri);
+    LOGI("send request success");
 }
 
 JNIEXPORT void JNICALL
@@ -387,15 +465,23 @@ Java_org_iotivity_ca_service_RMInterface_RMSendReqestToAll(JNIEnv *env, jobject
                                                            jint selectedNetwork)
 {
     LOGI("selectedNetwork - %d", selectedNetwork);
-    CAResult_t res = get_network_type(selectedNetwork);
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
+
+    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+    CAResult_t res = get_network_type(selectedNetwork, &flags);
     if (CA_STATUS_OK != res)
     {
+        LOGE("Not supported network type");
         return;
     }
 
     // create remote endpoint
     CAEndpoint_t *endpoint = NULL;
-    res = CACreateEndpoint(CA_IPV4, g_selectedNwType, NULL, 0, &endpoint);
+    res = CACreateEndpoint(flags, g_selectedNwType, NULL, 0, &endpoint);
 
     if (CA_STATUS_OK != res)
     {
@@ -489,10 +575,16 @@ Java_org_iotivity_ca_service_RMInterface_RMSendResponse(JNIEnv *env, jobject obj
                                                         jint responseValue)
 {
     LOGI("RMSendResponse");
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     LOGI("selectedNetwork - %d", selectedNetwork);
 
-    CAResult_t res = get_network_type(selectedNetwork);
+    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+    CAResult_t res = get_network_type(selectedNetwork, &flags);
     if (CA_STATUS_OK != res)
     {
         LOGE("Not supported network type");
@@ -514,7 +606,13 @@ Java_org_iotivity_ca_service_RMInterface_RMSendResponse(JNIEnv *env, jobject obj
 
     CAResponseInfo_t responseInfo = { 0 };
 
-    if (msgType != CA_MSG_RESET)
+    if (CA_MSG_RESET == msgType ||
+        (CA_MSG_ACKNOWLEDGE == msgType && CA_EMPTY == responseValue))
+    {
+        printf("RESET or ACK/EMPTY. there will be not payload/option\n");
+        responseInfo.result = CA_EMPTY;
+    }
+    else
     {
         responseData.token = g_clientToken;
         responseData.tokenLength = g_clientTokenLength;
@@ -524,23 +622,18 @@ Java_org_iotivity_ca_service_RMInterface_RMSendResponse(JNIEnv *env, jobject obj
         {
             uint32_t length = strlen(SECURE_INFO_DATA) + strlen(g_resourceUri) + 1;
             responseData.payload = (CAPayload_t) malloc(length);
-            sprintf(responseData.payload, SECURE_INFO_DATA, g_resourceUri,
-                    g_localSecurePort);
+            snprintf((char *) responseData.payload, length, SECURE_INFO_DATA,
+                     g_resourceUri, g_localSecurePort);
             responseData.payloadSize = length;
         }
         else
         {
             uint32_t length = strlen(NORMAL_INFO_DATA) + strlen(g_resourceUri) + 1;
             responseData.payload = (CAPayload_t) malloc(length);
-            sprintf(responseData.payload, NORMAL_INFO_DATA, g_resourceUri);
+            snprintf((char *) responseData.payload, length, NORMAL_INFO_DATA, g_resourceUri);
             responseData.payloadSize = length;
         }
     }
-    //msgType is RESET
-    else
-    {
-        responseInfo.result = CA_EMPTY;
-    }
 
     responseInfo.info = responseData;
 
@@ -559,17 +652,34 @@ Java_org_iotivity_ca_service_RMInterface_RMSendResponse(JNIEnv *env, jobject obj
     // destroy remote endpoint
     CADestroyEndpoint(g_clientEndpoint);
     g_clientEndpoint = NULL;
+    free(responseData.payload);
 }
 
 JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject obj, jstring uri,
                                                             jstring payload, jint selectedNetwork,
-                                                            jint isSecured, jint msgType,
-                                                            jint responseValue)
+                                                            jint isSecured, jint msgType)
 {
     LOGI("selectedNetwork - %d", selectedNetwork);
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
-    CAResult_t res = get_network_type(selectedNetwork);
+    if (!payload)
+    {
+        LOGE("payload is NULL");
+    }
+
+    if (!uri)
+    {
+        LOGE("Invalid input parameter : uri");
+        return;
+    }
+
+    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+    CAResult_t res = get_network_type(selectedNetwork, &flags);
     if (CA_STATUS_OK != res)
     {
         LOGE("Not supported network type");
@@ -579,8 +689,7 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
     const char* strUri = (*env)->GetStringUTFChars(env, uri, NULL);
     LOGI("RMSendNotification - %s", strUri);
 
-    CATransportFlags_t flags;
-    addressSet_t address = {};
+    addressSet_t address = {{0}, 0};
     parsing_coap_uri(strUri, &address, &flags);
 
     //create remote endpoint
@@ -615,11 +724,11 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
         return;
     }
 
-    CAInfo_t responseData = { 0 };
-    responseData.token = token;
-    responseData.tokenLength = tokenLength;
-    responseData.resourceUri = (CAURI_t) malloc(sizeof(resourceURI));
-    if (NULL == responseData.resourceUri)
+    CAInfo_t requestData = { 0 };
+    requestData.token = token;
+    requestData.tokenLength = tokenLength;
+    requestData.resourceUri = (CAURI_t) malloc(sizeof(resourceURI));
+    if (NULL == requestData.resourceUri)
     {
         LOGE("Memory allocation failed!");
         // destroy token
@@ -628,13 +737,13 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
         CADestroyEndpoint(endpoint);
         return;
     }
-    memcpy(responseData.resourceUri, resourceURI, sizeof(resourceURI));
+    memcpy(requestData.resourceUri, resourceURI, sizeof(resourceURI));
 
     if (1 == isSecured)
     {
         uint32_t length = sizeof(SECURE_INFO_DATA) + strlen(resourceURI);
-        responseData.payload = (CAPayload_t) malloc(length);
-        if (NULL == responseData.payload)
+        requestData.payload = (CAPayload_t) malloc(length);
+        if (NULL == requestData.payload)
         {
             LOGE("Memory allocation failed!");
             // destroy token
@@ -642,16 +751,18 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
             // destroy remote endpoint
             CADestroyEndpoint(endpoint);
 
-            free(responseData.resourceUri);
+            free(requestData.resourceUri);
             return;
         }
-        snprintf(responseData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
+        snprintf((char *) requestData.payload, length, SECURE_INFO_DATA,
+                 resourceURI, g_localSecurePort);
+        requestData.payloadSize = length;
     }
     else
     {
         uint32_t length = sizeof(NORMAL_INFO_DATA) + strlen(resourceURI);
-        responseData.payload = (CAPayload_t) malloc(length);
-        if (NULL == responseData.payload)
+        requestData.payload = (CAPayload_t) malloc(length);
+        if (NULL == requestData.payload)
         {
             LOGE("Memory allocation failed!");
             // destroy token
@@ -659,20 +770,21 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
             // destroy remote endpoint
             CADestroyEndpoint(endpoint);
 
-            free(responseData.resourceUri);
+            free(requestData.resourceUri);
             return;
         }
-        snprintf(responseData.payload, length, NORMAL_INFO_DATA, resourceURI);
+        snprintf((char *) requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
+        requestData.payloadSize = length;
     }
 
-    responseData.type = messageType;
+    requestData.type = messageType;
 
-    CAResponseInfo_t responseInfo = { 0 };
-    responseInfo.result = responseValue;
-    responseInfo.info = responseData;
+    CARequestInfo_t requestInfo = { 0 };
+    requestInfo.method = CA_GET;
+    requestInfo.info = requestData;
 
     // send notification
-    if (CA_STATUS_OK != CASendNotification(endpoint, &responseInfo))
+    if (CA_STATUS_OK != CASendRequest(endpoint, &requestInfo))
     {
         LOGE("Could not send notification");
     }
@@ -685,8 +797,8 @@ Java_org_iotivity_ca_service_RMInterface_RMSendNotification(JNIEnv *env, jobject
     // destroy remote endpoint
     CADestroyEndpoint(endpoint);
 
-    free(responseData.payload);
-    free(responseData.resourceUri);
+    free(requestData.payload);
+    free(requestData.resourceUri);
 }
 
 JNIEXPORT void JNICALL
@@ -694,6 +806,11 @@ Java_org_iotivity_ca_service_RMInterface_RMSelectNetwork(JNIEnv *env, jobject ob
                                                          jint networkType)
 {
     LOGI("RMSelectNetwork Type : %d", networkType);
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     if (CA_STATUS_OK != CASelectNetwork(networkType))
     {
@@ -706,6 +823,11 @@ Java_org_iotivity_ca_service_RMInterface_RMUnSelectNetwork(JNIEnv *env, jobject
                                                            jint networkType)
 {
     LOGI("RMUnSelectNetwork Type : %d", networkType);
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     if (CA_STATUS_OK != CAUnSelectNetwork(networkType))
     {
@@ -717,6 +839,11 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMGetNetworkInfomation(JNIEnv *env, jobject obj)
 {
     LOGI("RMGetNetworkInfomation");
+    if (!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     CAEndpoint_t *tempInfo = NULL;
     uint32_t tempSize = 0;
@@ -736,7 +863,7 @@ Java_org_iotivity_ca_service_RMInterface_RMGetNetworkInfomation(JNIEnv *env, job
     uint32_t index;
     for (index = 0; index < tempSize; index++)
     {
-        res = get_remote_address(tempInfo[index].adapter, tempInfo[index].addr);
+        res = get_remote_address(tempInfo[index].addr);
         if (CA_STATUS_OK != res)
         {
             free(tempInfo);
@@ -746,12 +873,12 @@ Java_org_iotivity_ca_service_RMInterface_RMGetNetworkInfomation(JNIEnv *env, job
         {
             char networkInfo[NETWORK_INFO_LENGTH];
             LOGI("Type: %d", tempInfo[index].adapter);
-            sprintf(networkInfo, "%d",tempInfo[index].adapter);
+            snprintf(networkInfo, NETWORK_INFO_LENGTH, "%d",tempInfo[index].adapter);
             callback("Type :", networkInfo);
             if (CA_ADAPTER_IP == tempInfo[index].adapter)
             {
                 LOGI("Port: %d", tempInfo[index].port);
-                sprintf(networkInfo, "%d",tempInfo[index].port);
+                snprintf(networkInfo, NETWORK_INFO_LENGTH, "%d",tempInfo[index].port);
                 callback("Port: ", networkInfo);
             }
             LOGI("Secured: %d", (tempInfo[index].flags & CA_SECURE));
@@ -775,6 +902,11 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_service_RMInterface_RMHandleRequestResponse(JNIEnv *env, jobject obj)
 {
     LOGI("RMHandleRequestResponse");
+    if(!env || !obj)
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
 
     if (CA_STATUS_OK != CAHandleRequestResponse())
     {
@@ -805,7 +937,7 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
         return;
     }
 
-    CAResult_t res = get_remote_address(object->adapter, object->addr);
+    CAResult_t res = get_remote_address(object->addr);
     if (CA_STATUS_OK != res)
     {
         return;
@@ -859,7 +991,7 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
         free(g_remoteAddress);
 
         char portInfo[PORT_LENGTH] = { 0, };
-        sprintf(portInfo, "%d", object->port);
+        snprintf(portInfo, PORT_LENGTH, "%d", object->port);
         callback("Remote Port: ", portInfo);
 
         //clone g_clientEndpoint
@@ -921,7 +1053,14 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
             memcpy(clonePayload, requestInfo->info.payload, len);
             clonePayload[len] = '\0';
 
-            callback("Data: ", clonePayload);
+            if (len > BIG_PAYLOAD_LENGTH)
+            {
+                saveFile(clonePayload, len);
+            }
+            else
+            {
+                callback("Data: ", clonePayload);
+            }
             free(clonePayload);
         }
     }
@@ -943,9 +1082,10 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
             if (NULL != g_responseListenerObject)
             {
                 char optionInfo[OPTION_INFO_LENGTH] = { 0, };
-                sprintf(optionInfo, "Num[%d] - ID : %d, Option Length : %d", i + 1,
-                        requestInfo->info.options[i].optionID,
-                        requestInfo->info.options[i].optionLength);
+                snprintf(optionInfo, OPTION_INFO_LENGTH,
+                         "Num[%d] - ID : %d, Option Length : %d", i + 1,
+                         requestInfo->info.options[i].optionID,
+                         requestInfo->info.options[i].optionLength);
 
                 callback("Option info: ", optionInfo);
 
@@ -990,8 +1130,13 @@ void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestI
 
 void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo)
 {
+    if (!object || !responseInfo)
+    {
+        LOGE("Invalid input parameter");
+        return;
+    }
 
-    CAResult_t res = get_remote_address(object->adapter, object->addr);
+    CAResult_t res = get_remote_address(object->addr);
     if (CA_STATUS_OK != res)
     {
         return;
@@ -1045,7 +1190,7 @@ void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* respon
         free(g_remoteAddress);
 
         char portInfo[PORT_LENGTH] = { 0, };
-        sprintf(portInfo, "%d", object->port);
+        snprintf(portInfo, PORT_LENGTH, "%d", object->port);
         callback("Remote Port: ", portInfo);
 
         if (NULL != responseInfo->info.payload && responseInfo->info.payloadSize)
@@ -1061,7 +1206,14 @@ void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* respon
             memcpy(clonePayload, responseInfo->info.payload, len);
             clonePayload[len] = '\0';
 
-            callback("Data: ", clonePayload);
+            if (len > BIG_PAYLOAD_LENGTH)
+            {
+                saveFile(clonePayload, len);
+            }
+            else
+            {
+                callback("Data: ", clonePayload);
+            }
             free(clonePayload);
         }
     }
@@ -1080,9 +1232,10 @@ void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* respon
             if (NULL != g_responseListenerObject)
             {
                 char optionInfo[OPTION_INFO_LENGTH] = { 0, };
-                sprintf(optionInfo, "Num[%d] - ID : %d, Option Length : %d", i + 1,
-                        responseInfo->info.options[i].optionID,
-                        responseInfo->info.options[i].optionLength);
+                snprintf(optionInfo, OPTION_INFO_LENGTH,
+                         "Num[%d] - ID : %d, Option Length : %d", i + 1,
+                         responseInfo->info.options[i].optionID,
+                         responseInfo->info.options[i].optionLength);
 
                 callback("Option info: ", optionInfo);
 
@@ -1115,9 +1268,15 @@ void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* respon
 
 void error_handler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
 {
-    printf("+++++++++++++++++++++++++++++++++++ErrorInfo+++++++++++++++++++++++++++++++++++");
+    LOGI("+++++++++++++++++++++++++++++++++++ErrorInfo+++++++++++++++++++++++++++++++++++");
 
-    if(errorInfo)
+    if (rep)
+    {
+        LOGI("Error Handler, Adapter Type : %d", rep->adapter);
+        LOGI("Error Handler, Adapter Type : %s", rep->addr);
+    }
+
+    if (errorInfo)
     {
         const CAInfo_t *info = &errorInfo->info;
         LOGI("Error Handler, ErrorInfo :");
@@ -1154,7 +1313,7 @@ void error_handler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
     return;
 }
 
-void get_resource_uri(const char *URI, char *resourceURI, uint32_t length)
+void get_resource_uri(const char *URI, char *resourceURI, int32_t length)
 {
     const char *startPos = URI;
     const char *temp = strstr(URI, "://");
@@ -1194,13 +1353,13 @@ uint32_t get_secure_information(CAPayload_t payLoad)
     }
 
     const char *subString = NULL;
-    if (NULL == (subString = strstr(payLoad, "\"sec\":1")))
+    if (NULL == (subString = strstr((const char *) payLoad, "\"sec\":1")))
     {
         LOGE("This is not secure resource");
         return -1;
     }
 
-    if (NULL == (subString = strstr(payLoad, "\"port\":")))
+    if (NULL == (subString = strstr((const char *) payLoad, "\"port\":")))
     {
         LOGE("This secure resource does not have port information");
         return -1;
@@ -1227,51 +1386,112 @@ uint32_t get_secure_information(CAPayload_t payLoad)
     return atoi(portStr);
 }
 
-CAResult_t get_network_type(uint32_t selectedNetwork)
+CAResult_t get_network_type(uint32_t selectedNetwork, CATransportFlags_t *flags)
 {
 
     uint32_t number = selectedNetwork;
 
-    if (!(number & 0xf))
+    if (!(number & CA_ALL_ADAPTERS))
     {
+        LOGE("get_network_type Out of range");
         return CA_NOT_SUPPORTED;
     }
-    if (number & CA_ADAPTER_IP)
+    if ((number & CA_ADAPTER_IP) == CA_ADAPTER_IP)
     {
+        *flags = CA_IPV4;
         g_selectedNwType = CA_ADAPTER_IP;
         return CA_STATUS_OK;
     }
-    if (number & CA_ADAPTER_RFCOMM_BTEDR)
+    if ((number & CA_ADAPTER_RFCOMM_BTEDR) == CA_ADAPTER_RFCOMM_BTEDR)
     {
         g_selectedNwType = CA_ADAPTER_RFCOMM_BTEDR;
         return CA_STATUS_OK;
     }
-    if (number & CA_ADAPTER_GATT_BTLE)
+    if ((number & CA_ADAPTER_GATT_BTLE) == CA_ADAPTER_GATT_BTLE)
     {
         g_selectedNwType = CA_ADAPTER_GATT_BTLE;
         return CA_STATUS_OK;
     }
+    if ((number & CA_ADAPTER_TCP) == CA_ADAPTER_TCP)
+    {
+        g_selectedNwType = CA_ADAPTER_TCP;
+        return CA_STATUS_OK;
+    }
+    if ((number & CA_ADAPTER_NFC) == CA_ADAPTER_NFC)
+    {
+        g_selectedNwType = CA_ADAPTER_NFC;
+        return CA_STATUS_OK;
+    }
 
-    return CA_NOT_SUPPORTED;
+   LOGE("Invalid transport");
+   return CA_NOT_SUPPORTED;
 }
 
 void callback(char *subject, char *receivedData)
 {
-    JNIEnv* env = NULL;
-    uint32_t status = (*g_jvm)->GetEnv(g_jvm, (void **) &env, JNI_VERSION_1_6);
-    uint32_t res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+    bool isAttached = false;
+    JNIEnv* env;
+
+    if (!g_responseListenerObject)
+    {
+        LOGE("g_responseListenerObject is NULL, cannot have callback");
+        return;
+    }
+
+    jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+    if (JNI_OK != res)
+    {
+        LOGI("Could not get JNIEnv pointer");
+        res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+        if (JNI_OK != res)
+        {
+            LOGE("AttachCurrentThread has failed");
+            return;
+        }
+        isAttached = true;
+    }
 
     jclass cls = (*env)->GetObjectClass(env, g_responseListenerObject);
+    if (!cls)
+    {
+        LOGE("could not get class");
+        goto detach_thread;
+    }
+
     jmethodID mid = (*env)->GetMethodID(env, cls, "OnResponseReceived",
                                         "(Ljava/lang/String;Ljava/lang/String;)V");
+    if (!mid)
+    {
+        LOGE("could not get Method ID");
+        goto detach_thread;
+    }
 
     jstring jsubject = (*env)->NewStringUTF(env, (char*) subject);
+    if (!jsubject)
+    {
+        LOGE("NewStringUTF failed");
+        goto detach_thread;
+    }
+
     jstring jreceivedData = (*env)->NewStringUTF(env, (char*) receivedData);
+    if (!jreceivedData)
+    {
+        LOGE("NewStringUTF failed");
+        goto detach_thread;
+    }
+
     (*env)->CallVoidMethod(env, g_responseListenerObject, mid, jsubject, jreceivedData);
 
+detach_thread :
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+        LOGI("DetachCurrentThread");
+    }
 }
 
-CAResult_t get_remote_address(CATransportAdapter_t transportType, const char *address)
+CAResult_t get_remote_address(const char *address)
 {
     uint32_t len = strlen(address);
 
@@ -1309,11 +1529,16 @@ void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t
     {
         LOGI("uri has '%s' prefix", COAP_PREFIX);
         startIndex = COAP_PREFIX_LEN;
+    }
+    else if (strncmp(COAP_TCP_PREFIX, uri, COAP_TCP_PREFIX_LEN) == 0)
+    {
+        LOGI("uri has '%s' prefix\n", COAP_TCP_PREFIX);
+        startIndex = COAP_TCP_PREFIX_LEN;
         *flags = CA_IPV4;
     }
 
     // #2. copy uri for parse
-    int32_t len = strlen(uri) - startIndex;
+    size_t len = strlen(uri) - startIndex;
 
     if (len <= 0)
     {
@@ -1328,33 +1553,27 @@ void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t
         return;
     }
 
-    memcpy(cloneUri, &uri[startIndex], sizeof(char) * len);
-    cloneUri[len] = '\0';
+    OICStrcpy(cloneUri, len+1, &uri[startIndex]);
 
-    char *pAddress = cloneUri;
-    char *pResourceUri = NULL;
+    char *pstr = NULL;
+    //filter out the resource uri
+    char *pUrl = strtok_r(cloneUri, "/", &pstr);
 
-    int32_t i = 0;
-    for (i = 0; i < len; i++)
+    if (pUrl)
     {
-        if (cloneUri[i] == '/')
+        LOGI("pAddress : %s", pUrl);
+        int res = get_address_set(pUrl, address);
+        if (res == -1)
         {
-            // separate
-            cloneUri[i] = 0;
-            pResourceUri = &cloneUri[i + 1];
-            break;
+            LOGE("address parse error");
+            return;
         }
     }
-    LOGI("pAddress : %s", pAddress);
-
-    int res = get_address_set(pAddress, address);
-    if (res == -1)
+    else
     {
-        LOGE("address parse error");
-
-        free(cloneUri);
-        return;
+        LOGE("strtok_r error, could not get the address");
     }
+
     return;
 }
 
@@ -1366,12 +1585,11 @@ int get_address_set(const char *pAddress, addressSet_t* outAddress)
         return -1;
     }
 
-    int32_t len = strlen(pAddress);
-    int32_t isIp = 0;
-    int32_t ipLen = 0;
+    size_t len = strlen(pAddress);
+    int isIp = 0;
+    size_t ipLen = 0;
 
-    int32_t i = 0;
-    for (i = 0; i < len; i++)
+    for (size_t i = 0; i < len; i++)
     {
         if (pAddress[i] == '.')
         {
@@ -1388,12 +1606,12 @@ int get_address_set(const char *pAddress, addressSet_t* outAddress)
 
     if (isIp)
     {
-        if(ipLen && ipLen < sizeof(outAddress->ipAddress))
+        if(ipLen && (ipLen <  sizeof(outAddress->ipAddress)))
         {
             strncpy(outAddress->ipAddress, pAddress, ipLen);
             outAddress->ipAddress[ipLen] = '\0';
         }
-        else if (!ipLen && len < sizeof(outAddress->ipAddress))
+        else if (!ipLen && (len <  sizeof(outAddress->ipAddress)))
         {
             strncpy(outAddress->ipAddress, pAddress, len);
             outAddress->ipAddress[len] = '\0';
@@ -1417,3 +1635,131 @@ int get_address_set(const char *pAddress, addressSet_t* outAddress)
 
     return isIp;
 }
+
+void delete_global_references(JNIEnv *env, jobject obj)
+{
+    LOGI("delete_global_references");
+    if (!env || !obj )
+    {
+        LOGI("Invalid input parameter");
+        return;
+    }
+
+    CADeleteGlobalReferences(env);
+    (*env)->DeleteGlobalRef(env, g_responseListenerObject);
+}
+
+
+bool read_file(const char* name, char** bytes, size_t* length)
+{
+    if (NULL == name)
+    {
+        LOGE("parameter is null");
+        return false;
+    }
+
+    FILE* file;
+    char* buffer;
+    long fileLen;
+
+    // Open file
+    file = fopen(name, "rt");
+    if (!file)
+    {
+        fprintf(stderr, "Unable to open file %s", name);
+        return false;
+    }
+
+    // Get file length
+    fseek(file, 0, SEEK_END);
+    fileLen = ftell(file);
+    if (-1 == fileLen)
+    {
+        fprintf(stderr, "Failed to read file length");
+        fclose(file);
+        return false;
+    }
+    fseek(file, 0, SEEK_SET);
+
+    LOGI("file size: %ld", fileLen);
+
+    // Allocate memory
+    buffer = calloc(1, sizeof(char) * fileLen + 1);
+    if (!buffer)
+    {
+        fprintf(stderr, "Memory error!");
+        fclose(file);
+        return false;
+    }
+
+    // Read file contents into buffer
+    size_t ret = fread(buffer, fileLen, 1, file);
+    if (ret != 1)
+    {
+        printf("Failed to read data from file, %s\n", name);
+        fclose(file);
+        free(buffer);
+        return false;
+    }
+
+    fclose(file);
+
+    LOGI("file bytes: %s", buffer);
+
+    *bytes = buffer;
+    *length = fileLen;
+
+    return true;
+}
+
+void saveFile(const char *payload, size_t payloadSize)
+{
+    // 1. get day
+    uint32_t day = gettodaydate();
+
+    // 2. get time
+    time_t current_time;
+    struct tm * time_info;
+    char timeString[RECEIVED_FILE_NAME_PREFIX_LENGTH];
+
+    time(&current_time);
+    time_info = localtime(&current_time);
+
+    strftime(timeString, sizeof(timeString), "%H%M%S", time_info);
+
+    uint32_t path_length = strlen(RECEIVED_FILE_PATH) + RECEIVED_FILE_NAME_LENGTH + 1;
+    char* path = calloc(1, sizeof(char) * path_length);
+    if (path != NULL)
+    {
+        snprintf(path, path_length, RECEIVED_FILE_PATH, day, timeString);
+        LOGI("received file path: %s", path);
+
+        FILE *fp = fopen(path, "wt");
+        fwrite(payload, 1, payloadSize, fp);
+        fclose(fp);
+
+        callback("File Path: ", path);
+    }
+    else
+    {
+        LOGE("path Out of memory");
+    }
+}
+
+uint32_t gettodaydate()
+{
+    uint32_t ldate;
+    time_t clock;
+    struct tm *date;
+
+    clock = time(0);
+    date = localtime(&clock);
+    ldate = date->tm_year * 100000;
+    ldate += (date->tm_mon + 1) * 1000;
+    ldate += date->tm_mday * 10;
+    ldate += date->tm_wday;
+    ldate += 190000000;
+    ldate /= 10;
+
+    return(ldate);
+}