import android.net.ConnectivityManager;\r
import android.net.NetworkInfo;\r
import android.net.wifi.WifiManager;\r
++import android.util.Log;\r
\r
public class CaIpInterface {\r
private static Context mContext;\r
\r
++ public enum WifiAPState{\r
++ WIFI_AP_STATE_DISABLING (10),\r
++ WIFI_AP_STATE_DISABLED (11),\r
++ WIFI_AP_STATE_ENABLING (12),\r
++ WIFI_AP_STATE_ENABLED (13),\r
++ WIFI_AP_STATE_FAILED (14)\r
++ ; // semicolon needed when fields / methods follow\r
++\r
++\r
++ private final int apstate;\r
++\r
++ WifiAPState(int apstate)\r
++ {\r
++ this.apstate = apstate;\r
++ }\r
++ public int getIntValue() {\r
++ return this.apstate;\r
++ }\r
++ }\r
++\r
private CaIpInterface(Context context) {\r
mContext = context;\r
registerIpStateReceiver();\r
IntentFilter intentFilter = new IntentFilter();\r
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);\r
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);\r
++ intentFilter.addAction("android.net.wifi.WIFI_AP_STATE_CHANGED");\r
\r
mContext.registerReceiver(mReceiver, intentFilter);\r
}\r
caIpStateEnabled();\r
}\r
}\r
++\r
++ if (intent.getAction().equals("android.net.wifi.WIFI_AP_STATE_CHANGED")) {\r
++ if (intent.getIntExtra("wifi_state",\r
++ WifiAPState.WIFI_AP_STATE_DISABLED.getIntValue())\r
++ == WifiAPState.WIFI_AP_STATE_DISABLED.getIntValue())\r
++ {\r
++ caIpStateDisabled();\r
++ }else if(intent.getIntExtra("wifi_state",\r
++ WifiAPState.WIFI_AP_STATE_DISABLED.getIntValue())\r
++ == WifiAPState.WIFI_AP_STATE_ENABLED.getIntValue())\r
++ {\r
++ try {\r
++ Thread.sleep(1000);\r
++ } catch (InterruptedException e) {\r
++ // TODO Auto-generated catch block\r
++ e.printStackTrace();\r
++ }\r
++ caIpStateEnabled();\r
++ }\r
++ }\r
}\r
};\r
\r
env.SConscript('./src/SConscript')
-if build_sample == 'ON':
- if target_os in ['linux', 'arduino', 'android']:
- env.SConscript('./samples/' + target_os + '/SConscript')
-
+#if build_sample == 'ON':
+# if target_os in ['linux', 'arduino', 'android']:
+# env.SConscript('./samples/' + target_os + '/SConscript')
-
VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
- CAResult_t ret = CAIPJniInit();
+ CAResult_t ret = CA_STATUS_FAILED;
+
- //TODO: Have to fix the JNI load issue for CA using direct csdk APIs instead OCPlatform Java API
- // and remove the EASY_SETUP_CA_INIT
- #ifndef EASY_SETUP_CA_INIT
+ ret = CAIPJniInit();
if (CA_STATUS_OK != ret)
{
OIC_LOG(ERROR, IP_MONITOR_TAG, "Initialization failed");
return OC_STACK_OK;
}
- OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
- const char *referenceUri, const char *request, OCConnectivityType conType,
- OCQualityOfService qos, OCCallbackData *cbData,
- OCHeaderOption * options, uint8_t numOptions)
+ /**
+ * A request uri consists of the following components in order:
+ * example
+ * optional prefix "coap://"
+ * optionally one of
+ * IPv6 address "[1234::5678]"
+ * IPv4 address "192.168.1.1"
+ * optional port ":5683"
+ * resource uri "/oc/core..."
+ *
+ * for PRESENCE requests, extract resource type.
+ */
+ static OCStackResult ParseRequestUri(const char *fullUri,
+ OCTransportAdapter adapter,
+ OCTransportFlags flags,
+ OCDevAddr **devAddr,
+ char **resourceUri,
+ char **resourceType)
{
- OCStackResult result = OC_STACK_ERROR;
- ClientCB *clientCB = NULL;
- char * requestUri = NULL;
- char * resourceType = NULL;
- char * query = NULL;
- char * newUri = (char *)requiredUri;
- (void) referenceUri;
- CARemoteEndpoint_t* endpoint = NULL;
- CAResult_t caResult;
- CAToken_t token = NULL;
- uint8_t tokenLength = CA_MAX_TOKEN_LEN;
- OCDoHandle resHandle = NULL;
- CAInfo_t requestData ={};
- CARequestInfo_t requestInfo ={};
- CAGroupEndpoint_t grpEnd = {};
+ VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
- OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
+ OCStackResult result = OC_STACK_OK;
+ OCDevAddr *da = NULL;
+ char *colon = NULL;
+ char *end;
- // Validate input parameters
- VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
- VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
+ // provide defaults for all returned values
+ if (devAddr)
+ {
+ *devAddr = NULL;
+ }
+ if (resourceUri)
+ {
+ *resourceUri = NULL;
+ }
+ if (resourceType)
+ {
+ *resourceType = NULL;
+ }
- //TODO ("Need to form the final query by concatenating require and reference URI's");
- VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
+ // delimit url prefix, if any
+ const char *start = fullUri;
+ char *slash2 = strstr(start, "//");
+ if (slash2)
+ {
+ start = slash2 + 2;
+ }
+ char *slash = strchr(start, '/');
+ if (!slash)
+ {
+ return OC_STACK_INVALID_URI;
+ }
- uint16_t uriLen = strlen(requiredUri);
+ // processs url prefix, if any
+ size_t urlLen = slash - start;
+ if (urlLen && devAddr)
+ { // construct OCDevAddr
+ if (start[0] == '[')
+ { // ipv6 address
+ char *close = strchr(++start, ']');
+ if (!close || close > slash)
+ {
+ return OC_STACK_INVALID_URI;
+ }
+ end = close;
+ if (close[1] == ':')
+ {
+ colon = close + 1;
+ }
+ }
+ else
+ { // ipv4 address
+ end = slash;
+ colon = strchr(start, ':');
+ end = (colon && colon < slash) ? colon : slash;
+ }
+ size_t len = end - start;
+ if (len > MAX_ADDR_STR_SIZE)
+ {
+ return OC_STACK_INVALID_URI;
+ }
- // ToDo: We should also check if the requiredUri has a mutlicast address,
- // then qos has to be OC_Low_QOS
- switch (method)
- {
- case OC_REST_GET:
- case OC_REST_OBSERVE:
- case OC_REST_OBSERVE_ALL:
- case OC_REST_CANCEL_OBSERVE:
- requestInfo.method = CA_GET;
- break;
+ // port
+ uint16_t port = 0; // use standard multicast port
+ if (colon && colon < slash)
+ {
+ for (colon++; colon < slash; colon++)
+ {
+ char c = colon[0];
+ if (c < '0' || c > '9')
+ {
+ return OC_STACK_INVALID_URI;
+ }
+ port = 10 * port + c - '0';
+ }
+ }
- case OC_REST_PUT:
- requestInfo.method = CA_PUT;
- break;
- da = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
++ da = (OCDevAddr *)OICCalloc(1, sizeof (OCDevAddr));
+ if (!da)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ strncpy(da->addr, start, len);
+ da->port = port;
+ da->adapter = adapter;
+ da->flags = flags;
+ if (!strncmp(fullUri, "coaps:", 6))
+ {
+ da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
+ }
+ *devAddr = da;
+ }
- case OC_REST_POST:
- requestInfo.method = CA_POST;
- break;
+ // process resource uri, if any
+ if (slash)
+ { // request uri and query
+ size_t ulen = strlen(slash); // resource uri length
+ size_t tlen = 0; // resource type length
+ char *type = NULL;
- case OC_REST_DELETE:
- requestInfo.method = CA_DELETE;
- break;
+ static const char *strPresence = "/oc/presence?rt=";
+ static const size_t lenPresence = 15; // = strlen(presence);
+ if (!strncmp(slash, strPresence, lenPresence))
+ {
+ type = slash + lenPresence;
+ tlen = ulen - lenPresence;
+ }
+ // resource uri
+ if (resourceUri)
+ {
+ *resourceUri = (char *)OICMalloc(ulen + 1);
+ if (!*resourceUri)
+ {
+ result = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+ strcpy(*resourceUri, slash);
+ }
+ // resource type
+ if (type && resourceType)
+ {
+ *resourceType = (char *)OICMalloc(tlen + 1);
+ if (!*resourceType)
+ {
+ result = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+ strncpy(*resourceType, type, tlen);
+ }
+ }
- #ifdef WITH_PRESENCE
- case OC_REST_PRESENCE:
- // Replacing method type with GET because "presence"
- // is a stack layer only implementation.
- requestInfo.method = CA_GET;
- break;
- #endif
+ return OC_STACK_OK;
- default:
- result = OC_STACK_INVALID_METHOD;
- goto exit;
+ error:
+ // free all returned values
+ if (devAddr)
+ {
+ OICFree(*devAddr);
+ }
+ if (resourceUri)
+ {
+ OICFree(*resourceUri);
}
+ if (resourceType)
+ {
+ OICFree(*resourceType);
+ }
+ return result;
+ }
+
+ static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
+ char *resourceUri, char **requestUri)
+ {
+ char uri[CA_MAX_URI_LENGTH];
+
+ FormCanonicalPresenceUri(endpoint, resourceUri, uri);
+
+ *requestUri = (char *)OICMalloc(strlen(uri) + 1);
+ if (!*requestUri)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+
+ strcpy(*requestUri, uri);
+ return OC_STACK_OK;
+ }
+
+ /**
+ * Discover or Perform requests on a specified resource
+ */
+ OCStackResult OCDoResource(OCDoHandle *handle,
+ OCMethod method,
+ const char *requestUri,
+ const OCDevAddr *destination,
+ const char *request,
+ OCConnectivityType connectivityType,
+ OCQualityOfService qos,
+ OCCallbackData *cbData,
+ OCHeaderOption *options,
+ uint8_t numOptions)
+ {
+ OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
+
+ // Validate input parameters
+ VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
+ VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
+ VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI);
- if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
+ OCStackResult result = OC_STACK_ERROR;
+ CAResult_t caResult;
+ CAToken_t token = NULL;
+ uint8_t tokenLength = CA_MAX_TOKEN_LEN;
+ ClientCB *clientCB = NULL;
+ OCDoHandle resHandle = NULL;
+ CAEndpoint_t *endpoint = NULL;
+ OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
+ uint32_t ttl = 0;
+ OCTransportAdapter adapter;
+ OCTransportFlags flags;
+ // the request contents are put here
+ CARequestInfo_t requestInfo = { CA_GET };
+ // requestUri will be parsed into the following three variables
+ OCDevAddr *devAddr = NULL;
+ char *resourceUri = NULL;
+ char *resourceType = NULL;
+
+ // To track if memory is allocated for additional header options
+ uint8_t hdrOptionMemAlloc = 0;
+
+ // This validation is broken, but doesn't cause harm
+ size_t uriLen = strlen(requestUri );
+ if ((result = verifyUriQueryLength(requestUri , uriLen)) != OC_STACK_OK)
{
goto exit;
}
# Build protocol plugin project
# protocol-plugin use 'inotify', this feature isn't support by MAC OSX
- if target_os not in ['darwin', 'ios']:
- SConscript('protocol-plugin/SConscript')
+ #if target_os not in ['darwin', 'ios', 'android']:
+ # SConscript('protocol-plugin/SConscript')
# Build notification manager project
- SConscript('notification-manager/SConscript')
-#else:
-# SConscript('notification-manager/SampleApp/arduino/SConscript')
-
+ #SConscript('notification-manager/SConscript')
+
+if target_os in ['arduino','android', 'linux']:
- SConscript('easy-setup/SConscript')
++ SConscript('easy-setup/SConscript')
--- /dev/null
- env.get('SRC_DIR') + '/resource/csdk/ocmalloc/include',
+#******************************************************************
+#
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# easy-setup project build script
+##
+
+import os
+
+Import('env')
+
+env.AppendUnique(CPPDEFINES = ['EASY_SETUP_CA_INIT'])
+
+easy_setup_env = env.Clone()
+target_os = env.get('TARGET_OS')
+
+lib_env = env.Clone()
+if target_os == 'android':
+ SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env')
+
+######################################################################
+# Build flags
+######################################################################
+easy_setup_env.AppendUnique(CPPPATH = ['sdk/inc', 'sdk/src', 'sdk/common'])
+
+if target_os not in ['windows', 'winrt']:
+ easy_setup_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+ if target_os not in ['android', 'arduino']:
+ easy_setup_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+if target_os in ['android', 'linux']:
+ easy_setup_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ easy_setup_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
+ easy_setup_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ if target_os not in ['linux', 'arduino']:
+ easy_setup_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'gnustl_shared'])
+ if not env.get('RELEASE'):
+ easy_setup_env.AppendUnique(LIBS = ['log'])
+ else:
+ easy_setup_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'pthread', 'connectivity_abstraction'])
+
+if target_os == 'arduino':
+ easy_setup_env.AppendUnique(CPPPATH = [
+ '../../resource/oc_logger/include',
+ '../../resource/csdk/logger/include',
+ '../../resource/csdk/stack/include',
+ '../../extlibs/cjson',
+ 'sdk/enrollee/arduino/wifi',
+ 'sdk/enrollee/common/src',
+ 'sdk/enrollee/common/inc'])
+
+if target_os in ['android','linux']:
+ easy_setup_env.PrependUnique(CPPPATH = [
++ env.get('SRC_DIR') + '/resource/c_common/oic_malloc/include',
+ env.get('SRC_DIR') + '/resource/csdk/connectivity/common/inc',
+ env.get('SRC_DIR') + '/resource/csdk/connectivity/api',
+ env.get('SRC_DIR') + '/resource/csdk/stack/include',
+ env.get('SRC_DIR') + '/resource/csdk/logger/include',
+ env.get('SRC_DIR') + '/resource/csdk/security/include',
+ env.get('SRC_DIR') + '/extlibs/cjson',
+ 'sdk/common',
+ 'sdk/mediator/inc'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+
+if target_os == 'arduino':
+ es_sdk_static = easy_setup_env.StaticLibrary('ESSDKLibrary',
+ ['sdk/enrollee/common/src/easysetup.cpp',
+ 'sdk/enrollee/common/src/resourceHandler.cpp',
+ 'sdk/enrollee/arduino/wifi/networkHandler.cpp'])
+ easy_setup_env.InstallTarget(es_sdk_static, 'libESSDK')
+
+
+if target_os == 'android':
+ es_sdk_shared = easy_setup_env.StaticLibrary('libESSDK',
+ ['sdk/mediator/src/easysetupmgr.cpp',
+ 'sdk/mediator/src/camutex_pthreads.c',
+ 'sdk/mediator/src/provisioninghandler.cpp'])
+ easy_setup_env.InstallTarget(es_sdk_shared, 'libESSDK')
+
+if target_os == 'linux':
+ es_sdk_shared = easy_setup_env.SharedLibrary('ESSDKLibrary',
+ ['sdk/mediator/src/easysetupmgr.cpp',
+ 'sdk/mediator/src/camutex_pthreads.c',
+ 'sdk/mediator/src/provisioninghandler.cpp'])
+ easy_setup_env.InstallTarget(es_sdk_shared, 'libESSDK')
+
+#Go to build sample apps
+SConscript('sampleapp/SConscript')
+
+
--- /dev/null
- void ProvisioningStatusCallback(ProvisioningInfo provInfo) {
- OIC_LOG_V(INFO, TAG, "Enrollee connectivity: %d", provInfo.provDeviceInfo.connType);
- if(provInfo.provStatus == DEVICE_PROVISIONED)
+//******************************************************************
+//
+// Copyright 2015 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sstream>
+
+#include "easysetupmgr.h"
+#include "logger.h"
+
+#define TAG "easysetupsample"
+
+int quitFlag = 0;
+
+/* SIGINT handler: set quitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+ if (signum == SIGINT) {
+ quitFlag = 1;
+ }
+}
+
+/**
+ * This callback function is used to receive the notifications about the provisioning status
+ * In success or failure, ProvisioningInfo structure holds the current state of provisioning
+ * and also holds the Enrollee information for which provisioning is requested
+ * This function can be used to update the application about the current provisioning status of the Enrollee
+ */
- OIC_LOG_V(INFO, TAG, "Successfully provisioned the Enrollee with IP : %d.%d.%d.%d ",
- provInfo.provDeviceInfo.addr->addr[0],
- provInfo.provDeviceInfo.addr->addr[1],
- provInfo.provDeviceInfo.addr->addr[2],
- provInfo.provDeviceInfo.addr->addr[3]);
++void ProvisioningStatusCallback(ProvisioningInfo *provInfo) {
++ OIC_LOG_V(INFO, TAG, "Enrollee connectivity: %d", provInfo->provDeviceInfo.connType);
++ if(provInfo->provStatus == DEVICE_PROVISIONED)
+ {
- OIC_LOG_V(INFO, TAG, "Provisioing Failed for the Enrollee with IP : %d.%d.%d.%d ",
- provInfo.provDeviceInfo.addr->addr[0],
- provInfo.provDeviceInfo.addr->addr[1],
- provInfo.provDeviceInfo.addr->addr[2],
- provInfo.provDeviceInfo.addr->addr[3]);
++ OIC_LOG_V(INFO, TAG, "Successfully provisioned the Enrollee with IP : %s ",
++ provInfo->provDeviceInfo.addr->addr);
+ }
+ else{
- netInfo.connType = OC_IPV4;
++ OIC_LOG_V(INFO, TAG, "Provisioing Failed for the Enrollee with IP : %s",
++ provInfo->provDeviceInfo.addr->addr);
+ }
+}
+
+static void PrintUsage()
+{
+ OIC_LOG(INFO, TAG, "Usage : occlient -d \"192.168.0.20\"");
+}
+
+
+int main (int argc, char**argv) {
+ int opt;
+ EnrolleeNWProvInfo_t netInfo;
+ PrintUsage();
+ InitEasySetupManager();
+
+ RegisterProvisioningStausCallback(ProvisioningStatusCallback);
+
+ while ((opt = getopt(argc, argv, "d:s:p:")) != -1)
+ {
+ switch(opt)
+ {
+ case 'd':
+ strncpy(netInfo.netAddressInfo.WIFI.ipAddress, optarg, IPV4_ADDR_SIZE);
+ break;
+ case 's':
+ strncpy(netInfo.netAddressInfo.WIFI.ssid, optarg, NET_WIFI_SSID_SIZE);
+ break;
+ case 'p':
+ strncpy(netInfo.netAddressInfo.WIFI.pwd, optarg, NET_WIFI_PWD_SIZE);
+ break;
+ default:
+ PrintUsage();
+ return -1;
+ }
+ }
+
++ netInfo.connType = CT_ADAPTER_IP;
+ OIC_LOG_V(INFO, TAG, "IP Address of the Provisioning device is =%s\n",
+ netInfo.netAddressInfo.WIFI.ipAddress);
+ OIC_LOG_V(INFO, TAG, "SSID of the Enroller is =%s\n",netInfo.netAddressInfo.WIFI.ssid);
+ OIC_LOG_V(INFO, TAG, "Password of the Enroller is =%s\n",netInfo.netAddressInfo.WIFI.pwd);
+
+ ProvisionEnrollee(&netInfo);
+
+ signal(SIGINT, handleSigInt);
+ while (!quitFlag) {
+ sleep(1);
+ }
++
++ TerminateEasySetupManager();
+ OIC_LOG(INFO, TAG, "Exiting occlient main loop...");
+
+ return 0;
+}
+
--- /dev/null
- static OCConnectivityType OC_CONNTYPE = OC_IPV4;
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef ES_COMMON_H_
+#define ES_COMMON_H_
+
+#include "ocstack.h"
+#include "octypes.h"
+
+// Defines
+#define OIC_STRING_MAX_VALUE 100
+#define IPV4_ADDR_SIZE 16
+#define IP_PORT 6298
+#define NET_WIFI_SSID_SIZE 16
+#define NET_WIFI_PWD_SIZE 16
+
+/**
+ * @brief Mac address length for BT port
+ */
+#define NET_MACADDR_SIZE 18
+
+//The following variable determines the interface (wifi, ethernet etc.)
+//to be used for sending unicast messages. Default set to Ethernet.
- static const char * OIC_PROVISIONING_URI = "/oic/prov";
++static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
+
+static const char * UNICAST_PROVISIONING_QUERY = "coap://%s:%d/oic/res?rt=oic.prov";
- typedef void (*OCProvisioningStatusCB)(ProvisioningInfo provInfo);
++static const char * UNICAST_PROV_STATUS_QUERY = "coap://%s:%d%s";
++
++
++/**
++ * Attributes used to form a proper easysetup conforming JSON message.
++ */
++#define OC_RSRVD_ES_PS "ps"
++#define OC_RSRVD_ES_TNN "tnn"
++#define OC_RSRVD_ES_CD "cd"
++
++
++
+
+typedef enum
+{
+ ES_ERROR = -1,
+ ES_OK = 0,
+ ES_NETWORKFOUND = 1,
+ ES_NETWORKCONNECTED,
+ ES_NETWORKNOTCONNECTED,
+ ES_RESOURCECREATED = 11,
+ ES_RECVREQOFPROVRES = 21,
+ ES_RECVREQOFNETRES,
+ ES_RECVUPDATEOFPROVRES,
+ ES_RECVTRIGGEROFPROVRES,
+} ES_RESULT;
+
+
+/**
+ * Provisioning Device Status
+ */
+typedef struct {
+ /// Address of remote server
+ OCDevAddr * addr;
+ /// Indicates adaptor type on which the response was received
+ OCConnectivityType connType;
+} ProvDeviceInfo;
+
+/**
+ * Provosioning Status
+ */
+typedef enum {
+ DEVICE_PROVISIONED = 0, DEVICE_NOT_PROVISIONED
+} ProvStatus;
+
+/**
+ * Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
+ */
+typedef struct {
+ // Provisioning Status
+ ProvStatus provStatus;
+ // Provisioning Device Info
+ ProvDeviceInfo provDeviceInfo;
+} ProvisioningInfo;
+
+/**
+ * @brief Network information of the Enroller
+ */
+typedef union
+{
+ /**
+ * @brief BT Mac Information
+ */
+ struct
+ {
+ char btMacAddress[NET_MACADDR_SIZE]; /**< BT mac address **/
+ } BT;
+
+ /**
+ * @brief LE MAC Information
+ */
+ struct
+ {
+ char leMacAddress[NET_MACADDR_SIZE]; /**< BLE mac address **/
+ } LE;
+
+ /**
+ * @brief IP Information
+ */
+ struct
+ {
+ char ipAddress[IPV4_ADDR_SIZE]; /**< IP Address of the Enroller**/
+ char ssid[NET_WIFI_SSID_SIZE]; /**< ssid of the Enroller**/
+ char pwd[NET_WIFI_PWD_SIZE]; /**< pwd of the Enroller**/
+ } WIFI;
+} EnrolleeInfo_t;
+
+
+/**
+ * @brief Network Information
+ */
+typedef struct
+{
+ EnrolleeInfo_t netAddressInfo; /**< Enroller Network Info**/
+ OCConnectivityType connType; /**< Connectivity Type**/
+ bool isSecured; /**< Secure connection**/
+} EnrolleeNWProvInfo_t;
+
+/**
+ * Client applications implement this callback to consume responses received from Servers.
+ */
++typedef void (*OCProvisioningStatusCB)(ProvisioningInfo *provInfo);
+
+#endif
--- /dev/null
- package="org.iotivity.service.easysetup"\r
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"\r
++ package="org.iotivity.service.easysetup.mediator"\r
+ android:versionCode="1"\r
+ android:versionName="1.0" >\r
+\r
+ <uses-sdk\r
+ android:minSdkVersion="8"\r
+ android:targetSdkVersion="21" />\r
+\r
+ <application\r
+ android:allowBackup="true"\r
+ android:icon="@drawable/ic_launcher"\r
+ android:label="@string/app_name"\r
+ android:theme="@style/AppTheme" >\r
+ </application>\r
+\r
+</manifest>\r
--- /dev/null
- void JNIProvisioningStatusCallback(ProvisioningInfo provInfo) {\r
+//******************************************************************\r
+//\r
+// Copyright 2015 Samsung Electronics All Rights Reserved.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+\r
+#include "jni_easy_setup.h"\r
+\r
+#include "jni_easy_setup_jvm.h"\r
+#include "easysetupmgr.h"\r
+\r
- if (provInfo.provStatus == DEVICE_PROVISIONED) {\r
++void JNIProvisioningStatusCallback(ProvisioningInfo *provInfo) {\r
+ JNIEnv *env = EasySetupJVM::getEnv();\r
+ if (env == NULL) {\r
+ LOGE("JNIProvisioningStatusCallback : Getting JNIEnv failed");\r
+ return;\r
+ }\r
+\r
+ // Get EasySetupHandler class reference\r
+ jclass easysetupCallbacks = GetJClass(\r
+ EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH);\r
+ if (NULL == easysetupCallbacks) {\r
+ LOGE(\r
+ "JNIProvisioningStatusCallback : GetJClass easysetupCallbacks failed");\r
+ EasySetupJVM::releaseEnv();\r
+ return;\r
+ }\r
+\r
+ // Get the easysetupCallback class instance\r
+ jobject jobjectCallback = GetJObjectInstance(\r
+ EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH);\r
+ if (NULL == jobjectCallback) {\r
+ LOGE("getInstance( %s) failed!",\r
+ EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH);\r
+ EasySetupJVM::releaseEnv();\r
+ return;\r
+ }\r
+\r
+ // Get onResourceCallback method reference\r
+ jmethodID method_id = env->GetMethodID(easysetupCallbacks,\r
+ "ProvisioningStatusCallBack",\r
+ METHOD_PROVISIONING_STATUS_INTEGER_CALLBACK);\r
+ if (NULL == method_id) {\r
+ LOGE(\r
+ "JNIProvisioningStatusCallback: onResourceCallback : GetMethodID failed");\r
+ EasySetupJVM::releaseEnv();\r
+ return;\r
+ }\r
+\r
+ if ((env)->ExceptionCheck()) {\r
+ LOGE("JNIProvisioningStatusCallback : ExceptionCheck failed");\r
+ EasySetupJVM::releaseEnv();\r
+ return;\r
+ }\r
+\r
+ if (NULL == method_id) {\r
+ LOGI("JNI method_id is NULL");\r
+ } else {\r
+ LOGI("JNI method_id is VALID");\r
+\r
+ jint result;\r
- netInfo.connType = OCConnectivityType::OC_IPV4;\r
++ if (provInfo->provStatus == DEVICE_PROVISIONED) {\r
+ result = 0;\r
+ } else {\r
+ result = -1;\r
+ }\r
+\r
+ env->CallVoidMethod(jobjectCallback, method_id, (jint) result);\r
+ }\r
+\r
+ EasySetupJVM::releaseEnv();\r
+}\r
+\r
+JNIEXPORT void JNICALL JNIInitEasySetup(JNIEnv *env, jobject thisObj)\r
+{\r
+ LOGI("JNI JNIInitEasySetup: Enter");\r
+ InitEasySetupManager();\r
+ RegisterProvisioningStausCallback(JNIProvisioningStatusCallback);\r
+}\r
+\r
+JNIEXPORT void JNICALL JNITerminateEasySetup(JNIEnv *env, jobject thisObj)\r
+{\r
+ LOGI("JNI JNITerminateEasySetup: Enter");\r
+ TerminateEasySetupManager();\r
+}\r
+\r
+\r
+JNIEXPORT void JNICALL JNIProvisionEnrollee(JNIEnv *env, jobject thisObj,\r
+ jstring jIPAddress,\r
+ jstring jNetSSID,\r
+ jstring jNetPWD,\r
+ jint jConnectivityType)\r
+{\r
+ LOGI("JNI JNIProvisionEnrollee: Enter");\r
+\r
+ if (!jIPAddress)\r
+ {\r
+ LOGE("JNI JNIProvisionEnrollee : jIPAddress is NULL!");\r
+ return;\r
+ }\r
+\r
+ const char *ipAddress = env->GetStringUTFChars(jIPAddress, NULL);\r
+ if (NULL == ipAddress)\r
+ {\r
+ LOGE("JNI JNIProvisionEnrollee : Failed to convert jstring to char string!");\r
+ }\r
+\r
+ LOGI("JNI JNIProvisionEnrollee : ipAddress is : %s",ipAddress);\r
+\r
+ const char *netSSID = env->GetStringUTFChars(jNetSSID, NULL);\r
+ if (NULL == netSSID)\r
+ {\r
+ LOGE("JNI JNIProvisionEnrollee : Failed to convert jstring to char string!");\r
+ }\r
+\r
+ LOGI("JNI JNIProvisionEnrollee : netSSID is : %s",netSSID);\r
+\r
+ const char *netPWD = env->GetStringUTFChars(jNetPWD, NULL);\r
+ if (NULL == netPWD)\r
+ {\r
+ LOGE("JNI JNIProvisionEnrollee : Failed to convert jstring to char string!");\r
+ }\r
+\r
+ LOGI("JNI JNIProvisionEnrollee : netPWD is : %s",netPWD);\r
+\r
+ OCConnectivityType connecitivityType;\r
+ EnrolleeNWProvInfo_t netInfo = {0};\r
+\r
+ strncpy(netInfo.netAddressInfo.WIFI.ipAddress, ipAddress, IPV4_ADDR_SIZE);\r
+ strncpy(netInfo.netAddressInfo.WIFI.ssid, netSSID, NET_WIFI_SSID_SIZE);\r
+ strncpy(netInfo.netAddressInfo.WIFI.pwd, netPWD, NET_WIFI_PWD_SIZE);\r
- connecitivityType = OCConnectivityType::OC_IPV4;\r
++ netInfo.connType = OCConnectivityType::CT_ADAPTER_IP;\r
+ netInfo.isSecured = true;\r
+\r
+ ProvisionEnrollee(&netInfo);\r
+\r
+ return;\r
+}\r
+\r
+JNIEXPORT void JNICALL JNIStopEnrolleeProvisioning(JNIEnv *env, jobject thisObj,\r
+ jint jConnectivityType)\r
+{\r
+ LOGI("JNI Stop Easy Setup: Entering");\r
+\r
+ OCConnectivityType connecitivityType;\r
+\r
+ if(jConnectivityType == 0)\r
+ {\r
++ connecitivityType = OCConnectivityType::CT_ADAPTER_IP;\r
+ }\r
+\r
+ StopEnrolleeProvisioning(connecitivityType);\r
+\r
+ return;\r
+}\r
+\r
+\r
--- /dev/null
- OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query);
+//******************************************************************
+//
+// Copyright 2015 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __PROVISIONING_HANDLER_H_
+#define __PROVISIONING_HANDLER_H_
+
+#include "logger.h"
+#include "ocstack.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "provisioninghandler"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#ifndef MAX_LENGTH_IPv4_ADDR
+#define MAX_LENGTH_IPv4_ADDR 16
+#endif
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * List of methods that can be inititated from the client
+ */
+OCStackResult InitProvisioningHandler();
+
+OCStackResult TerminateProvisioningHandler();
+
+void listeningFunc(void*);
+
+OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse);
+
- OCStackResult FindProvisioningResource(OCQualityOfService qos,
- const char* requestURI);
++OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri);
+
+OCStackApplicationResult GetProvisioningStatusResponse(void* ctx,
+ OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackResult InvokeOCDoResource(const char* query, OCMethod method,
+ OCQualityOfService qos, OCClientResponseHandler cb, const char* request,
+ OCHeaderOption * options, uint8_t numOptions);
+
+OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query);
+
+OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,
+ OCProvisioningStatusCB provisioningStatusCallback);
+
+
+void StopProvisioningProcess();
+
+OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse* clientResponse);
+
+OCStackResult SubscribeProvPresence(OCQualityOfService qos, const char* requestURI);
+
+OCStackApplicationResult FindProvisioningResourceResponse(void* ctx,
+ OCDoHandle handle, OCClientResponse * clientResponse);
+
- void PrepareProvisioingStatusCB(ProvisioningInfo *provInfo,
- OCClientResponse * clientResponse, ProvStatus provStatus);
++void FindProvisioningResource(void *data);
+
+//Invoke Provisioning Status Callback
++ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse,
++ ProvStatus provStatus);
+
+#endif
+
--- /dev/null
- #include <ocmalloc.h>
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+//
+//*********************************************************************
+
+/**
+ * @file
+ * This file provides APIs related to mutex and semaphores.
+ */
+
+// Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1b, Real-time extensions
+// (IEEE Std 1003.1b-1993) specification
+//
+// For this specific file, see use of clock_gettime and PTHREAD_MUTEX_DEFAULT
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <assert.h>
++#include <oic_malloc.h>
+
+#include "camutex.h"
+#include "logger.h"
+
+/**
+ * TAG
+ * Logging tag for module name
+ */
+#define TAG PCF("UMUTEX")
+
+static const uint64_t USECS_PER_SEC = 1000000;
+static const uint64_t NANOSECS_PER_USECS = 1000;
+static const uint64_t NANOSECS_PER_SEC = 1000000000L;
+
+typedef struct _tagMutexInfo_t {
+ pthread_mutex_t mutex;
+} ca_mutex_internal;
+
+typedef struct _tagEventInfo_t {
+ pthread_cond_t cond;
+ pthread_condattr_t condattr;
+} ca_cond_internal;
+
+ca_mutex ca_mutex_new(void) {
+ ca_mutex retVal = NULL;
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) OICMalloc(
+ sizeof(ca_mutex_internal));
+ if (NULL != mutexInfo) {
+ // create the mutex with the attributes set
+ int ret = pthread_mutex_init(&(mutexInfo->mutex),
+ PTHREAD_MUTEX_DEFAULT);
+ if (0 == ret) {
+ retVal = (ca_mutex) mutexInfo;
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s Failed to initialize mutex !", __func__);
+ OICFree(mutexInfo);
+ }
+ }
+
+ return retVal;
+}
+
+bool ca_mutex_free(ca_mutex mutex) {
+ bool bRet = false;
+
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
+ if (mutexInfo) {
+ int ret = pthread_mutex_destroy(&mutexInfo->mutex);
+ if (0 == ret) {
+ OICFree(mutexInfo);
+ bRet = true;
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s Failed to free mutex !", __func__);
+ }
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
+ }
+
+ return bRet;
+}
+
+void ca_mutex_lock(ca_mutex mutex) {
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
+ if (mutexInfo) {
+ int ret = pthread_mutex_lock(&mutexInfo->mutex);
+ assert(0 == ret);
+ (void) ret;
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
+ return;
+ }
+}
+
+bool ca_mutex_trylock(ca_mutex mutex) {
+ if (NULL == mutex) {
+ OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
+ return false;
+ }
+
+ bool bRet = false;
+
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
+
+ int result = pthread_mutex_trylock(&mutexInfo->mutex);
+
+ switch (result) {
+ case 0:
+ // Success
+ bRet = true;
+ break;
+ case EINVAL:
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
+ break;
+ case EBUSY:
+ default:
+ break;
+ }
+
+ return bRet;
+}
+
+void ca_mutex_unlock(ca_mutex mutex) {
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
+ if (mutexInfo) {
+ int ret = pthread_mutex_unlock(&mutexInfo->mutex);
+ assert(0 == ret);
+ (void) ret;
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
+ return;
+ }
+}
+
+ca_cond ca_cond_new(void) {
+ ca_cond retVal = NULL;
+ ca_cond_internal *eventInfo = (ca_cond_internal*) OICMalloc(
+ sizeof(ca_cond_internal));
+ if (NULL != eventInfo) {
+ int ret = pthread_condattr_init(&(eventInfo->condattr));
+ if (0 != ret) {
+ OIC_LOG_V(ERROR, TAG,
+ "%s: Failed to initialize condition variable attribute %d!",
+ __func__, ret);
+ return retVal;
+ }
+
+#if defined(__ANDROID__) || _POSIX_TIMERS > 0
+ ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
+
+ if(0 != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!",
+ __func__, ret);
+ return retVal;
+ }
+#endif
+ ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr));
+ if (0 == ret) {
+ retVal = (ca_cond) eventInfo;
+ } else {
+ OIC_LOG_V(ERROR, TAG,
+ "%s: Failed to initialize condition variable %d!", __func__,
+ ret);
+ OICFree(eventInfo);
+ }
+ }
+
+ return retVal;
+}
+
+void ca_cond_free(ca_cond cond) {
+ ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
+ if (eventInfo != NULL) {
+ int ret = pthread_cond_destroy(&(eventInfo->cond));
+ int ret2 = pthread_condattr_destroy(&(eventInfo->condattr));
+ if (0 == ret && 0 == ret2) {
+ OICFree(cond);
+ } else {
+ OIC_LOG_V(ERROR, TAG,
+ "%s: Failed to destroy condition variable %d, %d", __func__,
+ ret, ret2);
+ }
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
+ }
+}
+
+void ca_cond_signal(ca_cond cond) {
+ ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
+ if (eventInfo != NULL) {
+ int ret = pthread_cond_signal(&(eventInfo->cond));
+ if (0 != ret) {
+ OIC_LOG_V(ERROR, TAG, "%s: Failed to signal condition variable",
+ __func__);
+ }
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
+ }
+}
+
+void ca_cond_broadcast(ca_cond cond) {
+ ca_cond_internal* eventInfo = (ca_cond_internal*) cond;
+ if (eventInfo != NULL) {
+ int ret = pthread_cond_broadcast(&(eventInfo->cond));
+ if (0 != ret) {
+ OIC_LOG_V(ERROR, TAG, "%s: failed to signal condition variable",
+ __func__);
+ }
+ } else {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
+ }
+}
+
+void ca_cond_wait(ca_cond cond, ca_mutex mutex) {
+ ca_cond_wait_for(cond, mutex, 0L);
+}
+
+struct timespec ca_get_current_time() {
+#if defined(__ANDROID__) || _POSIX_TIMERS > 0
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ return ts;
+#endif
+}
+
+void ca_add_microseconds_to_timespec(struct timespec* ts,
+ uint64_t microseconds) {
+ time_t secPart = microseconds / USECS_PER_SEC;
+ uint64_t nsecPart = (microseconds % USECS_PER_SEC) * NANOSECS_PER_USECS;
+ uint64_t totalNs = ts->tv_nsec + nsecPart;
+ time_t secOfNs = totalNs / NANOSECS_PER_SEC;
+
+ ts->tv_nsec = (totalNs) % NANOSECS_PER_SEC;
+ ts->tv_sec += secPart + secOfNs;
+}
+
+CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex,
+ uint64_t microseconds) {
+ CAWaitResult_t retVal = CA_WAIT_INVAL;
+
+ ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
+ ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
+
+ if (NULL == mutexInfo) {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
+ return CA_WAIT_INVAL;
+ }
+
+ if (NULL == eventInfo) {
+ OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
+ return CA_WAIT_INVAL;
+ }
+
+ if (microseconds > 0) {
+ struct timespec abstime = ca_get_current_time();
+ ca_add_microseconds_to_timespec(&abstime, microseconds);
+
+ //Wait for the given time
+ int ret = pthread_cond_timedwait(&(eventInfo->cond),
+ &(mutexInfo->mutex), &abstime);
+ switch (ret) {
+ case 0:
+ // Success
+ retVal = CA_WAIT_SUCCESS;
+ break;
+ case ETIMEDOUT:
+ retVal = CA_WAIT_TIMEDOUT;
+ break;
+ case EINVAL:
+ OIC_LOG_V(ERROR, TAG, "%s: condition, mutex, or abstime is Invalid",
+ __func__);
+ retVal = CA_WAIT_INVAL;
+ break;
+ default:
+ OIC_LOG_V(ERROR, TAG, "%s: pthread_cond_timedwait returned %d",
+ __func__, retVal);
+ retVal = CA_WAIT_INVAL;
+ break;
+ }
+ } else {
+ // Wait forever
+ int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
+ retVal = ret == 0 ? CA_WAIT_SUCCESS : CA_WAIT_INVAL;
+ }
+
+ return retVal;
+}
+
--- /dev/null
- ProvisioningInfo provInfo;
+//******************************************************************
+//
+// Copyright 2015 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "provisioninghandler.h"
+
+// External includes
+#include "cJSON.h"
+#include "camutex.h"
+#include "cathreadpool.h"
+#include "logger.h"
+#include "oic_malloc.h"
+
+
+/**
+ * @var g_provisioningMutex
+ * @brief Mutex to synchronize access to g_caDtlsContext.
+ */
+static ca_mutex g_provisioningMutex = NULL;
+static ca_cond g_provisioningCond = NULL;
+bool g_provisioningCondFlag = false;
+
+static EnrolleeNWProvInfo_t* netProvInfo;
+
+/**
+ * @var cbData
+ * @brief Callback for providing provisioning status callback to application
+ */
+static OCProvisioningStatusCB cbData = NULL;
+static ca_thread_pool_t g_threadPoolHandle = NULL;
+
+OCStackResult InitProvisioningHandler() {
+ OCStackResult ret = OC_STACK_ERROR;
+ /* Initialize OCStack*/
+ if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack init error");
+ return ret;
+ }
+
+ g_provisioningMutex = ca_mutex_new();
+
+ OIC_LOG(DEBUG, TAG, "ca_thread_pool_init initializing");
+
+ if (CA_STATUS_OK != ca_thread_pool_init(2, &g_threadPoolHandle)) {
+ OIC_LOG(DEBUG, TAG, "thread_pool_init failed");
+ return OC_STACK_ERROR;
+ }
+
+ g_provisioningCond = ca_cond_new();
+ if (NULL == g_provisioningCond) {
+ OIC_LOG(DEBUG, TAG, "Failed to create condition");
+ ca_mutex_free(g_provisioningMutex);
+ ca_thread_pool_free(g_threadPoolHandle);
+ return OC_STACK_ERROR;
+ }
+
+ char *string = "listeningFunc invoked in a thread";
+ if (CA_STATUS_OK
+ != ca_thread_pool_add_task(g_threadPoolHandle, listeningFunc,
+ (void *) string)) {
+ OIC_LOG(DEBUG, TAG, "thread_pool_add_task failed");
+ ca_thread_pool_free(g_threadPoolHandle);
+ ca_mutex_unlock(g_provisioningMutex);
+ ca_mutex_free(g_provisioningMutex);
+ ca_cond_free(g_provisioningCond);
+ return OC_STACK_ERROR;
+ }
+ return OC_STACK_OK;
+}
+
+OCStackResult TerminateProvisioningHandler() {
+ OCStackResult ret = OC_STACK_ERROR;
+ if (OCStop() != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ ca_mutex_lock(g_provisioningMutex);
+ g_provisioningCondFlag = true;
+ //ca_cond_signal(g_provisioningCond);
+ ca_mutex_unlock(g_provisioningMutex);
+
+ ca_mutex_free(g_provisioningMutex);
+ g_provisioningMutex = NULL;
+
+ ca_thread_pool_free(g_threadPoolHandle);
+ g_threadPoolHandle = NULL;
+
+ ret = OC_STACK_OK;
+ return ret;
+}
+
+void listeningFunc(void *data) {
+ while (!g_provisioningCondFlag) {
+ OCStackResult result;
+
+ ca_mutex_lock(g_provisioningMutex);
+ result = OCProcess();
+ ca_mutex_unlock(g_provisioningMutex);
+
+ if (result != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ // To minimize CPU utilization we may wish to do this with sleep
+ sleep(1);
+ }
+}
+
+OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse) {
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ ProvisioningInfo *provInfo;
+
+ if (clientResponse) {
+ OIC_LOG_V(INFO, TAG, "Put Response JSON = %s",
+ clientResponse->resJSONPayload);
+ } else {
+ OIC_LOG_V(INFO, TAG,
+ "ProvisionEnrolleeResponse received Null clientResponse");
- uint16_t remotePortNum;
-
- OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNum);
-
- char sourceaddr[OIC_STRING_MAX_VALUE] = { '\0' };
- snprintf(sourceaddr, sizeof(sourceaddr), "%d.%d.%d.%d:%d%s",
- clientResponse->addr->addr[0], clientResponse->addr->addr[1],
- clientResponse->addr->addr[2], clientResponse->addr->addr[3],
- remotePortNum, OIC_PROVISIONING_URI);
-
- OIC_LOG_V(DEBUG, TAG, "ProvisionEnrolleeResponse %s @ %s",
- clientResponse->resJSONPayload, sourceaddr);
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
- cJSON *ocArray = cJSON_GetObjectItem(observeJson, "oic");
++ OIC_LOG_V(DEBUG, TAG, "ProvisionEnrolleeResponse %s ",
++ clientResponse->resJSONPayload);
+
+ if (clientResponse->resJSONPayload) {
+ cJSON *observeJson = cJSON_CreateObject();
+ observeJson = cJSON_Parse(clientResponse->resJSONPayload);
+
- cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, "rep");
++ cJSON *ocArray = cJSON_GetObjectItem(observeJson, OC_RSRVD_OC);
+ cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
+
- OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %d", i,
++ cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_REPRESENTATION);
+ char *ocArray_str = cJSON_PrintUnformatted(representationArray);
+
+ if (strstr(ocArray_str, "[{}") == ocArray_str) {
+ OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
+ cJSON_Delete(observeJson);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ int countofrep = cJSON_GetArraySize(representationArray);
+
+ for (int i = 0; i < countofrep; ++i) {
+ cJSON *arrayJSON = cJSON_GetArrayItem(representationArray, i);
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's name : %s", i, arrayJSON->string);
+
++ if (!strcmp(arrayJSON->string, OC_RSRVD_ES_PS))
++ {
++ if(arrayJSON->valueint == 1)
++ {
++ OIC_LOG_V(DEBUG, TAG, "PS is proper");
++ continue;
++ }
++ else{
++ OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
++ DEVICE_NOT_PROVISIONED);
++ cbData(provInfo);
++ }
++ }
++
++ if (!strcmp(arrayJSON->string, OC_RSRVD_ES_TNN))
++ {
++ if(!strcmp(arrayJSON->valuestring, netProvInfo->netAddressInfo.WIFI.ssid))
++ {
++ OIC_LOG_V(DEBUG, TAG, "SSID is proper");
++ continue;
++ }
++ else{
++ OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
++ DEVICE_NOT_PROVISIONED);
++ cbData(provInfo);
++ }
++ }
++
++ if (!strcmp(arrayJSON->string, OC_RSRVD_ES_CD))
++ {
++ if(!strcmp(arrayJSON->valuestring, netProvInfo->netAddressInfo.WIFI.pwd))
++ {
++ OIC_LOG_V(DEBUG, TAG, "Password is proper");
++ continue;
++ }
++ else{
++ OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
++ DEVICE_NOT_PROVISIONED);
++ cbData(provInfo);
++ }
++ }
++
+ switch (arrayJSON->type) {
+ case cJSON_False:
+ case cJSON_True:
- OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %f", i,
++ OIC_LOG_V(DEBUG, TAG, "rep#%d's int value : %d", i,
+ arrayJSON->valueint);
+ break;
+ case cJSON_Number:
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ OIC_LOG_V(DEBUG, TAG, "rep#%d's double value : %f", i,
+ arrayJSON->valuedouble);
+ break;
+ case cJSON_String:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %s", i,
+ arrayJSON->valuestring);
+ break;
+ case cJSON_NULL:
+ default:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : NULL", i);
+ break;
+ }
+ }
+
+ cJSON_Delete(observeJson);
+
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_PROVISIONED);
+ cbData(provInfo);
+
+ return OC_STACK_KEEP_TRANSACTION;
+ } else {
+ OIC_LOG(INFO, TAG,
+ "ProvisionEnrolleeResponse received NULL clientResponse. \
+ Invoking Provisioing Status Callback");
- OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query) {
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+}
+
- char nodeData[OIC_STRING_MAX_VALUE] = { '\0' };
- snprintf(nodeData, sizeof(nodeData), "%s", OIC_PROVISIONING_URI);
-
- cJSON_AddStringToObject(json, "href", nodeData);
- cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
- cJSON_AddStringToObject(format, "tnn", netProvInfo->netAddressInfo.WIFI.ssid);
- cJSON_AddStringToObject(format, "cd", netProvInfo->netAddressInfo.WIFI.pwd);
- cJSON_AddItemToObject(jsonFinal, "oic", jsonArray = cJSON_CreateArray());
++OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri) {
+ OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);
+
+ cJSON *jsonFinal = cJSON_CreateObject();
+ cJSON *json = cJSON_CreateObject();
+ cJSON *jsonArray;
+ cJSON *format;
+ char* payload = NULL;
+
- ProvisioningInfo provInfo;
++ cJSON_AddStringToObject(json, OC_RSRVD_HREF, resUri);
++ cJSON_AddItemToObject(json, OC_RSRVD_REPRESENTATION, format = cJSON_CreateObject());
++ cJSON_AddStringToObject(format, OC_RSRVD_ES_TNN, netProvInfo->netAddressInfo.WIFI.ssid);
++ cJSON_AddStringToObject(format, OC_RSRVD_ES_CD, netProvInfo->netAddressInfo.WIFI.pwd);
++ cJSON_AddItemToObject(jsonFinal, OC_RSRVD_OC, jsonArray = cJSON_CreateArray());
+ cJSON_AddItemToArray(jsonArray, json);
+
+ OIC_LOG_V(DEBUG, TAG, "ProvisionEnrollee : %s",
+ cJSON_PrintUnformatted(jsonFinal));
+ payload = cJSON_Print(jsonFinal);
+ OIC_LOG_V(DEBUG, TAG, "Payload : %s", payload);
+
+ OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, OC_HIGH_QOS,
+ ProvisionEnrolleeResponse, payload, NULL, 0);
+
+ cJSON_Delete(json);
+ return ret;
+}
+
+OCStackApplicationResult GetProvisioningStatusResponse(void* ctx,
+ OCDoHandle handle, OCClientResponse * clientResponse) {
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ ProvisioningInfo *provInfo;
+
+ if (clientResponse == NULL) {
+ OIC_LOG(INFO, TAG,
+ "getReqCB received NULL clientResponse. \
+ Invoking Provisioing Status Callback");
- char sourceaddr[OIC_STRING_MAX_VALUE] = { '\0' };
- snprintf(sourceaddr, sizeof(sourceaddr), "%d.%d.%d.%d:%d%s",
- clientResponse->addr->addr[0], clientResponse->addr->addr[1],
- clientResponse->addr->addr[2], clientResponse->addr->addr[3],
- 6298, OIC_PROVISIONING_URI);
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (clientResponse->rcvdVendorSpecificHeaderOptions
+ && clientResponse->numRcvdVendorSpecificHeaderOptions) {
+ OIC_LOG(INFO, TAG, "Received vendor specific options");
+ uint8_t i = 0;
+ OCHeaderOption * rcvdOptions =
+ clientResponse->rcvdVendorSpecificHeaderOptions;
+ for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;
+ i++) {
+ if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID) {
+ OIC_LOG_V(INFO, TAG,
+ "Received option with OC_COAP_ID and ID %u with",
+ ((OCHeaderOption) rcvdOptions[i]).optionID);
+
+ OIC_LOG_BUFFER(INFO, TAG,
+ ((OCHeaderOption) rcvdOptions[i]).optionData,
+ MAX_HEADER_OPTION_DATA_LENGTH);
+ }
+ }
+ }
+
- cJSON *ocArray = cJSON_GetObjectItem(observeJson, "oic");
++ char query[OIC_STRING_MAX_VALUE] = { '\0' };
++
+
+ if (clientResponse->resJSONPayload) {
+ cJSON *observeJson = cJSON_CreateObject();
+ observeJson = cJSON_Parse(clientResponse->resJSONPayload);
+
- cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, "rep");
++ cJSON *ocArray = cJSON_GetObjectItem(observeJson, OC_RSRVD_OC);
+ cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
+
- if (ProvisionEnrollee(OC_HIGH_QOS, sourceaddr) != OC_STACK_OK) {
++ cJSON *resUriObj = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_HREF);
++
++ OIC_LOG_V(DEBUG, TAG, "resUriObj = %s, valueString = %s",
++ resUriObj->string, resUriObj->valuestring);
++
++ char resURI[MAX_URI_LENGTH]={'\0'};
++
++ strncpy(resURI, resUriObj->valuestring, sizeof(resURI));
++
++ snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY,
++ clientResponse->addr->addr,
++ IP_PORT, resURI);
++
++ cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_REPRESENTATION);
+ char *ocArray_str = cJSON_PrintUnformatted(representationArray);
+
+ if (strstr(ocArray_str, "[{}") == ocArray_str) {
+ OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
+ cJSON_Delete(observeJson);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ int countofrep = cJSON_GetArraySize(representationArray);
+
+ for (int i = 0; i < countofrep; ++i) {
+ cJSON *arrayJSON = cJSON_GetArrayItem(representationArray, i);
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's name : %s", i, arrayJSON->string);
+
+ switch (arrayJSON->type) {
+ case cJSON_False:
+ case cJSON_True:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %d", i,
+ arrayJSON->valueint);
+ break;
+ case cJSON_Number:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %f", i,
+ arrayJSON->valuedouble);
+ break;
+ case cJSON_String:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %s", i,
+ arrayJSON->valuestring);
+ break;
+ case cJSON_NULL:
+ default:
+ OIC_LOG_V(DEBUG, TAG, "rep#%d's value : NULL", i);
+ break;
+ }
+ }
+ cJSON_Delete(observeJson);
+
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ if (ProvisionEnrollee(OC_HIGH_QOS, query, resURI) != OC_STACK_OK) {
+ OIC_LOG(INFO, TAG,
+ "GetProvisioningStatusResponse received NULL clientResponse. \
+ Invoking Provisioing Status Callback");
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ } else {
+ OIC_LOG(INFO, TAG,
+ "GetProvisioningStatusResponse received NULL clientResponse. \
+ Invoking Provisioing Status Callback");
- ProvisioningInfo provInfo;
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult InvokeOCDoResource(const char* query, OCMethod method,
+ OCQualityOfService qos, OCClientResponseHandler cb, const char* request,
+ OCHeaderOption * options, uint8_t numOptions) {
+ OCStackResult ret;
+ OCCallbackData cbData;
+
+ cbData.cb = cb;
+ cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ ret = OCDoResource(NULL, method, query, 0, request, OC_CONNTYPE, qos,
+ &cbData, options, numOptions);
+
+ if (ret != OC_STACK_OK) {
+ OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d",
+ ret, method);
+ }
+
+ return ret;
+}
+
+OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query) {
+ OCStackResult ret = OC_STACK_ERROR;
+ OCHeaderOption options[MAX_HEADER_OPTIONS];
+
+ OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+
+ uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
+ memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
+ options[0].protocolID = OC_COAP_ID;
+ options[0].optionID = 2048;
+ memcpy(options[0].optionData, option0, sizeof(option0));
+ options[0].optionLength = 10;
+ options[1].protocolID = OC_COAP_ID;
+ options[1].optionID = 3000;
+ memcpy(options[1].optionData, option1, sizeof(option1));
+ options[1].optionLength = 10;
+
+ ret = InvokeOCDoResource(query, OC_REST_GET, OC_HIGH_QOS,
+ GetProvisioningStatusResponse, NULL, options, 2);
+ return ret;
+}
+
+OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,
+ OCProvisioningStatusCB provisioningStatusCallback) {
+ OCStackResult result = OC_STACK_ERROR;
- /* Start a discovery query*/
- char szQueryUri[64] = { 0 };
-
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
- netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);
-
- OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);
-
- if (FindProvisioningResource(OC_HIGH_QOS, szQueryUri) != OC_STACK_OK) {
- OIC_LOG(ERROR, TAG,
- "FindProvisioningResource failed. \
- Invoking Provisioing Status Callback");
-
- ProvDeviceInfo provDeviceIndo;
- OCDevAddr dst = { };
+
+ if (netInfo->netAddressInfo.WIFI.ipAddress == NULL) {
+ OIC_LOG(ERROR, TAG, "Request URI is NULL");
+ return result;
+ }
+
+ if (provisioningStatusCallback == NULL) {
+ OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");
+ return result;
+ }
+
+ cbData = provisioningStatusCallback;
+
+ //Copy Network Provisioning Information
+ netProvInfo = (EnrolleeNWProvInfo_t *)OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));
+
+ if (NULL == netProvInfo)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid input..");
+ return OC_STACK_ERROR;
+ }
+ memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));
+
+ OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",
+ netProvInfo->netAddressInfo.WIFI.ssid);
+
+ OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",
+ netProvInfo->netAddressInfo.WIFI.pwd);
+
- dst.addr[0] = netProvInfo->netAddressInfo.WIFI.ipAddress[0];
- dst.addr[1] = netProvInfo->netAddressInfo.WIFI.ipAddress[1];
- dst.addr[2] = netProvInfo->netAddressInfo.WIFI.ipAddress[2];
- dst.addr[3] = netProvInfo->netAddressInfo.WIFI.ipAddress[3];
- dst.addr[4] = (uint8_t) IP_PORT;
- dst.addr[5] = (uint8_t)(IP_PORT >> 8);
-
- provInfo.provStatus = DEVICE_NOT_PROVISIONED;
- provDeviceIndo.addr = &dst;
- provDeviceIndo.connType = OC_IPV4;
- provInfo.provDeviceInfo = provDeviceIndo;
-
- cbData(provInfo);
- return result;
+
- result = OC_STACK_OK;
-
- return result;
++ if (CA_STATUS_OK
++ != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,
++ (void *) "")) {
++ OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");
++ ca_thread_pool_free(g_threadPoolHandle);
++ ca_mutex_unlock(g_provisioningMutex);
++ ca_mutex_free(g_provisioningMutex);
++ ca_cond_free(g_provisioningCond);
++ return OC_STACK_ERROR;
+ }
- ProvisioningInfo provInfo;
++ return OC_STACK_OK;
+}
+
+void StopProvisioningProcess() {
+ cbData = NULL;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult FindProvisioningResourceResponse(void* ctx,
+ OCDoHandle handle, OCClientResponse * clientResponse) {
+ OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));
+
+ OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
+
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ ProvisioningInfo *provInfo;
+
+ if (clientResponse->result != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG,
+ "OCStack stop error. Calling Provisioing Status Callback");
+
- // Parse header options from server
- uint16_t optionID;
- uint8_t* optionData;
- const char* payload;
-
- for (int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;
- i++) {
- optionID =
- clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
- optionData =
- clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData;
- payload = clientResponse->resJSONPayload;
- }
-
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+
+ cbData(provInfo);
+ return response;
+ }
+
+ if (clientResponse) {
- cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, "oic");
+ cJSON *discoveryJson = cJSON_CreateObject();
+ discoveryJson = cJSON_Parse((char *) clientResponse->resJSONPayload);
+
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++ cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, OC_RSRVD_OC);
+ char *ocArray_str = cJSON_PrintUnformatted(ocArray);
+
+ if (strstr(ocArray_str, "[{}") == ocArray_str) {
+ OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
+ cJSON_Delete(discoveryJson);
+
- char sourceaddr[OIC_STRING_MAX_VALUE] = { '\0' };
- snprintf(sourceaddr, sizeof(sourceaddr), "%d.%d.%d.%d:%d%s",
- clientResponse->addr->addr[0], clientResponse->addr->addr[1],
- clientResponse->addr->addr[2], clientResponse->addr->addr[3],
- IP_PORT, OIC_PROVISIONING_URI);
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return response;
+ }
+
- OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s",
- clientResponse->resJSONPayload, sourceaddr);
++ cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
++ cJSON *resUriObj = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_HREF);
+
- if (GetProvisioningStatus(OC_HIGH_QOS, sourceaddr) != OC_STACK_OK) {
++ OIC_LOG_V(DEBUG, TAG, "resUriObj = %s, valueString = %s",
++ resUriObj->string, resUriObj->valuestring);
+
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
++
++ char szQueryUri[64] = { 0 };
++
++ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
++ clientResponse->devAddr.addr, IP_PORT, resUriObj->valuestring);
++ OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);
++
++ if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri) != OC_STACK_OK) {
+ OIC_LOG(INFO, TAG,
+ "GetProvisioningStatus returned error. \
+ Invoking Provisioing Status Callback");
- cbData(provInfo);
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
- PrepareProvisioingStatusCB(&provInfo, clientResponse,
+
++ cbData(provInfo);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ } else {
+ // clientResponse is invalid
+ OIC_LOG(ERROR, TAG,
+ "Invalid response for Provisioning Discovery request. \
+ Invoking Provisioing Status Callback");
- OCStackResult FindProvisioningResource(OCQualityOfService qos,
- const char* requestURI) {
++ provInfo = PrepareProvisioingStatusCB(clientResponse,
+ DEVICE_NOT_PROVISIONED);
+ cbData(provInfo);
+ return response;
+ }
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
- OCCallbackData cbData;
++void FindProvisioningResource(void *data)
++{
+ OCStackResult ret = OC_STACK_ERROR;
+
- cbData.cb = FindProvisioningResourceResponse;
- cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
- cbData.cd = NULL;
++ /* Start a discovery query*/
++ char szQueryUri[64] = { 0 };
+
- ret = OCDoResource(NULL, OC_REST_GET, requestURI, 0, 0, OC_CONNTYPE,
- OC_LOW_QOS, &cbData, NULL, 0);
++ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
++ netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);
+
- }
++ OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);
++
++ OCCallbackData ocCBData;
++
++ ocCBData.cb = FindProvisioningResourceResponse;
++ ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;
++ ocCBData.cd = NULL;
++
++ ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
++ OC_LOW_QOS, &ocCBData, NULL, 0);
+
+ if (ret != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
- return ret;
+
- // Parse header options from server
- uint16_t optionID;
- uint8_t* optionData;
- const char* payload;
-
- for (int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;
- i++) {
- optionID =
- clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
- optionData =
- clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData;
- payload = clientResponse->resJSONPayload;
- }
++ OIC_LOG(ERROR, TAG,
++ "FindProvisioningResource failed. \
++ Invoking Provisioing Status Callback");
++
++ ProvisioningInfo *provInfo;
++ provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
++
++ if(provInfo == NULL)
++ {
++ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
++ return;
++ }
++
++ OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
++
++ if(devAddr == NULL)
++ {
++ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
++ return;
++ }
++
++ strncpy(devAddr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress, sizeof(devAddr->addr));
++ devAddr->port= IP_PORT;
++ provInfo->provDeviceInfo.addr = devAddr;
++ provInfo->provStatus = DEVICE_NOT_PROVISIONED;
++
++
++ cbData(provInfo);
++ }
+}
+
+OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse* clientResponse) {
+ OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));
+
+ OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
+
+ if (clientResponse->result != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ return response;
+ }
+
+ if (clientResponse) {
+ OIC_LOG(INFO, TAG, PCF("Client Response exists"));
- cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, "oic");
+
+ cJSON *discoveryJson = cJSON_CreateObject();
+ discoveryJson = cJSON_Parse((char *) clientResponse->resJSONPayload);
+
- snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%d.%d.%d.%d",
- clientResponse->addr->addr[0], clientResponse->addr->addr[1],
- clientResponse->addr->addr[2], clientResponse->addr->addr[3]);
++ cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, OC_RSRVD_OC);
+ char *ocArray_str = cJSON_PrintUnformatted(ocArray);
+
+ if (strstr(ocArray_str, "[{}") == ocArray_str) {
+ OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
+ cJSON_Delete(discoveryJson);
+ return response;
+ }
+
+ char sourceIPAddr[OIC_STRING_MAX_VALUE] = { '\0' };
- OCQualityOfService qos = OC_NA_QOS;
++ snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);
+
+ OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s",
+ clientResponse->resJSONPayload, sourceIPAddr);
+
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
- if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {
+
+ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
+ sourceIPAddr, IP_PORT);
+
- }
++ /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");
+ return OC_STACK_KEEP_TRANSACTION;
- void PrepareProvisioingStatusCB(ProvisioningInfo *provInfo,
- OCClientResponse * clientResponse, ProvStatus provStatus) {
- ProvDeviceInfo provDeviceIndo;
- OCDevAddr dst = { };
++ }*/
+ } else {
+ // clientResponse is invalid
+ OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));
+ }
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
+OCStackResult SubscribeProvPresence(OCQualityOfService qos,
+ const char* requestURI) {
+ OCStackResult ret = OC_STACK_ERROR;
+
+ OCCallbackData cbData;
+
+ cbData.cb = &SubscribeProvPresenceCallback;
+ cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE,
+ OC_LOW_QOS, &cbData, NULL, 0);
+
+ if (ret != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ return ret;
+}
+
+OCStackResult FindNetworkResource() {
+ OCStackResult ret = OC_STACK_ERROR;
+ if (OCStop() != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ return ret;
+}
+
- uint16_t remotePortNum;
- OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNum);
++ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse, ProvStatus provStatus) {
+
- dst.addr[0] = clientResponse->addr->addr[0];
- dst.addr[1] = clientResponse->addr->addr[1];
- dst.addr[2] = clientResponse->addr->addr[2];
- dst.addr[3] = clientResponse->addr->addr[3];
- dst.addr[4] = (uint8_t) remotePortNum;
- dst.addr[5] = (uint8_t)(remotePortNum >> 8);
++ ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
+
- provInfo->provStatus = provStatus;
++ if(provInfo == NULL)
++ {
++ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
++ return NULL;
++ }
+
- provDeviceIndo.addr = &dst;
- provDeviceIndo.connType = OC_IPV4;
++ OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
+
- provInfo->provDeviceInfo = provDeviceIndo;
++ if(devAddr == NULL)
++ {
++ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
++ return NULL;
++ }
++
++ strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));
++ devAddr->port= clientResponse->addr->port;
++
++ provInfo->provDeviceInfo.addr = devAddr;
++
++ provInfo->provStatus = provStatus;
+
++ return provInfo;
+}
+